From 495c0e996ad9e2278089ed24ca8906bac6effc8b Mon Sep 17 00:00:00 2001 From: Snir Broshi Date: Fri, 19 Feb 2021 18:32:57 +0200 Subject: [PATCH 01/36] fix cursor position when at the start of RTL syntax tokens --- src/vs/editor/browser/viewParts/lines/rangeUtil.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/browser/viewParts/lines/rangeUtil.ts b/src/vs/editor/browser/viewParts/lines/rangeUtil.ts index 7718ae4003a..56875381773 100644 --- a/src/vs/editor/browser/viewParts/lines/rangeUtil.ts +++ b/src/vs/editor/browser/viewParts/lines/rangeUtil.ts @@ -121,9 +121,9 @@ export class RangeUtil { startChildIndex = Math.min(max, Math.max(min, startChildIndex)); endChildIndex = Math.min(max, Math.max(min, endChildIndex)); - if (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0) { + if (startChildIndex === endChildIndex && startOffset === endOffset && startOffset === 0 && !domNode.children[startChildIndex].firstChild) { // We must find the position at the beginning of a - // To cover cases of empty s, aboid using a range and use the 's bounding box + // To cover cases of empty s, avoid using a range and use the 's bounding box const clientRects = domNode.children[startChildIndex].getClientRects(); return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft); } From e22c2be14d1381faed2934db143dc2f52a6a2605 Mon Sep 17 00:00:00 2001 From: soredake <5204968+soredake@users.noreply.github.com> Date: Mon, 8 Mar 2021 17:23:35 +0200 Subject: [PATCH 02/36] snap: set compression to lzo, #117852 (#118116) --- resources/linux/snap/snapcraft.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/linux/snap/snapcraft.yaml b/resources/linux/snap/snapcraft.yaml index c24d0af3ea7..71eff238e12 100644 --- a/resources/linux/snap/snapcraft.yaml +++ b/resources/linux/snap/snapcraft.yaml @@ -9,6 +9,7 @@ description: | architectures: - build-on: amd64 run-on: @@ARCHITECTURE@@ +compression: lzo grade: stable confinement: classic From 1469a82540f499533310e5f972b4340c873ae758 Mon Sep 17 00:00:00 2001 From: isidor Date: Mon, 8 Mar 2021 16:42:20 +0100 Subject: [PATCH 03/36] fixes #118006 --- src/vs/workbench/contrib/debug/browser/repl.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts index 8ae3c2eb16e..0bc759b8caf 100644 --- a/src/vs/workbench/contrib/debug/browser/repl.ts +++ b/src/vs/workbench/contrib/debug/browser/repl.ts @@ -852,14 +852,12 @@ registerAction2(class extends ViewAction { const stopppedChildSession = debugService.getModel().getSessions().find(s => s.parentSession === session && s.state === State.Stopped); if (stopppedChildSession) { session = stopppedChildSession; - } else { - await view.selectSession(session); } } await debugService.focusStackFrame(undefined, undefined, session, true); - } else { - await view.selectSession(session); } + // Need to select the session in the view since the focussed session might not have changed + await view.selectSession(session); } }); From 3df01b4ae74ff60460e2deaa0a50bb85c2060abd Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 8 Mar 2021 08:30:57 -0800 Subject: [PATCH 04/36] Include ms in shutdown constant comments Part of microsoft/vscode#118437 --- src/vs/platform/terminal/node/terminalProcess.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index 984a9561c83..e26fb834502 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -27,7 +27,7 @@ const WRITE_INTERVAL_MS = 5; const enum ShutdownConstants { /** - * The amount of time that must pass between data events after exit is queued before the actual + * The amount of ms that must pass between data events after exit is queued before the actual * kill call is triggered. This data flush mechanism works around an [issue in node-pty][1] * where not all data is flushed which causes problems for task problem matchers. Additionally * on Windows under conpty, killing a process while data is being output will cause the [conhost @@ -39,7 +39,7 @@ const enum ShutdownConstants { */ DataFlushTimeout = 250, /** - * The maximum time to allow after dispose is called because forcefully killing the process. + * The maximum ms to allow after dispose is called because forcefully killing the process. */ MaximumShutdownTime = 5000 } From 78cb4cfc32b9f35e484cce1216897e74b8f3f50a Mon Sep 17 00:00:00 2001 From: Andre Weinand Date: Thu, 4 Mar 2021 18:03:33 +0100 Subject: [PATCH 05/36] improved comment for InlineValueContext.frameId --- 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 91c1d4fadb4..fc6dd15a2df 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -700,7 +700,7 @@ declare module 'vscode' { export interface InlineValueContext { /** - * Debug Adapter Protocol ID of the the stack frame. + * The stack frame (as a DAP Id) where the execution has stopped. */ readonly frameId: number; From 820f0eeb270422b2c679b6bca10de3cb5c474e1c Mon Sep 17 00:00:00 2001 From: Stefan Petrescu Date: Mon, 8 Mar 2021 20:44:26 +0200 Subject: [PATCH 06/36] Fix tooltip not showing for codelens extension --- src/vs/editor/contrib/codelens/codelensWidget.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/codelens/codelensWidget.ts b/src/vs/editor/contrib/codelens/codelensWidget.ts index 9014c904a2a..918d6b64632 100644 --- a/src/vs/editor/contrib/codelens/codelensWidget.ts +++ b/src/vs/editor/contrib/codelens/codelensWidget.ts @@ -90,10 +90,10 @@ class CodeLensContentWidget implements IContentWidget { if (lens.command) { const title = renderLabelWithIcons(lens.command.title.trim()); if (lens.command.id) { - children.push(dom.$('a', { id: String(i) }, ...title)); + children.push(dom.$('a', { id: String(i), title: lens.command.tooltip }, ...title)); this._commands.set(String(i), lens.command); } else { - children.push(dom.$('span', undefined, ...title)); + children.push(dom.$('span', { title: lens.command.tooltip }, ...title)); } if (i + 1 < lenses.length) { children.push(dom.$('span', undefined, '\u00a0|\u00a0')); From 584999658ee7e5e7b632b7013894534f8ddb2432 Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 8 Mar 2021 11:02:10 -0800 Subject: [PATCH 07/36] Bug --- .../src/singlefolder-tests/notebook.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index 9f75f92f43f..6fb9c7bea18 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -1240,6 +1240,12 @@ suite('Notebook API tests', function () { assert.strictEqual(document.cells[0].metadata.executionOrder, executionOrder); assert.strictEqual(document.cells[0].metadata.runState, vscode.NotebookCellRunState.Success); }); + test.only('Opening a notebook should fire activeNotebook event changed only once', async function () { + const openedEditor = asPromise(vscode.window.onDidChangeActiveNotebookEditor); + const resource = await createRandomFile('', undefined, '.vsctestnb'); + await vscode.notebook.openNotebookDocument(resource); + assert.ok(await openedEditor); + }); // }); From a39e7343653069261c610bb4c5274a789ce3727b Mon Sep 17 00:00:00 2001 From: Don Jayamanne Date: Mon, 8 Mar 2021 11:05:28 -0800 Subject: [PATCH 08/36] Oops --- .../vscode-api-tests/src/singlefolder-tests/notebook.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index 6fb9c7bea18..06458587116 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -1240,7 +1240,7 @@ suite('Notebook API tests', function () { assert.strictEqual(document.cells[0].metadata.executionOrder, executionOrder); assert.strictEqual(document.cells[0].metadata.runState, vscode.NotebookCellRunState.Success); }); - test.only('Opening a notebook should fire activeNotebook event changed only once', async function () { + test('Opening a notebook should fire activeNotebook event changed only once', async function () { const openedEditor = asPromise(vscode.window.onDidChangeActiveNotebookEditor); const resource = await createRandomFile('', undefined, '.vsctestnb'); await vscode.notebook.openNotebookDocument(resource); From 7e6d4c5eb9167f956ffee4e01e77304da739cd95 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 8 Mar 2021 11:32:09 -0800 Subject: [PATCH 09/36] debug: fill in selected configuration by name if not provided Fixes #118472 --- .../contrib/debug/browser/debugConfigurationManager.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts index d26321962a5..380bda0cdb3 100644 --- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts @@ -374,6 +374,10 @@ export class ConfigurationManager implements IConfigurationManager { let type = config?.type; if (name && names.indexOf(name) >= 0) { this.setSelectedLaunchName(name); + if (!config && name && launch) { + config = launch.getConfiguration(name); + type = config?.type; + } } else if (dynamicConfig && dynamicConfig.type) { // We could not find the previously used name and config is not passed. We should get all dynamic configurations from providers // And potentially auto select the previously used dynamic configuration #96293 From b6b9aa15ef6238e0df27bac823011311ab1b3041 Mon Sep 17 00:00:00 2001 From: Connor Peet Date: Mon, 8 Mar 2021 11:46:02 -0800 Subject: [PATCH 10/36] debug: allow passing partial config to start debugging command --- src/vs/workbench/contrib/debug/browser/debugCommands.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/debug/browser/debugCommands.ts b/src/vs/workbench/contrib/debug/browser/debugCommands.ts index 8aef4812c8c..e86421e0896 100644 --- a/src/vs/workbench/contrib/debug/browser/debugCommands.ts +++ b/src/vs/workbench/contrib/debug/browser/debugCommands.ts @@ -384,12 +384,12 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ 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 }) => { + handler: async (accessor: ServicesAccessor, debugStartOptions: { config?: Partial; 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 }); + const configOrName = config ? Object.assign(deepClone(config), debugStartOptions.config) : name; + await debugService.startDebugging(launch, configOrName, { noDebug: debugStartOptions.noDebug }); } }); From 18f16643ead48fd10b15c78c1344282a3a05be09 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sat, 6 Mar 2021 17:46:56 -0800 Subject: [PATCH 11/36] Add button to reenable search excludes Fix #115352 --- .../search/browser/patternInputWidget.ts | 1 + .../contrib/search/browser/searchView.ts | 34 +++++++++++-------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/patternInputWidget.ts b/src/vs/workbench/contrib/search/browser/patternInputWidget.ts index 76d4e0b1ae9..134c7d220b2 100644 --- a/src/vs/workbench/contrib/search/browser/patternInputWidget.ts +++ b/src/vs/workbench/contrib/search/browser/patternInputWidget.ts @@ -255,6 +255,7 @@ export class ExcludePatternInputWidget extends PatternInputWidget { setUseExcludesAndIgnoreFiles(value: boolean) { this.useExcludesAndIgnoreFilesBox.checked = value; + this._onChangeIgnoreBoxEmitter.fire(); } protected getSubcontrolsWidth(): number { diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index cd392813418..3d2bd9bf78c 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -1496,14 +1496,14 @@ export class SearchView extends ViewPane { })); } else { const openSettingsLink = dom.append(p, $('a.pointer.prominent', { tabindex: 0 }, nls.localize('openSettings.message', "Open Settings"))); - this.addClickEvents(openSettingsLink, this.onOpenSettings); + this.addClickEvents(openSettingsLink, this.onOpenSettings.bind(this)); } if (completed) { dom.append(p, $('span', undefined, ' - ')); const learnMoreLink = dom.append(p, $('a.pointer.prominent', { tabindex: 0 }, nls.localize('openSettings.learnMore', "Learn More"))); - this.addClickEvents(learnMoreLink, this.onLearnMore); + this.addClickEvents(learnMoreLink, this.onLearnMore.bind(this)); } if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { @@ -1574,11 +1574,10 @@ export class SearchView extends ViewPane { })); }; - private onOpenSettings = (e: dom.EventLike): void => { + private onOpenSettings(e: dom.EventLike): void { dom.EventHelper.stop(e, false); - this.openSettings('.exclude'); - }; + } private openSettings(query: string): Promise { const options: ISettingsEditorOptions = { query }; @@ -1587,11 +1586,15 @@ export class SearchView extends ViewPane { this.preferencesService.openGlobalSettings(undefined, options); } - private onLearnMore = (e: MouseEvent): void => { + private onLearnMore(e: MouseEvent): void { dom.EventHelper.stop(e, false); - this.openerService.open(URI.parse('https://go.microsoft.com/fwlink/?linkid=853977')); - }; + } + + private onEnableExcludes(e: MouseEvent): void { + dom.EventHelper.stop(e, false); + this.searchExcludePattern.setUseExcludesAndIgnoreFiles(true); + } private updateSearchResultCount(disregardExcludesAndIgnores?: boolean): void { const fileCount = this.viewModel.searchResult.fileCount(); @@ -1600,18 +1603,21 @@ export class SearchView extends ViewPane { const msgWasHidden = this.messagesElement.style.display === 'none'; const messageEl = this.clearMessage(); - let resultMsg = this.buildResultCountMessage(this.viewModel.searchResult.count(), fileCount); + const resultMsg = this.buildResultCountMessage(this.viewModel.searchResult.count(), fileCount); this.tree.ariaLabel = resultMsg + nls.localize('forTerm', " - Search: {0}", this.searchResult.query?.contentPattern.pattern ?? ''); + dom.append(messageEl, resultMsg); if (fileCount > 0) { if (disregardExcludesAndIgnores) { - resultMsg += nls.localize('useIgnoresAndExcludesDisabled', " - exclude settings and ignore files are disabled"); + const excludesDisabledMessage = ' - ' + nls.localize('useIgnoresAndExcludesDisabled', "exclude settings and ignore files are disabled") + ' '; + const enableMessage = nls.localize('excludes.enable', "enable"); + const enableExcludesButton = $('a.pointer.prominent', { title: nls.localize('useExcludesAndIgnoreFilesDescription', "Use Exclude Settings and Ignore Files") }, enableMessage); + this.addClickEvents(enableExcludesButton, this.onEnableExcludes.bind(this)); + dom.append(messageEl, $('span', undefined, excludesDisabledMessage, '(', enableExcludesButton, ')')); } - dom.append(messageEl, $('span', undefined, resultMsg + ' - ')); - const span = dom.append(messageEl, $('span')); - const openInEditorLink = dom.append(span, $('a.pointer.prominent', undefined, nls.localize('openInEditor.message', "Open in editor"))); - + dom.append(messageEl, ' - '); + const openInEditorLink = dom.append(messageEl, $('a.pointer.prominent', undefined, nls.localize('openInEditor.message', "Open in editor"))); openInEditorLink.title = appendKeyBindingLabel( nls.localize('openInEditor.tooltip', "Copy current search results to an editor"), this.keybindingService.lookupKeybinding(Constants.OpenInEditorCommandId), this.keybindingService); From 31a7757fc7bf7cd581badb45885517d6e44722fb Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Sat, 6 Mar 2021 17:49:17 -0800 Subject: [PATCH 12/36] Better "Open Settings" option in search view --- src/vs/workbench/contrib/search/browser/searchView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index 3d2bd9bf78c..c26e77aca90 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -1576,7 +1576,7 @@ export class SearchView extends ViewPane { private onOpenSettings(e: dom.EventLike): void { dom.EventHelper.stop(e, false); - this.openSettings('.exclude'); + this.openSettings('@id:files.exclude,search.exclude,search.useGlobalIgnoreFiles,search.useIgnoreFiles'); } private openSettings(query: string): Promise { From 2b9470cb4e1e9350242f2a81bfe3c6ae4800fa85 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 8 Mar 2021 11:58:50 -0800 Subject: [PATCH 13/36] Clean up SearchView link button code --- .../contrib/search/browser/searchView.ts | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index c26e77aca90..c7f61dfb125 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -17,7 +17,7 @@ import * as errors from 'vs/base/common/errors'; import { Event } from 'vs/base/common/event'; import { Iterable } from 'vs/base/common/iterator'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; import * as env from 'vs/base/common/platform'; import * as strings from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; @@ -1478,11 +1478,11 @@ export class SearchView extends ViewPane { const p = dom.append(messageEl, $('p', undefined, message)); if (!completed) { - const searchAgainLink = dom.append(p, $('a.pointer.prominent', undefined, nls.localize('rerunSearch.message', "Search again"))); - this.messageDisposables.push(dom.addDisposableListener(searchAgainLink, dom.EventType.CLICK, (e: MouseEvent) => { - dom.EventHelper.stop(e, false); - this.triggerQueryChange({ preserveFocus: false }); - })); + const searchAgainButton = new SearchLinkButton( + nls.localize('rerunSearch.message', "Search again"), + () => this.triggerQueryChange({ preserveFocus: false })); + this.messageDisposables.push(searchAgainButton); + dom.append(p, searchAgainButton.element); } else if (hasIncludes || hasExcludes) { const searchAgainLink = dom.append(p, $('a.pointer.prominent', { tabindex: 0 }, nls.localize('rerunSearchInAll.message', "Search again in all files"))); this.messageDisposables.push(dom.addDisposableListener(searchAgainLink, dom.EventType.CLICK, (e: MouseEvent) => { @@ -1495,15 +1495,17 @@ export class SearchView extends ViewPane { this.triggerQueryChange({ preserveFocus: false }); })); } else { - const openSettingsLink = dom.append(p, $('a.pointer.prominent', { tabindex: 0 }, nls.localize('openSettings.message', "Open Settings"))); - this.addClickEvents(openSettingsLink, this.onOpenSettings.bind(this)); + const openSettingsButton = new SearchLinkButton(nls.localize('openSettings.message', "Open Settings"), this.onOpenSettings.bind(this)); + this.messageDisposables.push(openSettingsButton); + dom.append(p, openSettingsButton.element); } if (completed) { dom.append(p, $('span', undefined, ' - ')); - const learnMoreLink = dom.append(p, $('a.pointer.prominent', { tabindex: 0 }, nls.localize('openSettings.learnMore', "Learn More"))); - this.addClickEvents(learnMoreLink, this.onLearnMore.bind(this)); + const learnMoreButton = new SearchLinkButton(nls.localize('openSettings.learnMore', "Learn More"), this.onLearnMore.bind(this)); + this.messageDisposables.push(learnMoreButton); + dom.append(p, learnMoreButton.element); } if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) { @@ -1555,25 +1557,6 @@ export class SearchView extends ViewPane { .then(onComplete, onError); } - private addClickEvents = (element: HTMLElement, handler: (event: any) => void): void => { - this.messageDisposables.push(dom.addDisposableListener(element, dom.EventType.CLICK, handler)); - this.messageDisposables.push(dom.addDisposableListener(element, dom.EventType.KEY_DOWN, e => { - const event = new StandardKeyboardEvent(e); - let eventHandled = true; - - if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) { - handler(e); - } else { - eventHandled = false; - } - - if (eventHandled) { - event.preventDefault(); - event.stopPropagation(); - } - })); - }; - private onOpenSettings(e: dom.EventLike): void { dom.EventHelper.stop(e, false); this.openSettings('@id:files.exclude,search.exclude,search.useGlobalIgnoreFiles,search.useIgnoreFiles'); @@ -1586,13 +1569,12 @@ export class SearchView extends ViewPane { this.preferencesService.openGlobalSettings(undefined, options); } - private onLearnMore(e: MouseEvent): void { - dom.EventHelper.stop(e, false); + private onLearnMore(): void { this.openerService.open(URI.parse('https://go.microsoft.com/fwlink/?linkid=853977')); } - private onEnableExcludes(e: MouseEvent): void { - dom.EventHelper.stop(e, false); + private onEnableExcludes(): void { + this.toggleQueryDetails(false, true); this.searchExcludePattern.setUseExcludesAndIgnoreFiles(true); } @@ -1610,10 +1592,9 @@ export class SearchView extends ViewPane { if (fileCount > 0) { if (disregardExcludesAndIgnores) { const excludesDisabledMessage = ' - ' + nls.localize('useIgnoresAndExcludesDisabled', "exclude settings and ignore files are disabled") + ' '; - const enableMessage = nls.localize('excludes.enable', "enable"); - const enableExcludesButton = $('a.pointer.prominent', { title: nls.localize('useExcludesAndIgnoreFilesDescription', "Use Exclude Settings and Ignore Files") }, enableMessage); - this.addClickEvents(enableExcludesButton, this.onEnableExcludes.bind(this)); - dom.append(messageEl, $('span', undefined, excludesDisabledMessage, '(', enableExcludesButton, ')')); + const enableExcludesButton = new SearchLinkButton(nls.localize('excludes.enable', "enable"), this.onEnableExcludes.bind(this), nls.localize('useExcludesAndIgnoreFilesDescription', "Use Exclude Settings and Ignore Files")); + this.messageDisposables.push(enableExcludesButton); + dom.append(messageEl, $('span', undefined, excludesDisabledMessage, '(', enableExcludesButton.element, ')')); } dom.append(messageEl, ' - '); @@ -1937,3 +1918,30 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = } } }); + +class SearchLinkButton extends Disposable { + public readonly element: HTMLElement; + + constructor(label: string, handler: (e: dom.EventLike) => unknown, tooltip?: string) { + super(); + this.element = $('a.pointer.prominent', { tabindex: 0, title: tooltip }, label); + this.addEventHandlers(handler); + } + + private addEventHandlers(handler: (e: dom.EventLike) => unknown): void { + const wrappedHandler = (e: dom.EventLike) => { + dom.EventHelper.stop(e, false); + handler(e); + }; + + this._register(dom.addDisposableListener(this.element, dom.EventType.CLICK, wrappedHandler)); + this._register(dom.addDisposableListener(this.element, dom.EventType.KEY_DOWN, e => { + const event = new StandardKeyboardEvent(e); + if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) { + wrappedHandler(e); + event.preventDefault(); + event.stopPropagation(); + } + })); + } +} From a8739f9c3a5d14ece033760957a78f2f04d94fa9 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 8 Mar 2021 12:08:43 -0800 Subject: [PATCH 14/36] Change messageDisposables to DisposableStore --- .../contrib/search/browser/searchView.ts | 87 +++++++++---------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index c7f61dfb125..a0db321f838 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -17,7 +17,7 @@ import * as errors from 'vs/base/common/errors'; import { Event } from 'vs/base/common/event'; import { Iterable } from 'vs/base/common/iterator'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; -import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable, DisposableStore, dispose } from 'vs/base/common/lifecycle'; import * as env from 'vs/base/common/platform'; import * as strings from 'vs/base/common/strings'; import { URI } from 'vs/base/common/uri'; @@ -118,7 +118,7 @@ export class SearchView extends ViewPane { private treeLabels!: ResourceLabels; private viewletState: MementoObject; private messagesElement!: HTMLElement; - private messageDisposables: IDisposable[] = []; + private readonly messageDisposables: DisposableStore = new DisposableStore(); private searchWidgetsContainerElement!: HTMLElement; private searchWidget!: SearchWidget; private size!: dom.Dimension; @@ -680,8 +680,7 @@ export class SearchView extends ViewPane { const wasHidden = this.messagesElement.style.display === 'none'; dom.clearNode(this.messagesElement); dom.show(this.messagesElement); - dispose(this.messageDisposables); - this.messageDisposables = []; + this.messageDisposables.clear(); const newMessage = dom.append(this.messagesElement, $('.message')); if (wasHidden) { @@ -1478,33 +1477,22 @@ export class SearchView extends ViewPane { const p = dom.append(messageEl, $('p', undefined, message)); if (!completed) { - const searchAgainButton = new SearchLinkButton( + const searchAgainButton = this.messageDisposables.add(new SearchLinkButton( nls.localize('rerunSearch.message', "Search again"), - () => this.triggerQueryChange({ preserveFocus: false })); - this.messageDisposables.push(searchAgainButton); + () => this.triggerQueryChange({ preserveFocus: false }))); dom.append(p, searchAgainButton.element); } else if (hasIncludes || hasExcludes) { - const searchAgainLink = dom.append(p, $('a.pointer.prominent', { tabindex: 0 }, nls.localize('rerunSearchInAll.message', "Search again in all files"))); - this.messageDisposables.push(dom.addDisposableListener(searchAgainLink, dom.EventType.CLICK, (e: MouseEvent) => { - dom.EventHelper.stop(e, false); - - this.inputPatternExcludes.setValue(''); - this.inputPatternIncludes.setValue(''); - this.inputPatternIncludes.setOnlySearchInOpenEditors(false); - - this.triggerQueryChange({ preserveFocus: false }); - })); + const searchAgainButton = this.messageDisposables.add(new SearchLinkButton(nls.localize('rerunSearchInAll.message', "Search again in all files"), this.onSearchAgain.bind(this))); + dom.append(p, searchAgainButton.element); } else { - const openSettingsButton = new SearchLinkButton(nls.localize('openSettings.message', "Open Settings"), this.onOpenSettings.bind(this)); - this.messageDisposables.push(openSettingsButton); + const openSettingsButton = this.messageDisposables.add(new SearchLinkButton(nls.localize('openSettings.message', "Open Settings"), this.onOpenSettings.bind(this))); dom.append(p, openSettingsButton.element); } if (completed) { dom.append(p, $('span', undefined, ' - ')); - const learnMoreButton = new SearchLinkButton(nls.localize('openSettings.learnMore', "Learn More"), this.onLearnMore.bind(this)); - this.messageDisposables.push(learnMoreButton); + const learnMoreButton = this.messageDisposables.add(new SearchLinkButton(nls.localize('openSettings.learnMore', "Learn More"), this.onLearnMore.bind(this))); dom.append(p, learnMoreButton.element); } @@ -1573,6 +1561,14 @@ export class SearchView extends ViewPane { this.openerService.open(URI.parse('https://go.microsoft.com/fwlink/?linkid=853977')); } + private onSearchAgain(): void { + this.inputPatternExcludes.setValue(''); + this.inputPatternIncludes.setValue(''); + this.inputPatternIncludes.setOnlySearchInOpenEditors(false); + + this.triggerQueryChange({ preserveFocus: false }); + } + private onEnableExcludes(): void { this.toggleQueryDetails(false, true); this.searchExcludePattern.setUseExcludesAndIgnoreFiles(true); @@ -1592,21 +1588,20 @@ export class SearchView extends ViewPane { if (fileCount > 0) { if (disregardExcludesAndIgnores) { const excludesDisabledMessage = ' - ' + nls.localize('useIgnoresAndExcludesDisabled', "exclude settings and ignore files are disabled") + ' '; - const enableExcludesButton = new SearchLinkButton(nls.localize('excludes.enable', "enable"), this.onEnableExcludes.bind(this), nls.localize('useExcludesAndIgnoreFilesDescription', "Use Exclude Settings and Ignore Files")); - this.messageDisposables.push(enableExcludesButton); + const enableExcludesButton = this.messageDisposables.add(new SearchLinkButton(nls.localize('excludes.enable', "enable"), this.onEnableExcludes.bind(this), nls.localize('useExcludesAndIgnoreFilesDescription', "Use Exclude Settings and Ignore Files"))); dom.append(messageEl, $('span', undefined, excludesDisabledMessage, '(', enableExcludesButton.element, ')')); } dom.append(messageEl, ' - '); - const openInEditorLink = dom.append(messageEl, $('a.pointer.prominent', undefined, nls.localize('openInEditor.message', "Open in editor"))); - openInEditorLink.title = appendKeyBindingLabel( + + const openInEditorTooltip = appendKeyBindingLabel( nls.localize('openInEditor.tooltip', "Copy current search results to an editor"), this.keybindingService.lookupKeybinding(Constants.OpenInEditorCommandId), this.keybindingService); - - this.messageDisposables.push(dom.addDisposableListener(openInEditorLink, dom.EventType.CLICK, (e: MouseEvent) => { - dom.EventHelper.stop(e, false); - this.instantiationService.invokeFunction(createEditorFromSearchResult, this.searchResult, this.searchIncludePattern.getValue(), this.searchExcludePattern.getValue(), this.searchIncludePattern.onlySearchInOpenEditors()); - })); + const openInEditorButton = this.messageDisposables.add(new SearchLinkButton( + nls.localize('openInEditor.message', "Open in editor"), + () => this.instantiationService.invokeFunction(createEditorFromSearchResult, this.searchResult, this.searchIncludePattern.getValue(), this.searchExcludePattern.getValue(), this.searchIncludePattern.onlySearchInOpenEditors()), + openInEditorTooltip)); + dom.append(messageEl, openInEditorButton.element); this.reLayout(); } else if (!msgWasHidden) { @@ -1632,24 +1627,22 @@ export class SearchView extends ViewPane { const textEl = dom.append(this.searchWithoutFolderMessageElement, $('p', undefined, nls.localize('searchWithoutFolder', "You have not opened or specified a folder. Only open files are currently searched - "))); - const openFolderLink = dom.append(textEl, - $('a.pointer.prominent', { tabindex: 0 }, nls.localize('openFolder', "Open Folder"))); + const actionRunner = this.messageDisposables.add(new ActionRunner()); + const openFolderButton = this.messageDisposables.add(new SearchLinkButton( + nls.localize('openFolder', "Open Folder"), + () => { + const action = env.isMacintosh ? + this.instantiationService.createInstance(OpenFileFolderAction, OpenFileFolderAction.ID, OpenFileFolderAction.LABEL) : + this.instantiationService.createInstance(OpenFolderAction, OpenFolderAction.ID, OpenFolderAction.LABEL); - const actionRunner = new ActionRunner(); - this.messageDisposables.push(dom.addDisposableListener(openFolderLink, dom.EventType.CLICK, (e: MouseEvent) => { - dom.EventHelper.stop(e, false); - - const action = env.isMacintosh ? - this.instantiationService.createInstance(OpenFileFolderAction, OpenFileFolderAction.ID, OpenFileFolderAction.LABEL) : - this.instantiationService.createInstance(OpenFolderAction, OpenFolderAction.ID, OpenFolderAction.LABEL); - - actionRunner.run(action).then(() => { - action.dispose(); - }, err => { - action.dispose(); - errors.onUnexpectedError(err); - }); - })); + actionRunner.run(action).then(() => { + action.dispose(); + }, err => { + action.dispose(); + errors.onUnexpectedError(err); + }); + })); + dom.append(textEl, openFolderButton.element); } private showEmptyStage(forceHideMessages = false): void { From b20839c1f3dd8f7bd8342d7e9f16fd410cf38bd6 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 8 Mar 2021 12:10:04 -0800 Subject: [PATCH 15/36] Add 'Marketplace' issue type to issue reporter, closes #118473 --- package.json | 2 +- .../issue/issueReporterMain.ts | 57 +++++++++++++------ src/vs/platform/issue/common/issue.ts | 3 +- .../issue/electron-main/issueMainService.ts | 3 +- .../platform/product/common/productService.ts | 1 + 5 files changed, 47 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 29712325f67..145df3d7839 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.55.0", - "distro": "2173d6da3776d9f0e894d49e854ba495636e1b5d", + "distro": "0357427beb5cd348177cd1ed381cd740082966c4", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/code/electron-sandbox/issue/issueReporterMain.ts b/src/vs/code/electron-sandbox/issue/issueReporterMain.ts index 75b1c60e454..d02a264d933 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterMain.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterMain.ts @@ -53,6 +53,7 @@ export interface IssueReporterConfiguration extends IWindowConfiguration { commit: string | undefined; date: string | undefined; reportIssueUrl: string | undefined; + reportMarketplaceIssueUrl: string | undefined; } } @@ -83,6 +84,7 @@ export class IssueReporter extends Disposable { super(); this.initServices(configuration); + console.log(configuration); const targetExtension = configuration.data.extensionId ? configuration.data.enabledExtensions.find(extension => extension.id === configuration.data.extensionId) : undefined; this.issueReporterModel = new IssueReporterModel({ @@ -353,7 +355,8 @@ export class IssueReporter extends Disposable { this.addEventListener('issue-title', 'input', (e: Event) => { const title = (e.target).value; const lengthValidationMessage = this.getElementById('issue-title-length-validation-error'); - if (title && this.getIssueUrlWithTitle(title).length > MAX_URL_LENGTH) { + const issueUrl = this.getIssueUrl(); + if (title && this.getIssueUrlWithTitle(title, issueUrl).length > MAX_URL_LENGTH) { show(lengthValidationMessage); } else { hide(lengthValidationMessage); @@ -468,6 +471,10 @@ export class IssueReporter extends Disposable { return true; } + if (issueType === IssueType.Marketplace) { + return true; + } + return false; } @@ -633,11 +640,18 @@ export class IssueReporter extends Disposable { const typeSelect = this.getElementById('issue-type')! as HTMLSelectElement; const { issueType } = this.issueReporterModel.getData(); - reset(typeSelect, - makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")), - makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")), - makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")) - ); + this.configuration.product.reportMarketplaceIssueUrl + ? reset(typeSelect, + makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")), + makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")), + makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")), + makeOption(IssueType.Marketplace, localize('marketplaceIssue', "Extensions Marketplace Issue")) + ) + : reset(typeSelect, + makeOption(IssueType.Bug, localize('bugReporter', "Bug Report")), + makeOption(IssueType.FeatureRequest, localize('featureRequest', "Feature Request")), + makeOption(IssueType.PerformanceIssue, localize('performanceIssue', "Performance Issue")), + ); typeSelect.value = issueType.toString(); @@ -751,6 +765,9 @@ export class IssueReporter extends Disposable { if (fileOnExtension) { show(extensionSelector); } + } else if (issueType === IssueType.Marketplace) { + reset(descriptionTitle, localize('description', "Description"), $('span.required-input', undefined, '*')); + reset(descriptionSubtitle, localize('marketplaceDescription', "Please describe the feature you would like added to the marketplace, or steps to reliably reproduce the problem if you are reporting a bug. We support GitHub-flavored Markdown. You will be able to edit your issue and add screenshots when we preview it on GitHub.")); } } @@ -770,10 +787,14 @@ export class IssueReporter extends Disposable { private validateInputs(): boolean { let isValid = true; - ['issue-title', 'description', 'issue-source'].forEach(elementId => { + ['issue-title', 'description'].forEach(elementId => { isValid = this.validateInput(elementId) && isValid; }); + if (this.issueReporterModel.getData().issueType !== IssueType.Marketplace) { + isValid = this.validateInput('issue-source') && isValid; + } + if (this.issueReporterModel.fileOnExtension()) { isValid = this.validateInput('extension-selector') && isValid; } @@ -845,13 +866,13 @@ export class IssueReporter extends Disposable { const issueTitle = (this.getElementById('issue-title')).value; const issueBody = this.issueReporterModel.serialize(); - const issueUrl = this.issueReporterModel.fileOnExtension() ? this.getExtensionGitHubUrl() : this.configuration.product.reportIssueUrl!; + const issueUrl = this.getIssueUrl(); const gitHubDetails = this.parseGitHubUrl(issueUrl); if (this.configuration.data.githubAccessToken && gitHubDetails) { return this.submitToGitHub(issueTitle, issueBody, gitHubDetails); } - const baseUrl = this.getIssueUrlWithTitle((this.getElementById('issue-title')).value); + const baseUrl = this.getIssueUrlWithTitle((this.getElementById('issue-title')).value, issueUrl); let url = baseUrl + `&body=${encodeURIComponent(issueBody)}`; if (url.length > MAX_URL_LENGTH) { @@ -881,6 +902,14 @@ export class IssueReporter extends Disposable { }); } + private getIssueUrl(): string { + return this.issueReporterModel.fileOnExtension() + ? this.getExtensionGitHubUrl() + : this.issueReporterModel.getData().issueType === IssueType.Marketplace + ? this.configuration.product.reportMarketplaceIssueUrl! + : this.configuration.product.reportIssueUrl!; + } + private parseGitHubUrl(url: string): undefined | { repositoryName: string, owner: string } { // Assumes a GitHub url to a particular repo, https://github.com/repositoryName/owner. // Repository name and owner cannot contain '/' @@ -909,16 +938,12 @@ export class IssueReporter extends Disposable { return repositoryUrl; } - private getIssueUrlWithTitle(issueTitle: string): string { - let repositoryUrl = this.configuration.product.reportIssueUrl; + private getIssueUrlWithTitle(issueTitle: string, repositoryUrl: string): string { if (this.issueReporterModel.fileOnExtension()) { - const extensionGitHubUrl = this.getExtensionGitHubUrl(); - if (extensionGitHubUrl) { - repositoryUrl = extensionGitHubUrl + '/issues/new'; - } + repositoryUrl = repositoryUrl + '/issues/new'; } - const queryStringPrefix = this.configuration.product.reportIssueUrl && this.configuration.product.reportIssueUrl.indexOf('?') === -1 ? '?' : '&'; + const queryStringPrefix = repositoryUrl.indexOf('?') === -1 ? '?' : '&'; return `${repositoryUrl}${queryStringPrefix}title=${encodeURIComponent(issueTitle)}`; } diff --git a/src/vs/platform/issue/common/issue.ts b/src/vs/platform/issue/common/issue.ts index fc36369c68c..a7dada74828 100644 --- a/src/vs/platform/issue/common/issue.ts +++ b/src/vs/platform/issue/common/issue.ts @@ -17,7 +17,8 @@ export interface WindowData { export const enum IssueType { Bug, PerformanceIssue, - FeatureRequest + FeatureRequest, + Marketplace } export interface IssueReporterStyles extends WindowStyles { diff --git a/src/vs/platform/issue/electron-main/issueMainService.ts b/src/vs/platform/issue/electron-main/issueMainService.ts index f79bb21926c..d75cbec53a1 100644 --- a/src/vs/platform/issue/electron-main/issueMainService.ts +++ b/src/vs/platform/issue/electron-main/issueMainService.ts @@ -414,7 +414,8 @@ export class IssueMainService implements ICommonIssueService { version: !!product.darwinUniversalAssetId ? `${product.version} (Universal)` : product.version, commit: product.commit, date: product.date, - reportIssueUrl: product.reportIssueUrl + reportIssueUrl: product.reportIssueUrl, + reportMarketplaceIssueUrl: product.reportMarketplaceIssueUrl } }; diff --git a/src/vs/platform/product/common/productService.ts b/src/vs/platform/product/common/productService.ts index 07263ca07f2..3037c6562c0 100644 --- a/src/vs/platform/product/common/productService.ts +++ b/src/vs/platform/product/common/productService.ts @@ -107,6 +107,7 @@ export interface IProductConfiguration { readonly twitterUrl?: string; readonly requestFeatureUrl?: string; readonly reportIssueUrl?: string; + readonly reportMarketplaceIssueUrl?: string; readonly licenseUrl?: string; readonly privacyStatementUrl?: string; readonly telemetryOptOutUrl?: string; From 2c1037d35210cc6cd91d904fc73aa44988d91943 Mon Sep 17 00:00:00 2001 From: Jean Pierre Date: Mon, 8 Mar 2021 15:38:57 -0500 Subject: [PATCH 16/36] Fixes #117600 (#118397) --- .../browser/webviewPanel.contribution.ts | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.ts b/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.ts index 5816ad9f40a..81a8d4e5afa 100644 --- a/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.ts +++ b/src/vs/workbench/contrib/webviewPanel/browser/webviewPanel.contribution.ts @@ -5,11 +5,16 @@ import { localize } from 'vs/nls'; import { registerAction2 } from 'vs/platform/actions/common/actions'; +import { EditorOverride, ITextEditorOptions } from 'vs/platform/editor/common/editor'; 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 { EditorDescriptor, Extensions as EditorExtensions, IEditorRegistry } from 'vs/workbench/browser/editor'; -import { Extensions as EditorInputExtensions, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; +import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions'; +import { Extensions as EditorInputExtensions, IEditorInput, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor'; +import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; +import { IEditorService, IOpenEditorOverride } from 'vs/workbench/services/editor/common/editorService'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { HideWebViewEditorFindCommand, ReloadWebviewAction, ShowWebViewEditorFindWidgetAction, WebViewEditorFindNextCommand, WebViewEditorFindPreviousCommand } from './webviewCommands'; import { WebviewEditor } from './webviewEditor'; import { WebviewInput } from './webviewEditorInput'; @@ -22,6 +27,53 @@ import { IWebviewWorkbenchService, WebviewEditorService } from './webviewWorkben localize('webview.editor.label', "webview editor")), [new SyncDescriptor(WebviewInput)]); +class WebviewPanelContribution implements IWorkbenchContribution { + constructor( + @IEditorService private readonly editorService: IEditorService, + @IEditorGroupsService private readonly editorGroupService: IEditorGroupsService, + ) { + this.editorService.overrideOpenEditor({ + open: (editor, options, group) => this.onEditorOpening(editor, options, group) + }); + } + + private onEditorOpening( + editor: IEditorInput, + options: ITextEditorOptions | undefined, + group: IEditorGroup + ): IOpenEditorOverride | undefined { + if (!(editor instanceof WebviewInput) || editor.getTypeId() !== WebviewInput.typeId) { + return undefined; + } + + if (group.isOpened(editor)) { + return undefined; + } + + let previousGroup: IEditorGroup | undefined; + const groups = this.editorGroupService.groups; + for (const group of groups) { + if (group.isOpened(editor)) { + previousGroup = group; + break; + } + } + + if (!previousGroup) { + return undefined; + } + + previousGroup.closeEditor(editor); + + return { + override: this.editorService.openEditor(editor, { ...options, override: EditorOverride.DISABLED }, group) + }; + } +} + +const workbenchContributionsRegistry = Registry.as(WorkbenchExtensions.Workbench); +workbenchContributionsRegistry.registerWorkbenchContribution(WebviewPanelContribution, LifecyclePhase.Starting); + Registry.as(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory( WebviewEditorInputFactory.ID, WebviewEditorInputFactory); From 0e8fba32637ef0ee4fe52152a20f5856d8a0681b Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Mon, 8 Mar 2021 13:14:58 -0800 Subject: [PATCH 17/36] Add outline offset for view actions (fixes #117349) --- src/vs/base/browser/ui/splitview/paneview.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/vs/base/browser/ui/splitview/paneview.css b/src/vs/base/browser/ui/splitview/paneview.css index a7d76d81055..a2ab94660b4 100644 --- a/src/vs/base/browser/ui/splitview/paneview.css +++ b/src/vs/base/browser/ui/splitview/paneview.css @@ -73,6 +73,7 @@ align-items: center; justify-content: center; color: inherit; + outline-offset: -2px; } .monaco-pane-view .pane > .pane-header .monaco-action-bar .action-item.select-container { From bdbf5850127876124f44c06f6ffd01be065eba6c Mon Sep 17 00:00:00 2001 From: Raymond Zhao Date: Mon, 8 Mar 2021 13:51:07 -0800 Subject: [PATCH 18/36] Bump vscode-emmet-helper, fixes #118363 --- extensions/emmet/yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 50294f89cac..3b553d5997b 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -77,9 +77,9 @@ jsonc-parser@^2.3.0: integrity sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg== vscode-emmet-helper@^2.3.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.4.0.tgz#12f82fd05fb1df11ef7e78f85df63724de54a05b" - integrity sha512-aMbUL3oHBWM/Ux/C035a6KKLgIV8+GNGuu1b7ztuHXM6VmrdFFLNI5+tfFjfYQ3GBpD+Q7ZQU7CX/JaGlBbBiA== + version "2.4.1" + resolved "https://registry.yarnpkg.com/vscode-emmet-helper/-/vscode-emmet-helper-2.4.1.tgz#7e020f66cbd72cf8e107b0ac7235cb806a728126" + integrity sha512-Sz3QbEgD1h05+sK3ltVLOUl2KKqwFVGUFSLS7ZlVqZoKPCWiFnd0dgf3miyipt6lGOadrsqvn7mCRbiSXJAMqA== dependencies: emmet "^2.3.0" jsonc-parser "^2.3.0" From d4f8348c6ac9878df596bc3ad640af4d2aacd2e0 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 8 Mar 2021 15:01:16 -0800 Subject: [PATCH 19/36] Handle undefined extension publishers in issue reporter, fixes #118480 --- src/vs/code/electron-sandbox/issue/issueReporterMain.ts | 2 +- src/vs/code/electron-sandbox/issue/issueReporterModel.ts | 2 +- src/vs/platform/issue/common/issue.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/code/electron-sandbox/issue/issueReporterMain.ts b/src/vs/code/electron-sandbox/issue/issueReporterMain.ts index d02a264d933..28de366c453 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterMain.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterMain.ts @@ -1181,7 +1181,7 @@ export class IssueReporter extends Disposable { ), ...extensions.map(extension => $('tr', undefined, $('td', undefined, extension.name), - $('td', undefined, extension.publisher.substr(0, 3)), + $('td', undefined, extension.publisher?.substr(0, 3) ?? 'N/A'), $('td', undefined, extension.version), )) ); diff --git a/src/vs/code/electron-sandbox/issue/issueReporterModel.ts b/src/vs/code/electron-sandbox/issue/issueReporterModel.ts index f850e4d8093..82b7dd39bb5 100644 --- a/src/vs/code/electron-sandbox/issue/issueReporterModel.ts +++ b/src/vs/code/electron-sandbox/issue/issueReporterModel.ts @@ -238,7 +238,7 @@ ${this._data.experimentInfo} const tableHeader = `Extension|Author (truncated)|Version ---|---|---`; const table = this._data.enabledNonThemeExtesions.map(e => { - return `${e.name}|${e.publisher.substr(0, 3)}|${e.version}`; + return `${e.name}|${e.publisher?.substr(0, 3) ?? 'N/A'}|${e.version}`; }).join('\n'); return `
Extensions (${this._data.enabledNonThemeExtesions.length}) diff --git a/src/vs/platform/issue/common/issue.ts b/src/vs/platform/issue/common/issue.ts index a7dada74828..3669d53c9e7 100644 --- a/src/vs/platform/issue/common/issue.ts +++ b/src/vs/platform/issue/common/issue.ts @@ -41,7 +41,7 @@ export interface IssueReporterStyles extends WindowStyles { export interface IssueReporterExtensionData { name: string; - publisher: string; + publisher: string | undefined; version: string; id: string; isTheme: boolean; From c59c1101162b8d4ebf8e80572584798477922c32 Mon Sep 17 00:00:00 2001 From: rebornix Date: Mon, 8 Mar 2021 14:50:48 -0800 Subject: [PATCH 20/36] revealView should scroll a little to reveal items below viewport. --- .../notebook/browser/notebookBrowser.ts | 3 +- .../notebook/browser/view/notebookCellList.ts | 33 +++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index de4f972fb02..08d4592ea77 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -748,7 +748,8 @@ export enum CellRevealType { export enum CellRevealPosition { Top, - Center + Center, + Bottom } export enum CellEditState { diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index 67381a6fdba..c409ed8b2f1 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -698,7 +698,7 @@ export class NotebookCellList extends WorkbenchList implements ID return; } - const endIndex = this._getViewIndexUpperBound2(range.end); + const endIndex = this._getViewIndexUpperBound2(range.end - 1); const scrollTop = this.getViewScrollTop(); const wrapperBottom = this.getViewScrollBottom(); @@ -1074,18 +1074,31 @@ export class NotebookCellList extends WorkbenchList implements ID } } - // first render - const viewItemOffset = revealPosition === CellRevealPosition.Top ? elementTop : (elementTop - this.view.renderHeight / 2); - this.view.setScrollTop(viewItemOffset); - - // second scroll as markdown cell is dynamic - const newElementTop = this.view.elementTop(viewIndex); - const newViewItemOffset = revealPosition === CellRevealPosition.Top ? newElementTop : (newElementTop - this.view.renderHeight / 2); - this.view.setScrollTop(newViewItemOffset); + switch (revealPosition) { + case CellRevealPosition.Top: + this.view.setScrollTop(elementTop); + this.view.setScrollTop(this.view.elementTop(viewIndex)); + break; + case CellRevealPosition.Center: + this.view.setScrollTop(elementTop - this.view.renderHeight / 2); + this.view.setScrollTop(this.view.elementTop(viewIndex) - this.view.renderHeight / 2); + break; + case CellRevealPosition.Bottom: + this.view.setScrollTop(elementBottom - this.view.renderHeight); + this.view.setScrollTop(this.view.elementTop(viewIndex) + this.view.elementHeight(viewIndex) - this.view.renderHeight); + break; + default: + break; + } } private _revealInView(viewIndex: number) { - this._revealInternal(viewIndex, true, CellRevealPosition.Top); + const firstIndex = this.view.firstVisibleIndex; + if (viewIndex < firstIndex) { + this._revealInternal(viewIndex, true, CellRevealPosition.Top); + } else { + this._revealInternal(viewIndex, true, CellRevealPosition.Bottom); + } } private _revealInCenter(viewIndex: number) { From c870a55b708c3581676e7d0a1cfce70cd53b6953 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 8 Mar 2021 16:29:03 -0800 Subject: [PATCH 21/36] Update terminalProcessManager.ts --- .../contrib/terminal/browser/terminalProcessManager.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 9377db248a4..e5fe9253ac4 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -338,6 +338,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const useConpty = this._configHelper.config.windowsEnableConpty && !isScreenReaderModeEnabled; const shouldPersist = this._configHelper.config.enablePersistentSessions && !shellLaunchConfig.isFeatureTerminal; + // Mark the process as disconnected is the pty host is unresponsive, the responsive event + // will fire only when the pty host was already unresponsive this._register(localTerminalService.onPtyHostUnresponsive(() => { this.isDisconnected = true; this._onPtyDisconnect.fire(); @@ -347,8 +349,10 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce this._onPtyReconnect.fire(); }); this._register(toDisposable(() => this._ptyResponsiveListener?.dispose())); + + // When the pty host restarts, reconnect is no longer possible so dispose the responsive + // listener this._register(localTerminalService.onPtyHostRestart(() => { - // When the pty host restarts, reconnect is no longer possible this._ptyResponsiveListener?.dispose(); this._ptyResponsiveListener = undefined; })); From 250c7baf7e8c4d470d27e19ab78acb6d7f6a303f Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Mon, 8 Mar 2021 17:00:29 -0800 Subject: [PATCH 22/36] Fix #117903 --- src/vs/workbench/api/common/extHostAuthentication.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHostAuthentication.ts b/src/vs/workbench/api/common/extHostAuthentication.ts index d32ec2ad1dc..be7640ce1d9 100644 --- a/src/vs/workbench/api/common/extHostAuthentication.ts +++ b/src/vs/workbench/api/common/extHostAuthentication.ts @@ -114,7 +114,7 @@ export class ExtHostAuthentication implements ExtHostAuthenticationShape { this._proxy.$sendDidChangeSessions(id, { added: e.added ?? [], changed: e.changed ?? [], - removed: e.changed ?? [] + removed: e.removed ?? [] }); }); From 9878ccfbd74f4d49a69be4c6c2891019d3202bdb Mon Sep 17 00:00:00 2001 From: rebornix Date: Fri, 5 Mar 2021 18:57:38 -0800 Subject: [PATCH 23/36] remove markdown preview only when it is hidden or deleted. --- .../notebook/browser/view/notebookCellList.ts | 97 ++++++------------- .../browser/view/renderers/markdownCell.ts | 1 - 2 files changed, 31 insertions(+), 67 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index c409ed8b2f1..093773bfa00 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -24,6 +24,7 @@ import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/ import { diff, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, CellKind, ICellRange, NOTEBOOK_EDITOR_CURSOR_BEGIN_END, cellRangesToIndexes, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { clamp } from 'vs/base/common/numbers'; import { SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants'; +import { ISplice } from 'vs/base/common/sequence'; export interface IFocusNextPreviousDelegate { onFocusNext(applyFocusNext: () => void): void; @@ -313,53 +314,14 @@ export class NotebookCellList extends WorkbenchList implements ID }); if (e.synchronous) { - viewDiffs.reverse().forEach((diff) => { - // remove output in the webview - const hideOutputs: ICellOutputViewModel[] = []; - const deletedOutputs: ICellOutputViewModel[] = []; - - for (let i = diff.start; i < diff.start + diff.deleteCount; i++) { - const cell = this.element(i); - if (cell.cellKind === CellKind.Code) { - if (this._viewModel!.hasCell(cell.handle)) { - hideOutputs.push(...cell?.outputsViewModels); - } else { - deletedOutputs.push(...cell?.outputsViewModels); - } - } - } - - this.splice2(diff.start, diff.deleteCount, diff.toInsert); - - hideOutputs.forEach(output => this._onDidHideOutput.fire(output)); - deletedOutputs.forEach(output => this._onDidRemoveOutput.fire(output)); - }); + this._updateElementsInWebview(viewDiffs); } else { this._viewModelStore.add(DOM.scheduleAtNextAnimationFrame(() => { if (this._isDisposed) { return; } - viewDiffs.reverse().forEach((diff) => { - const hideOutputs: ICellOutputViewModel[] = []; - const deletedOutputs: ICellOutputViewModel[] = []; - - for (let i = diff.start; i < diff.start + diff.deleteCount; i++) { - const cell = this.element(i); - if (cell.cellKind === CellKind.Code) { - if (this._viewModel!.hasCell(cell.handle)) { - hideOutputs.push(...cell?.outputsViewModels); - } else { - deletedOutputs.push(...cell?.outputsViewModels); - } - } - } - - this.splice2(diff.start, diff.deleteCount, diff.toInsert); - - hideOutputs.forEach(output => this._onDidHideOutput.fire(output)); - deletedOutputs.forEach(output => this._onDidRemoveOutput.fire(output)); - }); + this._updateElementsInWebview(viewDiffs); })); } })); @@ -393,6 +355,33 @@ export class NotebookCellList extends WorkbenchList implements ID this.splice2(0, 0, viewCells); } + private _updateElementsInWebview(viewDiffs: ISplice[]) { + viewDiffs.reverse().forEach((diff) => { + const hideOutputs: ICellOutputViewModel[] = []; + const deletedOutputs: ICellOutputViewModel[] = []; + const removedMarkdownCells: ICellViewModel[] = []; + + for (let i = diff.start; i < diff.start + diff.deleteCount; i++) { + const cell = this.element(i); + if (cell.cellKind === CellKind.Code) { + if (this._viewModel!.hasCell(cell.handle)) { + hideOutputs.push(...cell?.outputsViewModels); + } else { + deletedOutputs.push(...cell?.outputsViewModels); + } + } else { + removedMarkdownCells.push(cell); + } + } + + this.splice2(diff.start, diff.deleteCount, diff.toInsert); + + hideOutputs.forEach(output => this._onDidHideOutput.fire(output)); + deletedOutputs.forEach(output => this._onDidRemoveOutput.fire(output)); + removedMarkdownCells.forEach(cell => this._onDidRemoveCellFromView.fire(cell)); + }); + } + clear() { super.splice(0, this.length); } @@ -473,31 +462,7 @@ export class NotebookCellList extends WorkbenchList implements ID return oldViewCellMapping.has(a.uri.toString()); }); - viewDiffs.reverse().forEach((diff) => { - // remove output in the webview - const hideOutputs: ICellOutputViewModel[] = []; - const deletedOutputs: ICellOutputViewModel[] = []; - const removedMarkdownCells: ICellViewModel[] = []; - - for (let i = diff.start; i < diff.start + diff.deleteCount; i++) { - const cell = this.element(i); - if (cell.cellKind === CellKind.Code) { - if (this._viewModel!.hasCell(cell.handle)) { - hideOutputs.push(...cell?.outputsViewModels); - } else { - deletedOutputs.push(...cell?.outputsViewModels); - } - } else { - removedMarkdownCells.push(cell); - } - } - - this.splice2(diff.start, diff.deleteCount, diff.toInsert); - - hideOutputs.forEach(output => this._onDidHideOutput.fire(output)); - deletedOutputs.forEach(output => this._onDidRemoveOutput.fire(output)); - removedMarkdownCells.forEach(cell => this._onDidRemoveCellFromView.fire(cell)); - }); + this._updateElementsInWebview(viewDiffs); } splice2(start: number, deleteCount: number, elements: CellViewModel[] = []): 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 4d0112043d2..0312488eb30 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/markdownCell.ts @@ -276,7 +276,6 @@ export class StatefulMarkdownCell extends Disposable { } dispose() { - this.notebookEditor.removeMarkdownPreview(this.viewCell); this.localDisposables.dispose(); this.viewCell.detachTextEditor(); super.dispose(); From 11a84a6e8ac6e6045311aa7b7002784b0aa6504f Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Tue, 9 Mar 2021 01:13:24 +0000 Subject: [PATCH 24/36] inset -> output. --- .../contrib/notebook/browser/diff/diffElementOutputs.ts | 2 +- .../notebook/browser/diff/notebookDiffEditorBrowser.ts | 2 +- .../contrib/notebook/browser/diff/notebookTextDiffEditor.ts | 4 ++-- src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts | 2 +- .../contrib/notebook/browser/notebookEditorWidget.ts | 4 ++-- .../notebook/browser/view/renderers/backLayerWebView.ts | 2 +- .../contrib/notebook/browser/view/renderers/cellOutput.ts | 4 ++-- src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts index f3561117874..1fb836f9fea 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffElementOutputs.ts @@ -109,7 +109,7 @@ export class OutputElement extends Disposable { if (result.type !== RenderOutputType.Mainframe) { // this.viewCell.selfSizeMonitoring = true; - this._notebookEditor.createInset( + this._notebookEditor.createOutput( this._diffElementViewModel, this._nestedCell, result, diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts index dd0920e45d3..0ca043aacff 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookDiffEditorBrowser.ts @@ -33,7 +33,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, diffSide: DiffSide): void; + createOutput(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, diffSide: DiffSide): void; showInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, displayOutput: ICellOutputViewModel, diffSide: DiffSide): void; removeInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: ICellOutputViewModel, diffSide: DiffSide): void; hideInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: IDiffNestedCellViewModel, output: ICellOutputViewModel): void; diff --git a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts index 3448adfd9c7..8fbe0f1dc72 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/notebookTextDiffEditor.ts @@ -590,7 +590,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD this._list.triggerScrollFromMouseWheelEvent(event); } - createInset(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, diffSide: DiffSide): void { + createOutput(cellDiffViewModel: DiffElementViewModelBase, cellViewModel: DiffNestedCellViewModel, output: IInsetRenderOutput, getOffset: () => number, diffSide: DiffSide): void { this._insetModifyQueueByOutputId.queue(output.source.model.outputId + (diffSide === DiffSide.Modified ? '-right' : 'left'), async () => { const activeWebview = diffSide === DiffSide.Modified ? this._modifiedWebview : this._originalWebview; if (!activeWebview) { @@ -599,7 +599,7 @@ export class NotebookTextDiffEditor extends EditorPane implements INotebookTextD 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()); + await activeWebview.createOutput({ 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; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 08d4592ea77..27010d49513 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -479,7 +479,7 @@ export interface INotebookEditor extends ICommonNotebookEditor { /** * Render the output in webview layer */ - createInset(cell: ICellViewModel, output: IInsetRenderOutput, offset: number): Promise; + createOutput(cell: ICellViewModel, output: IInsetRenderOutput, offset: number): Promise; /** * Remove the output from the webview layer diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index 270abab7746..4df6ab24776 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -1693,7 +1693,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor await this._webview?.updateMarkdownPreviewSelectionState(cell.id, isSelected); } - async createInset(cell: CodeCellViewModel, output: IInsetRenderOutput, offset: number): Promise { + async createOutput(cell: CodeCellViewModel, output: IInsetRenderOutput, offset: number): Promise { this._insetModifyQueueByOutputId.queue(output.source.model.outputId, async () => { if (!this._webview) { return; @@ -1703,7 +1703,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({ cellId: cell.id, cellHandle: cell.handle, cellUri: cell.uri }, output, cellTop, offset); + await this._webview!.createOutput({ cellId: cell.id, cellHandle: cell.handle, cellUri: cell.uri }, output, cellTop, offset); } else { const cellTop = this._list.getAbsoluteTopOfElement(cell); const scrollTop = this._list.scrollTop; 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 509cd5498a2..a7bb989709c 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -1163,7 +1163,7 @@ var requirejs = (function() { await p; } - async createInset(cellInfo: T, content: IInsetRenderOutput, cellTop: number, offset: number) { + async createOutput(cellInfo: T, content: IInsetRenderOutput, cellTop: number, offset: number) { 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 7604b08bca3..3aade6390a6 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/cellOutput.ts @@ -150,7 +150,7 @@ export class CellOutputElement extends Disposable { } if (renderResult.type !== RenderOutputType.Mainframe) { - this.notebookEditor.createInset(this.viewCell, renderResult, this.viewCell.getOutputOffset(index)); + this.notebookEditor.createOutput(this.viewCell, renderResult, this.viewCell.getOutputOffset(index)); this.domNode.classList.add('background'); } else { this.domNode.classList.add('foreground', 'output-element'); @@ -388,7 +388,7 @@ export class CellOutputContainer extends Disposable { const renderedOutput = this.outputEntries.get(currOutput); if (renderedOutput && renderedOutput.renderResult) { if (renderedOutput.renderResult.type !== RenderOutputType.Mainframe) { - this.notebookEditor.createInset(this.viewCell, renderedOutput.renderResult as IInsetRenderOutput, this.viewCell.getOutputOffset(index)); + this.notebookEditor.createOutput(this.viewCell, renderedOutput.renderResult as IInsetRenderOutput, this.viewCell.getOutputOffset(index)); } else { this.viewCell.updateOutputHeight(index, renderedOutput.domClientHeight); } diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 43296a32a9c..fed3e68aa04 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -309,7 +309,7 @@ export class TestNotebookEditor implements INotebookEditor { // throw new Error('Method not implemented.'); return; } - createInset(cell: CellViewModel, output: IInsetRenderOutput, offset: number): Promise { + createOutput(cell: CellViewModel, output: IInsetRenderOutput, offset: number): Promise { return Promise.resolve(); } createMarkdownPreview(cell: ICellViewModel): Promise { From ac229ced0739c2ff1e5e571cd433b055f8d0f098 Mon Sep 17 00:00:00 2001 From: Jackson Kearl Date: Mon, 8 Mar 2021 19:31:33 -0800 Subject: [PATCH 25/36] Revert "Reenable smoke test to see if still flakey" #115244 This reverts commit 5d80c30e5b6ce8b2f5336ed55ad043490b0b818f. --- test/smoke/src/areas/search/search.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smoke/src/areas/search/search.test.ts b/test/smoke/src/areas/search/search.test.ts index 444a9157aa2..77bcc40efb4 100644 --- a/test/smoke/src/areas/search/search.test.ts +++ b/test/smoke/src/areas/search/search.test.ts @@ -35,7 +35,7 @@ export function setup() { }); // https://github.com/microsoft/vscode/issues/115244 - it('dismisses result & checks for correct result number', async function () { + it.skip('dismisses result & checks for correct result number', async function () { const app = this.app as Application; await app.workbench.search.searchFor('body'); await app.workbench.search.removeFileMatch('app.js'); From 27975dad4fbe8885b9fffcfe309b5d7662f4912d Mon Sep 17 00:00:00 2001 From: Tyler James Leonhardt Date: Mon, 8 Mar 2021 19:46:34 -0800 Subject: [PATCH 26/36] move to IProcessEnvService where appropriate in default shell logic (#118271) * move to IProcessEnvService where appropriate * change distro --- package.json | 2 +- src/vs/base/node/shell.ts | 4 ++-- src/vs/platform/environment/node/shellEnv.ts | 2 +- src/vs/workbench/api/node/extHostTerminalService.ts | 4 ++-- .../terminal/electron-browser/terminal.contribution.ts | 5 ++++- .../terminal/electron-browser/terminalInstanceService.ts | 9 +++++++-- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 145df3d7839..788cc9872d7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.55.0", - "distro": "0357427beb5cd348177cd1ed381cd740082966c4", + "distro": "01f21bd70c49582992ba219c57b78d1c94bb5da7", "author": { "name": "Microsoft Corporation" }, diff --git a/src/vs/base/node/shell.ts b/src/vs/base/node/shell.ts index cacc2da4db2..98861c0dd07 100644 --- a/src/vs/base/node/shell.ts +++ b/src/vs/base/node/shell.ts @@ -13,7 +13,7 @@ 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 async function getSystemShell(p: platform.Platform, env = process.env as platform.IProcessEnvironment): Promise { +export async function getSystemShell(p: platform.Platform, env: platform.IProcessEnvironment): Promise { if (p === platform.Platform.Windows) { if (platform.isWindows) { return getSystemShellWindows(); @@ -25,7 +25,7 @@ export async function getSystemShell(p: platform.Platform, env = process.env as return getSystemShellUnixLike(p, env); } -export function getSystemShellSync(p: platform.Platform, env = process.env as platform.IProcessEnvironment): string { +export function getSystemShellSync(p: platform.Platform, env: platform.IProcessEnvironment): string { if (p === platform.Platform.Windows) { if (platform.isWindows) { return getSystemShellWindowsSync(env); diff --git a/src/vs/platform/environment/node/shellEnv.ts b/src/vs/platform/environment/node/shellEnv.ts index 9454f1d4730..c2d7594b124 100644 --- a/src/vs/platform/environment/node/shellEnv.ts +++ b/src/vs/platform/environment/node/shellEnv.ts @@ -79,7 +79,7 @@ async function doResolveUnixShellEnv(logService: ILogService): Promise this._defaultShell = s); + getSystemShell(platform.platform, process.env as platform.IProcessEnvironment).then(s => this._defaultShell = s); this._updateLastActiveWorkspace(); this._updateVariableResolver(); @@ -83,7 +83,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { return terminalEnvironment.getDefaultShell( fetchSetting, this._isWorkspaceShellAllowed, - this._defaultShell ?? getSystemShellSync(platform.platform), + this._defaultShell ?? getSystemShellSync(platform.platform, process.env as platform.IProcessEnvironment), process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), process.env.windir, terminalEnvironment.createVariableResolver(this._lastActiveWorkspace, this._variableResolver), 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 0c11faaf0b3..6b8955477c1 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts @@ -13,6 +13,8 @@ import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/co import { getTerminalShellConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { getSystemShell } from 'vs/base/node/shell'; +import { process } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { Platform } from 'vs/base/common/platform'; // This file contains additional desktop-only contributions on top of those in browser/ @@ -25,4 +27,5 @@ workbenchRegistry.registerWorkbenchContribution(TerminalNativeContribution, Life // Register configurations const configurationRegistry = Registry.as(Extensions.Configuration); -getTerminalShellConfiguration(getSystemShell).then(config => configurationRegistry.registerConfiguration(config)); +const systemShell = async (p: Platform) => getSystemShell(p, await process.getShellEnv()); +getTerminalShellConfiguration(systemShell).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 32673f92f70..facc10fc01b 100644 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts @@ -13,6 +13,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; +import { IShellEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/shellEnvironmentService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; import type { Terminal as XTermTerminal } from 'xterm'; import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; @@ -34,7 +35,8 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst @IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService, @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, @IHistoryService private readonly _historyService: IHistoryService, - @ILogService private readonly _logService: ILogService + @ILogService private readonly _logService: ILogService, + @IShellEnvironmentService private readonly _shellEnvironmentService: IShellEnvironmentService ) { super(); } @@ -76,10 +78,11 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(); let lastActiveWorkspace = activeWorkspaceRootUri ? this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri) : undefined; lastActiveWorkspace = lastActiveWorkspace === null ? undefined : lastActiveWorkspace; + const shell = getDefaultShell( (key) => this._configurationService.inspect(key), isWorkspaceShellAllowed, - await getSystemShell(platformOverride), + await getSystemShell(platformOverride, await this._shellEnvironmentService.getShellEnv()), process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), process.env.windir, createVariableResolver(lastActiveWorkspace, this._configurationResolverService), @@ -87,6 +90,7 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst useAutomationShell, platformOverride ); + const args = getDefaultShellArgs( (key) => this._configurationService.inspect(key), isWorkspaceShellAllowed, @@ -95,6 +99,7 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst this._logService, platformOverride ); + return Promise.resolve({ shell, args }); } From 7d96db1e51b3485da03daf6df9bdb4f1caaa2af4 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Mon, 8 Mar 2021 20:54:17 -0800 Subject: [PATCH 27/36] Make underlined link buttons blue to match the styling of similar buttons --- .../contrib/search/browser/media/searchview.css | 4 ---- .../contrib/search/browser/searchView.ts | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/search/browser/media/searchview.css b/src/vs/workbench/contrib/search/browser/media/searchview.css index 057347da4d8..d8a34d36a1c 100644 --- a/src/vs/workbench/contrib/search/browser/media/searchview.css +++ b/src/vs/workbench/contrib/search/browser/media/searchview.css @@ -303,10 +303,6 @@ box-sizing: border-box; } -.monaco-workbench .search-view a.prominent { - text-decoration: underline; -} - /* Theming */ .monaco-workbench.vs .search-view .search-widget .toggle-replace-button:hover { diff --git a/src/vs/workbench/contrib/search/browser/searchView.ts b/src/vs/workbench/contrib/search/browser/searchView.ts index a0db321f838..7d282f99aad 100644 --- a/src/vs/workbench/contrib/search/browser/searchView.ts +++ b/src/vs/workbench/contrib/search/browser/searchView.ts @@ -45,7 +45,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener'; import { IProgress, IProgressService, IProgressStep } 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 { diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, editorFindMatchHighlight, editorFindMatchHighlightBorder, foreground, listActiveSelectionForeground } from 'vs/platform/theme/common/colorRegistry'; +import { diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, editorFindMatchHighlight, editorFindMatchHighlightBorder, foreground, listActiveSelectionForeground, textLinkActiveForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry'; import { IColorTheme, ICssStyleCollector, 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'; @@ -1910,6 +1910,17 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) = collector.addRule(`.search-view .message { color: ${fgWithOpacity}; }`); } } + + const link = theme.getColor(textLinkForeground); + if (link) { + collector.addRule(`.monaco-workbench .search-view .message a { color: ${link}; }`); + } + + const activeLink = theme.getColor(textLinkActiveForeground); + if (activeLink) { + collector.addRule(`.monaco-workbench .search-view .message a:hover, + .monaco-workbench .search-view .message a:active { color: ${activeLink}; }`); + } }); class SearchLinkButton extends Disposable { @@ -1917,7 +1928,7 @@ class SearchLinkButton extends Disposable { constructor(label: string, handler: (e: dom.EventLike) => unknown, tooltip?: string) { super(); - this.element = $('a.pointer.prominent', { tabindex: 0, title: tooltip }, label); + this.element = $('a.pointer', { tabindex: 0, title: tooltip }, label); this.addEventHandlers(handler); } From 9d3a1d9f59cb4802f8121629f2d49b875511e5bc Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 9 Mar 2021 09:30:43 +0100 Subject: [PATCH 28/36] Fix #118443 --- test/automation/src/extensions.ts | 8 +++---- .../src/areas/extensions/extensions.test.ts | 21 ++++--------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/test/automation/src/extensions.ts b/test/automation/src/extensions.ts index b2bedb8f5c8..3e71563a202 100644 --- a/test/automation/src/extensions.ts +++ b/test/automation/src/extensions.ts @@ -24,10 +24,6 @@ export class Extensions extends Viewlet { await this.code.waitForActiveElement(SEARCH_BOX); } - async waitForExtensionsViewlet(): Promise { - await this.code.waitForElement(SEARCH_BOX); - } - async searchForExtension(id: string): Promise { await this.code.waitAndClick(SEARCH_BOX); await this.code.waitForActiveElement(SEARCH_BOX); @@ -40,6 +36,10 @@ export class Extensions extends Viewlet { await this.code.waitAndClick(`div.extensions-viewlet[id="workbench.view.extensions"] .monaco-list-row[data-extension-id="${id}"]`); } + async closeExtension(title: string): Promise { + await this.code.waitAndClick(`.tabs-container div.tab[title="Extension: ${title}"] div.tab-actions a.action-label.codicon.codicon-close`); + } + async installExtension(id: string, waitUntilEnabled: boolean): 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`); diff --git a/test/smoke/src/areas/extensions/extensions.test.ts b/test/smoke/src/areas/extensions/extensions.test.ts index 1abdd6ee13c..1ae9d679eec 100644 --- a/test/smoke/src/areas/extensions/extensions.test.ts +++ b/test/smoke/src/areas/extensions/extensions.test.ts @@ -10,32 +10,19 @@ export function setup() { it(`install and activate vscode-smoketest-check extension`, async function () { const app = this.app as Application; - if (app.quality === Quality.Dev || app.web /* https://github.com/microsoft/vscode/issues/118443 */) { + if (app.quality === Quality.Dev) { this.skip(); - return; - } - - if (!app.web) { - await app.workbench.settingsEditor.addUserSetting('webview.experimental.useIframes', 'true'); } await app.workbench.extensions.openExtensionsViewlet(); await app.workbench.extensions.installExtension('michelkaporin.vscode-smoketest-check', true); - await app.workbench.extensions.waitForExtensionsViewlet(); + // Close extension editor because keybindings dispatch is not working when web views are opened and focused + // https://github.com/microsoft/vscode/issues/110276 + await app.workbench.extensions.closeExtension('vscode-smoketest-check'); await app.workbench.quickaccess.runCommand('Smoke Test Check'); - await app.workbench.statusbar.waitForStatusbarText('smoke test', 'VS Code Smoke Test Check'); - }); - - after(async function () { - const app = this.app as Application; - if (app.web) { - return; - } - - await app.workbench.settingsEditor.clearUserSettings(); }); }); From fa6d38a99b33ccc405a46e70bd9f66b8f24689c3 Mon Sep 17 00:00:00 2001 From: isidor Date: Tue, 9 Mar 2021 09:32:32 +0100 Subject: [PATCH 29/36] change nls ids --- src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts | 2 +- src/vs/workbench/contrib/extensions/browser/extensionsViews.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts index 94fdc443a78..39750747195 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts @@ -272,7 +272,7 @@ export class ExtensionsTree extends WorkbenchAsyncDataTree>{ getAriaLabel(extensionData: IExtensionData): string { const extension = extensionData.extension; - return localize('extension-arialabel', "{0}, {1}, {2}, {3}", extension.displayName, extension.version, extension.publisherDisplayName, extension.description); + return localize('extension.arialabel', "{0}, {1}, {2}, {3}", extension.displayName, extension.version, extension.publisherDisplayName, extension.description); }, getWidgetAriaLabel(): string { return localize('extensions', "Extensions"); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts index dc2515142c5..f9a525c8466 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts @@ -165,7 +165,7 @@ export class ExtensionsListView extends ViewPane { horizontalScrolling: false, accessibilityProvider: >{ getAriaLabel(extension: IExtension | null): string { - return extension ? localize('extension-arialabel', "{0}, {1}, {2}, {3}", extension.displayName, extension.version, extension.publisherDisplayName, extension.description) : ''; + return extension ? localize('extension.arialabel', "{0}, {1}, {2}, {3}", extension.displayName, extension.version, extension.publisherDisplayName, extension.description) : ''; }, getWidgetAriaLabel(): string { return localize('extensions', "Extensions"); From edfbf27e3afaa703dc6eaecec80963566dc5b649 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Tue, 9 Mar 2021 09:34:12 +0100 Subject: [PATCH 30/36] #118443 - change name --- test/smoke/src/areas/extensions/extensions.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/smoke/src/areas/extensions/extensions.test.ts b/test/smoke/src/areas/extensions/extensions.test.ts index 1ae9d679eec..8154cc465f0 100644 --- a/test/smoke/src/areas/extensions/extensions.test.ts +++ b/test/smoke/src/areas/extensions/extensions.test.ts @@ -7,7 +7,7 @@ import { Application, Quality } from '../../../../automation'; export function setup() { describe('Extensions', () => { - it(`install and activate vscode-smoketest-check extension`, async function () { + it(`install and enable vscode-smoketest-check extension`, async function () { const app = this.app as Application; if (app.quality === Quality.Dev) { From 425316c3764f0f0ff9332a566fa679f0bc906a3f Mon Sep 17 00:00:00 2001 From: Alex Ross Date: Tue, 9 Mar 2021 10:52:58 +0100 Subject: [PATCH 31/36] Add a compose language (#118042) --- extensions/yaml/package.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/extensions/yaml/package.json b/extensions/yaml/package.json index 0673aeda746..fc7503a482b 100644 --- a/extensions/yaml/package.json +++ b/extensions/yaml/package.json @@ -13,6 +13,22 @@ }, "contributes": { "languages": [ + { + "id": "dockercompose", + "aliases": [ + "Compose", + "compose" + ], + "filenamePatterns": [ + "compose.yml", + "compose.yaml", + "compose.*.yml", + "compose.*.yaml", + "*docker*compose*.yml", + "*docker*compose*.yaml" + ], + "configuration": "./language-configuration.json" + }, { "id": "yaml", "aliases": [ @@ -30,6 +46,11 @@ } ], "grammars": [ + { + "language": "dockercompose", + "scopeName": "source.yaml", + "path": "./syntaxes/yaml.tmLanguage.json" + }, { "language": "yaml", "scopeName": "source.yaml", From 30d699fa104f30fc78b9f597cfa92683c1cf6c8a Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 9 Mar 2021 11:11:11 +0100 Subject: [PATCH 32/36] on fire active notebook change event when something changed, https://github.com/microsoft/vscode/issues/118470 --- src/vs/workbench/api/common/extHostNotebook.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/api/common/extHostNotebook.ts b/src/vs/workbench/api/common/extHostNotebook.ts index c027bc91d59..254a0ba8cca 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -776,7 +776,9 @@ export class ExtHostNotebookController implements ExtHostNotebookShape { } else if (delta.newActiveEditor) { this._activeNotebookEditor = this._editors.get(delta.newActiveEditor)?.editor; } - this._onDidChangeActiveNotebookEditor.fire(this._activeNotebookEditor?.editor); + if (delta.newActiveEditor !== undefined) { + this._onDidChangeActiveNotebookEditor.fire(this._activeNotebookEditor?.editor); + } } createNotebookCellStatusBarItemInternal(cell: vscode.NotebookCell, alignment: extHostTypes.NotebookCellStatusBarAlignment | undefined, priority: number | undefined) { From bcfcb539ab52a0d6a23c36a0302f924fd793ea4f Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 9 Mar 2021 11:28:41 +0100 Subject: [PATCH 33/36] unit test for https://github.com/microsoft/vscode/issues/118470 --- .../test/browser/api/extHostNotebook.test.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/vs/workbench/test/browser/api/extHostNotebook.test.ts b/src/vs/workbench/test/browser/api/extHostNotebook.test.ts index 1014b49cd96..d313a38230e 100644 --- a/src/vs/workbench/test/browser/api/extHostNotebook.test.ts +++ b/src/vs/workbench/test/browser/api/extHostNotebook.test.ts @@ -353,4 +353,25 @@ suite('NotebookCell#Document', function () { assert.strictEqual(event.changes[0].items[0].document.isClosed, false); assert.strictEqual(event.changes[0].items[1].document.isClosed, false); }); + + + test('Opening a notebook results in VS Code firing the event onDidChangeActiveNotebookEditor twice #118470', function () { + let count = 0; + extHostNotebooks.onDidChangeActiveNotebookEditor(() => count += 1); + + extHostNotebooks.$acceptDocumentAndEditorsDelta({ + addedEditors: [{ + documentUri: notebookUri, + id: '_notebook_editor_2', + selections: [{ start: 0, end: 1 }], + visibleRanges: [] + }] + }); + + extHostNotebooks.$acceptDocumentAndEditorsDelta({ + newActiveEditor: '_notebook_editor_2' + }); + + assert.strictEqual(count, 1); + }); }); From 0e04c15de4f380e271b97c0649d3d6f3dff12109 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 9 Mar 2021 11:31:12 +0100 Subject: [PATCH 34/36] assert unsetting of active notebook needs null, https://github.com/microsoft/vscode/issues/118470 --- .../test/browser/api/extHostNotebook.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/vs/workbench/test/browser/api/extHostNotebook.test.ts b/src/vs/workbench/test/browser/api/extHostNotebook.test.ts index d313a38230e..0a80acfb1a9 100644 --- a/src/vs/workbench/test/browser/api/extHostNotebook.test.ts +++ b/src/vs/workbench/test/browser/api/extHostNotebook.test.ts @@ -374,4 +374,19 @@ suite('NotebookCell#Document', function () { assert.strictEqual(count, 1); }); + + test('unset active notebook editor', function () { + + const editor = extHostNotebooks.activeNotebookEditor; + assert.ok(editor !== undefined); + + extHostNotebooks.$acceptDocumentAndEditorsDelta({ newActiveEditor: undefined }); + assert.ok(extHostNotebooks.activeNotebookEditor === editor); + + extHostNotebooks.$acceptDocumentAndEditorsDelta({}); + assert.ok(extHostNotebooks.activeNotebookEditor === editor); + + extHostNotebooks.$acceptDocumentAndEditorsDelta({ newActiveEditor: null }); + assert.ok(extHostNotebooks.activeNotebookEditor === undefined); + }); }); From 98a22a957a2b52b191f91518a5a8caf6e274eec5 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Tue, 9 Mar 2021 12:40:37 +0100 Subject: [PATCH 35/36] declare cancellation support for openNotebook and wire it up, exempt notebook content provider from provider naming rules --- .eslintrc.json | 3 ++- src/vs/vscode.proposed.d.ts | 26 +++++++++---------- .../api/browser/mainThreadNotebook.ts | 4 +-- .../workbench/api/common/extHost.protocol.ts | 2 +- .../workbench/api/common/extHostNotebook.ts | 4 +-- .../notebook/browser/notebookServiceImpl.ts | 4 +-- .../notebook/common/notebookEditorModel.ts | 2 +- .../notebook/common/notebookService.ts | 5 ++-- 8 files changed, 26 insertions(+), 24 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 1085686e464..e21cd93df02 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -985,7 +985,8 @@ "CustomEditorProvider", "CustomReadonlyEditorProvider", "TerminalLinkProvider", - "AuthenticationProvider" + "AuthenticationProvider", + "NotebookContentProvider" ] } ], diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index fc6dd15a2df..59100d9aaf9 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -1555,27 +1555,27 @@ declare module 'vscode' { readonly backupId?: string; } + // todo@API use openNotebookDOCUMENT to align with openCustomDocument etc? export interface NotebookContentProvider { + readonly options?: NotebookDocumentContentOptions; readonly onDidChangeNotebookContentOptions?: Event; + + // todo@API remove! against separation of data provider and renderer + // eslint-disable-next-line vscode-dts-cancellation + resolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Thenable; + /** * Content providers should always use [file system providers](#FileSystemProvider) to * resolve the raw content for `uri` as the resouce is not necessarily a file on disk. */ - // eslint-disable-next-line vscode-dts-provider-naming - openNotebook(uri: Uri, openContext: NotebookDocumentOpenContext): NotebookData | Thenable; - // eslint-disable-next-line vscode-dts-provider-naming - // eslint-disable-next-line vscode-dts-cancellation - resolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Thenable; - // eslint-disable-next-line vscode-dts-provider-naming - saveNotebook(document: NotebookDocument, cancellation: CancellationToken): Thenable; - // eslint-disable-next-line vscode-dts-provider-naming - saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Thenable; - // eslint-disable-next-line vscode-dts-provider-naming - backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, cancellation: CancellationToken): Thenable; + openNotebook(uri: Uri, openContext: NotebookDocumentOpenContext, token: CancellationToken): NotebookData | Thenable; - // ??? - // provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult; + saveNotebook(document: NotebookDocument, token: CancellationToken): Thenable; + + saveNotebookAs(targetResource: Uri, document: NotebookDocument, token: CancellationToken): Thenable; + + backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, token: CancellationToken): Thenable; } export namespace notebook { diff --git a/src/vs/workbench/api/browser/mainThreadNotebook.ts b/src/vs/workbench/api/browser/mainThreadNotebook.ts index 0788ef388a5..02742173831 100644 --- a/src/vs/workbench/api/browser/mainThreadNotebook.ts +++ b/src/vs/workbench/api/browser/mainThreadNotebook.ts @@ -403,8 +403,8 @@ export class MainThreadNotebooks implements MainThreadNotebookShape { contentOptions.transientOutputs = newOptions.transientOutputs; }, viewOptions: options.viewOptions, - openNotebook: async (viewType: string, uri: URI, backupId?: string) => { - const data = await this._proxy.$openNotebook(viewType, uri, backupId); + openNotebook: async (viewType: string, uri: URI, backupId: string | undefined, token: CancellationToken) => { + const data = await this._proxy.$openNotebook(viewType, uri, backupId, token); return { data, transientOptions: contentOptions diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 297d95919fb..7269a63dcfd 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1863,7 +1863,7 @@ export interface ExtHostNotebookShape { $executeNotebookKernelFromProvider(handle: number, uri: UriComponents, kernelId: string, cellHandle: number | undefined): Promise; $cancelNotebookKernelFromProvider(handle: number, uri: UriComponents, kernelId: string, cellHandle: number | undefined): Promise; $onDidReceiveMessage(editorId: string, rendererId: string | undefined, message: unknown): void; - $openNotebook(viewType: string, uri: UriComponents, backupId?: string): Promise; + $openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, token: CancellationToken): Promise; $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise; $saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise; $backupNotebook(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 254a0ba8cca..144390d8790 100644 --- a/src/vs/workbench/api/common/extHostNotebook.ts +++ b/src/vs/workbench/api/common/extHostNotebook.ts @@ -497,9 +497,9 @@ export class ExtHostNotebookController implements ExtHostNotebookShape { // --- open, save, saveAs, backup - async $openNotebook(viewType: string, uri: UriComponents, backupId?: string): Promise { + async $openNotebook(viewType: string, uri: UriComponents, backupId: string | undefined, token: CancellationToken): Promise { const { provider } = this._getProviderData(viewType); - const data = await provider.openNotebook(URI.revive(uri), { backupId }); + const data = await provider.openNotebook(URI.revive(uri), { backupId }, token); return { metadata: { ...notebookDocumentMetadataDefaults, diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 619c18136d8..60c702c929f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -512,12 +512,12 @@ export class NotebookService extends Disposable implements INotebookService, IEd return result; } - async fetchNotebookRawData(viewType: string, uri: URI, backupId?: string): Promise<{ data: NotebookDataDto, transientOptions: TransientOptions }> { + async fetchNotebookRawData(viewType: string, uri: URI, backupId: string | undefined, token: CancellationToken): Promise<{ data: NotebookDataDto, transientOptions: TransientOptions }> { if (!await this.canResolve(viewType)) { throw new Error(`CANNOT fetch notebook data, there is NO provider for '${viewType}'`); } const provider = this._withProvider(viewType)!; - return await provider.controller.openNotebook(viewType, uri, backupId); + return await provider.controller.openNotebook(viewType, uri, backupId, token); } async save(viewType: string, resource: URI, token: CancellationToken): Promise { diff --git a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts index 13748942e86..75406e7a644 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookEditorModel.ts @@ -170,7 +170,7 @@ export class NotebookEditorModel extends EditorModel implements INotebookEditorM private async _loadFromProvider(backupId: string | undefined): Promise { - const data = await this._notebookService.fetchNotebookRawData(this.viewType, this.resource, backupId); + const data = await this._notebookService.fetchNotebookRawData(this.viewType, this.resource, backupId, CancellationToken.None); this._lastResolvedFileStat = await this._resolveStats(this.resource); if (this.isDisposed()) { diff --git a/src/vs/workbench/contrib/notebook/common/notebookService.ts b/src/vs/workbench/contrib/notebook/common/notebookService.ts index db6cea79b0e..e4a628741bf 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookService.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookService.ts @@ -22,9 +22,10 @@ export const INotebookService = createDecorator('notebookServi export interface IMainNotebookController { viewOptions?: { displayName: string; filenamePattern: (string | IRelativePattern | INotebookExclusiveDocumentFilter)[]; exclusive: boolean; }; options: { transientOutputs: boolean; transientMetadata: TransientMetadata; }; - openNotebook(viewType: string, uri: URI, backupId?: string): Promise<{ data: NotebookDataDto, transientOptions: TransientOptions; }>; resolveNotebookEditor(viewType: string, uri: URI, editorId: string): Promise; onDidReceiveMessage(editorId: string, rendererType: string | undefined, message: any): void; + + openNotebook(viewType: string, uri: URI, backupId: string | undefined, token: CancellationToken): Promise<{ data: NotebookDataDto, transientOptions: TransientOptions; }>; save(uri: URI, token: CancellationToken): Promise; saveAs(uri: URI, target: URI, token: CancellationToken): Promise; backup(uri: URI, token: CancellationToken): Promise; @@ -66,7 +67,7 @@ export interface INotebookService { getNotebookProviderResourceRoots(): URI[]; destoryNotebookDocument(viewType: string, notebook: INotebookTextModel): void; - fetchNotebookRawData(viewType: string, uri: URI, backupId?: string): Promise; + fetchNotebookRawData(viewType: string, uri: URI, backupId: string | undefined, token: CancellationToken): Promise; save(viewType: string, resource: URI, token: CancellationToken): Promise; saveAs(viewType: string, resource: URI, target: URI, token: CancellationToken): Promise; backup(viewType: string, uri: URI, token: CancellationToken): Promise; From 5ce792fcfad12cb5d12493a1ce956495fe408060 Mon Sep 17 00:00:00 2001 From: Alexandru Dima Date: Tue, 9 Mar 2021 12:58:10 +0100 Subject: [PATCH 36/36] Add SECURITY.md --- SECURITY.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000000..a050f362c15 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + +