From 0bb10ce71d1cefc398257bfdb761d292c47bff77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 9 Apr 2020 16:06:27 +0200 Subject: [PATCH 01/26] finalize SourceControlInputBox.visible fixes #90499 --- src/vs/vscode.d.ts | 5 +++++ src/vs/vscode.proposed.d.ts | 15 --------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 567eb92bbf9..e90ce2dece0 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -9763,6 +9763,11 @@ declare module 'vscode' { * A string to show as placeholder in the input box to guide the user. */ placeholder: string; + + /** + * Controls whether the input box is visible (default is `true`). + */ + visible: boolean; } interface QuickDiffProvider { diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index b0322517e6f..1e9260db2bb 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -822,21 +822,6 @@ declare module 'vscode' { //#endregion - //#region Joao: SCM Input Box - - /** - * Represents the input box in the Source Control viewlet. - */ - export interface SourceControlInputBox { - - /** - * Controls whether the input box is visible (default is `true`). - */ - visible: boolean; - } - - //#endregion - //#region Terminal data write event https://github.com/microsoft/vscode/issues/78502 export interface TerminalDataWriteEvent { From c4e78f9660c5a82ff76b65269746dd7fe18682ea Mon Sep 17 00:00:00 2001 From: rebornix Date: Tue, 14 Apr 2020 18:15:21 -0700 Subject: [PATCH 02/26] move off index --- .../notebook/browser/notebookBrowser.ts | 42 ++++ .../notebook/browser/notebookEditor.ts | 149 ++++---------- .../notebook/browser/view/notebookCellList.ts | 190 +++++++++++++++--- 3 files changed, 238 insertions(+), 143 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index b99f6d0f277..6432f30eabd 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Event } from 'vs/base/common/event'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar'; @@ -20,6 +21,9 @@ import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } fro import { CellKind, IOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { Webview } from 'vs/workbench/contrib/webview/browser/webview'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; +import { ScrollEvent } from 'vs/base/common/scrollable'; +import { IListStyles, IListOptions } from 'vs/base/browser/ui/list/listWidget'; +import { IListEvent } from 'vs/base/browser/ui/list/list'; export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey('notebookFindWidgetFocused', false); @@ -270,6 +274,44 @@ export interface INotebookEditor { hideFind(): void; } +export interface INotebookCellList { + onWillScroll: Event; + onDidChangeFocus: Event>; + onDidChangeContentHeight: Event; + scrollTop: number; + scrollHeight: number; + scrollLeft: number; + length: number; + rowsContainer: HTMLElement; + readonly onDidRemoveOutput: Event; + detachViewModel(): void; + attachViewModel(viewModel: NotebookViewModel): void; + clear(): void; + focusElement(element: ICellViewModel): void; + selectElement(element: ICellViewModel): void; + getFocusedElements(): ICellViewModel[]; + revealElementInView(element: ICellViewModel): void; + revealElementInCenterIfOutsideViewport(element: ICellViewModel): void; + revealElementInCenter(element: ICellViewModel): void; + revealElementLineInView(element: ICellViewModel, line: number): void; + revealElementLineInCenter(element: ICellViewModel, line: number): void; + revealElementLineInCenterIfOutsideViewport(element: ICellViewModel, line: number): void; + revealElementRangeInView(element: ICellViewModel, range: Range): void; + revealElementRangeInCenter(element: ICellViewModel, range: Range): void; + revealElementRangeInCenterIfOutsideViewport(element: ICellViewModel, range: Range): void; + domElementOfElement(element: ICellViewModel): HTMLElement | null; + focusView(): void; + getAbsoluteTopOfElement(element: ICellViewModel): number; + triggerScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent): void; + updateElementHeight2(element: ICellViewModel, size: number): void; + domFocus(): void; + setCellSelection(element: ICellViewModel, range: Range): void; + style(styles: IListStyles): void; + updateOptions(options: IListOptions): void; + layout(height?: number, width?: number): void; + dispose(): void; +} + export interface BaseCellRenderTemplate { container: HTMLElement; cellContainer: HTMLElement; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index f18eba035e6..0de0d3c931c 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -30,7 +30,7 @@ import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; import { EditorOptions, IEditorCloseEvent, IEditorMemento } from 'vs/workbench/common/editor'; import { CELL_MARGIN, CELL_RUN_GUTTER, EDITOR_TOP_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants'; import { NotebookFindWidget } from 'vs/workbench/contrib/notebook/browser/contrib/notebookFindWidget'; -import { CellEditState, CellFocusMode, ICellViewModel, INotebookEditor, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, ICellViewModel, INotebookEditor, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, INotebookCellList } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService'; import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList'; @@ -70,7 +70,7 @@ export class NotebookCodeEditors implements ICompositeCodeEditor { readonly onDidChangeActiveEditor: Event = this._onDidChangeActiveEditor.event; constructor( - private _list: NotebookCellList, + private _list: INotebookCellList, private _renderedEditors: Map ) { _list.onDidChangeFocus(_e => this._onDidChangeActiveEditor.fire(this), undefined, this._disposables); @@ -93,7 +93,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { private body!: HTMLElement; private webview: BackLayerWebView | null = null; private webviewTransparentCover: HTMLElement | null = null; - private list: NotebookCellList | undefined; + private list: INotebookCellList | undefined; private control: ICompositeCodeEditor | undefined; private renderedEditors: Map = new Map(); private eventDispatcher: NotebookEventDispatcher | undefined; @@ -275,7 +275,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { this.webview = null; } - this.list?.splice(0, this.list?.length); + this.list?.clear(); super.onHide(); } @@ -348,12 +348,13 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { private detachModel() { this.localStore.clear(); + this.list?.detachViewModel(); this.notebookViewModel?.dispose(); this.notebookViewModel = undefined; this.webview?.clearInsets(); this.webview?.clearPreloadsCache(); this.findWidget.clear(); - this.list?.splice(0, this.list?.length || 0); + this.list?.clear(); } private async attachModel(input: NotebookEditorInput, model: NotebookEditorModel) { @@ -373,36 +374,6 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { this.editorEditable?.set(e.source.editable); })); - this.localStore.add(this.notebookViewModel.onDidChangeViewCells((e) => { - if (e.synchronous) { - e.splices.reverse().forEach((diff) => { - // remove output in the webview - for (let i = diff[0]; i < diff[0] + diff[1]; i++) { - const cell = this.list?.element(i); - cell?.model.outputs.forEach(output => { - this.removeInset(output); - }); - } - - this.list?.splice(diff[0], diff[1], diff[2]); - }); - } else { - DOM.scheduleAtNextAnimationFrame(() => { - e.splices.reverse().forEach((diff) => { - // remove output in the webview - for (let i = diff[0]; i < diff[0] + diff[1]; i++) { - const cell = this.list?.element(i); - cell?.model.outputs.forEach(output => { - this.removeInset(output); - }); - } - - this.list?.splice(diff[0], diff[1], diff[2]); - }); - }); - } - })); - this.webview?.updateRendererPreloads(this.notebookViewModel.renderers); this.localStore.add(this.list!.onWillScroll(e => { @@ -418,9 +389,8 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { if (this.webview?.insetMapping) { this.webview?.insetMapping.forEach((value, key) => { - let cell = value.cell; - let index = this.notebookViewModel!.getViewCellIndex(cell); - let cellTop = this.list?.getAbsoluteTop(index) || 0; + const cell = value.cell; + const cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0; if (this.webview!.shouldUpdateInset(cell, key, cellTop)) { updateItems.push({ cell: cell, @@ -436,8 +406,12 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { } })); - this.list?.splice(0, 0, this.notebookViewModel!.viewCells as CellViewModel[]); - this.list?.layout(); + this.list!.attachViewModel(this.notebookViewModel); + this.localStore.add(this.list!.onDidRemoveOutput(output => { + this.removeInset(output); + })); + + this.list!.layout(); if (viewState?.scrollPosition !== undefined) { this.list!.scrollTop = viewState!.scrollPosition.top; @@ -507,92 +481,47 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { //#region Editor Features selectElement(cell: ICellViewModel) { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.setSelection([index]); - this.list?.setFocus([index]); - } + this.list?.selectElement(cell); } revealInView(cell: ICellViewModel) { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealInView(index); - } + this.list?.revealElementInView(cell); } revealInCenterIfOutsideViewport(cell: ICellViewModel) { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealInCenterIfOutsideViewport(index); - } + this.list?.revealElementInCenterIfOutsideViewport(cell); } revealInCenter(cell: ICellViewModel) { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealInCenter(index); - } + this.list?.revealElementInCenter(cell); } revealLineInView(cell: ICellViewModel, line: number): void { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealLineInView(index, line); - } + this.list?.revealElementLineInView(cell, line); } revealLineInCenter(cell: ICellViewModel, line: number) { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealLineInCenter(index, line); - } + this.list?.revealElementLineInCenter(cell, line); } revealLineInCenterIfOutsideViewport(cell: ICellViewModel, line: number) { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealLineInCenterIfOutsideViewport(index, line); - } + this.list?.revealElementLineInCenterIfOutsideViewport(cell, line); } revealRangeInView(cell: ICellViewModel, range: Range): void { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealRangeInView(index, range); - } + this.list?.revealElementRangeInView(cell, range); } revealRangeInCenter(cell: ICellViewModel, range: Range): void { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealRangeInCenter(index, range); - } + this.list?.revealElementRangeInCenter(cell, range); } revealRangeInCenterIfOutsideViewport(cell: ICellViewModel, range: Range): void { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.revealRangeInCenterIfOutsideViewport(index, range); - } + this.list?.revealElementRangeInCenterIfOutsideViewport(cell, range); } setCellSelection(cell: ICellViewModel, range: Range): void { - const index = this.notebookViewModel?.getViewCellIndex(cell); - - if (index !== undefined) { - this.list?.setCellSelection(index, range); - } + this.list?.setCellSelection(cell, range); } changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => any): any { @@ -617,10 +546,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { //#region Cell operations async layoutNotebookCell(cell: ICellViewModel, height: number): Promise { let relayout = (cell: ICellViewModel, height: number) => { - let index = this.notebookViewModel!.getViewCellIndex(cell); - if (index >= 0) { - this.list?.updateElementHeight(index, height); - } + this.list?.updateElementHeight2(cell, height); }; let r: () => void; @@ -638,7 +564,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { const index = this.notebookViewModel!.getViewCellIndex(cell); const insertIndex = direction === 'above' ? index : index + 1; const newCell = this.notebookViewModel!.createCell(insertIndex, initialText.split(/\r?\n/g), language, type, true); - this.list?.setFocus([insertIndex]); + this.list?.focusElement(newCell); if (type === CellKind.Markdown) { newCell.editState = CellEditState.Editing; @@ -646,7 +572,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { let r: () => void; DOM.scheduleAtNextAnimationFrame(() => { - this.list?.revealInCenterIfOutsideViewport(insertIndex); + this.list?.revealElementInCenterIfOutsideViewport(cell); r(); }); @@ -686,7 +612,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { let r: () => void; DOM.scheduleAtNextAnimationFrame(() => { - this.list?.revealInCenterIfOutsideViewport(index + 1); + this.list?.revealElementInCenterIfOutsideViewport(this.notebookViewModel!.viewCells[index + 1]); r(); }); @@ -785,18 +711,15 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { } focusNotebookCell(cell: ICellViewModel, focusEditor: boolean) { - const index = this.notebookViewModel!.getViewCellIndex(cell); - if (focusEditor) { - this.list?.setFocus([index]); - this.list?.setSelection([index]); + this.selectElement(cell); this.list?.focusView(); cell.editState = CellEditState.Editing; cell.focusMode = CellFocusMode.Editor; this.revealInCenterIfOutsideViewport(cell); } else { - let itemDOM = this.list?.domElementAtIndex(index); + let itemDOM = this.list?.domElementOfElement(cell); if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) { (document.activeElement as HTMLElement).blur(); } @@ -804,8 +727,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { cell.editState = CellEditState.Preview; cell.focusMode = CellFocusMode.Editor; - this.list?.setFocus([index]); - this.list?.setSelection([index]); + this.selectElement(cell); this.revealInCenterIfOutsideViewport(cell); this.list?.focusView(); } @@ -839,13 +761,10 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { let preloads = this.notebookViewModel!.renderers; if (!this.webview!.insetMapping.has(output)) { - let index = this.notebookViewModel!.getViewCellIndex(cell); - let cellTop = this.list?.getAbsoluteTop(index) || 0; - + let cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0; this.webview!.createInset(cell, output, cellTop, offset, shadowContent, preloads); } else { - let index = this.notebookViewModel!.getViewCellIndex(cell); - let cellTop = this.list?.getAbsoluteTop(index) || 0; + let cellTop = this.list?.getAbsoluteTopOfElement(cell) || 0; let scrollTop = this.list?.scrollTop || 0; this.webview!.updateViewScrollTop(-scrollTop, [{ cell: cell, output: output, cellTop: cellTop }]); diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index 7e9c4102ab4..8956936a1ba 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -5,7 +5,7 @@ import * as DOM from 'vs/base/browser/dom'; import { IListRenderer, IListVirtualDelegate, ListError } from 'vs/base/browser/ui/list/list'; -import { Event } from 'vs/base/common/event'; +import { Event, Emitter } from 'vs/base/common/event'; import { ScrollEvent } from 'vs/base/common/scrollable'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; @@ -14,14 +14,14 @@ import { IListService, IWorkbenchListOptions, WorkbenchList } from 'vs/platform/ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { isMacintosh } from 'vs/base/common/platform'; -import { NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NOTEBOOK_EDITOR_CURSOR_BOUNDARY, IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { Range } from 'vs/editor/common/core/range'; -import { CellRevealType, CellRevealPosition, CursorAtBoundary } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellRevealType, CellRevealPosition, CursorAtBoundary, ICellViewModel, INotebookCellList } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; +import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { IStyleController, IListStyles } from 'vs/base/browser/ui/list/listWidget'; -export class NotebookCellList extends WorkbenchList implements IDisposable, IStyleController { +export class NotebookCellList extends WorkbenchList implements IDisposable, IStyleController, INotebookCellList { get onWillScroll(): Event { return this.view.onWillScroll; } get rowsContainer(): HTMLElement { @@ -29,7 +29,14 @@ export class NotebookCellList extends WorkbenchList implements ID } private _previousSelectedElements: CellViewModel[] = []; private _localDisposableStore = new DisposableStore(); + private _viewModelStore = new DisposableStore(); private styleElement?: HTMLStyleElement; + + private readonly _onDidRemoveOutput = new Emitter(); + readonly onDidRemoveOutput: Event = this._onDidRemoveOutput.event; + + private _viewModel: NotebookViewModel | null = null; + constructor( private listUser: string, container: HTMLElement, @@ -107,7 +114,140 @@ export class NotebookCellList extends WorkbenchList implements ID } - domElementAtIndex(index: number): HTMLElement | null { + detachViewModel() { + this._viewModelStore.clear(); + this._viewModel = null; + } + + attachViewModel(model: NotebookViewModel) { + this._viewModel = model; + this._viewModelStore.add(model.onDidChangeViewCells((e) => { + if (e.synchronous) { + e.splices.reverse().forEach((diff) => { + // remove output in the webview + for (let i = diff[0]; i < diff[0] + diff[1]; i++) { + const cell = this.element(i); + cell?.model.outputs.forEach(output => { + this._onDidRemoveOutput.fire(output); + }); + } + + this.splice(diff[0], diff[1], diff[2]); + }); + } else { + DOM.scheduleAtNextAnimationFrame(() => { + e.splices.reverse().forEach((diff) => { + // remove output in the webview + for (let i = diff[0]; i < diff[0] + diff[1]; i++) { + const cell = this.element(i); + cell?.model.outputs.forEach(output => { + this._onDidRemoveOutput.fire(output); + }); + } + + this.splice(diff[0], diff[1], diff[2]); + }); + }); + } + })); + + this.splice(0, 0, model.viewCells as CellViewModel[]); + } + + clear() { + this.splice(0, this.length); + } + + focusElement(cell: ICellViewModel) { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this.setFocus([index]); + } + } + selectElement(cell: ICellViewModel) { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this.setSelection([index]); + this.setFocus([index]); + } + } + + revealElementInView(cell: ICellViewModel) { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealInView(index); + } + } + + revealElementInCenterIfOutsideViewport(cell: ICellViewModel) { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealInCenterIfOutsideViewport(index); + } + } + + revealElementInCenter(cell: ICellViewModel) { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealInCenter(index); + } + } + + revealElementLineInView(cell: ICellViewModel, line: number): void { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealLineInView(index, line); + } + } + + revealElementLineInCenter(cell: ICellViewModel, line: number) { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealLineInCenter(index, line); + } + } + + revealElementLineInCenterIfOutsideViewport(cell: ICellViewModel, line: number) { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealLineInCenterIfOutsideViewport(index, line); + } + } + + revealElementRangeInView(cell: ICellViewModel, range: Range): void { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealRangeInView(index, range); + } + } + + revealElementRangeInCenter(cell: ICellViewModel, range: Range): void { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealRangeInCenter(index, range); + } + } + + revealElementRangeInCenterIfOutsideViewport(cell: ICellViewModel, range: Range): void { + const index = this._viewModel?.getViewCellIndex(cell); + + if (index !== undefined) { + this._revealRangeInCenterIfOutsideViewport(index, range); + } + } + + domElementOfElement(element: ICellViewModel): HTMLElement | null { + const index = this._viewModel!.getViewCellIndex(element); return this.view.domElement(index); } @@ -115,7 +255,8 @@ export class NotebookCellList extends WorkbenchList implements ID this.view.domNode.focus(); } - getAbsoluteTop(index: number): number { + getAbsoluteTopOfElement(element: ICellViewModel): number { + let index = this._viewModel!.getViewCellIndex(element); if (index < 0 || index >= this.length) { throw new ListError(this.listUser, `Invalid index ${index}`); } @@ -123,22 +264,15 @@ export class NotebookCellList extends WorkbenchList implements ID return this.view.elementTop(index); } - getElementHeight(index: number): number { - if (index < 0 || index >= this.length) { - throw new ListError(this.listUser, `Invalid index ${index}`); - } - - return this.view.elementHeight(index); - } - triggerScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent) { this.view.triggerScrollFromMouseWheelEvent(browserEvent); } - updateElementHeight(index: number, size: number): void { + + updateElementHeight2(element: ICellViewModel, size: number): void { + const index = this._viewModel!.getViewCellIndex(element); const focused = this.getSelection(); this.view.updateElementHeight(index, size, focused.length ? focused[0] : null); - // this.view.updateElementHeight(index, size, null); } // override @@ -221,11 +355,11 @@ export class NotebookCellList extends WorkbenchList implements ID } } - revealLineInView(index: number, line: number) { + private _revealLineInView(index: number, line: number) { this._revealRangeInternal(index, new Range(line, 1, line, 1), CellRevealType.Line); } - revealRangeInView(index: number, range: Range): void { + private _revealRangeInView(index: number, range: Range): void { this._revealRangeInternal(index, range, CellRevealType.Range); } @@ -253,11 +387,11 @@ export class NotebookCellList extends WorkbenchList implements ID } } - revealLineInCenter(index: number, line: number) { + private _revealLineInCenter(index: number, line: number) { this._revealRangeInCenterInternal(index, new Range(line, 1, line, 1), CellRevealType.Line); } - revealRangeInCenter(index: number, range: Range): void { + private _revealRangeInCenter(index: number, range: Range): void { this._revealRangeInCenterInternal(index, range, CellRevealType.Range); } @@ -303,11 +437,11 @@ export class NotebookCellList extends WorkbenchList implements ID } } - revealLineInCenterIfOutsideViewport(index: number, line: number) { + private _revealLineInCenterIfOutsideViewport(index: number, line: number) { this._revealRangeInCenterIfOutsideViewportInternal(index, new Range(line, 1, line, 1), CellRevealType.Line); } - revealRangeInCenterIfOutsideViewport(index: number, range: Range): void { + private _revealRangeInCenterIfOutsideViewport(index: number, range: Range): void { this._revealRangeInCenterIfOutsideViewportInternal(index, range, CellRevealType.Range); } @@ -335,20 +469,20 @@ export class NotebookCellList extends WorkbenchList implements ID this.view.setScrollTop(newViewItemOffset); } - revealInView(index: number) { + private _revealInView(index: number) { this._revealInternal(index, true, CellRevealPosition.Top); } - revealInCenter(index: number) { + private _revealInCenter(index: number) { this._revealInternal(index, false, CellRevealPosition.Center); } - revealInCenterIfOutsideViewport(index: number) { + private _revealInCenterIfOutsideViewport(index: number) { this._revealInternal(index, true, CellRevealPosition.Center); } - setCellSelection(index: number, range: Range) { - const element = this.view.element(index); + setCellSelection(cell: ICellViewModel, range: Range) { + const element = cell as CellViewModel; if (element.editorAttached) { element.setSelection(range); } else { From b7a88acb0d3f6265ff5bb92f0458751eb3e6f4fc Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 15 Apr 2020 08:26:03 -0700 Subject: [PATCH 03/26] Extract get view cell index. --- .../notebook/browser/view/notebookCellList.ts | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index 8956936a1ba..b5c2bd60892 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -158,15 +158,19 @@ export class NotebookCellList extends WorkbenchList implements ID this.splice(0, this.length); } + getViewCellIndex(cell: ICellViewModel) { + return this._viewModel?.getViewCellIndex(cell); + } + focusElement(cell: ICellViewModel) { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this.setFocus([index]); } } selectElement(cell: ICellViewModel) { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this.setSelection([index]); @@ -175,7 +179,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementInView(cell: ICellViewModel) { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealInView(index); @@ -183,7 +187,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementInCenterIfOutsideViewport(cell: ICellViewModel) { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealInCenterIfOutsideViewport(index); @@ -191,7 +195,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementInCenter(cell: ICellViewModel) { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealInCenter(index); @@ -199,7 +203,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementLineInView(cell: ICellViewModel, line: number): void { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealLineInView(index, line); @@ -207,7 +211,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementLineInCenter(cell: ICellViewModel, line: number) { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealLineInCenter(index, line); @@ -215,7 +219,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementLineInCenterIfOutsideViewport(cell: ICellViewModel, line: number) { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealLineInCenterIfOutsideViewport(index, line); @@ -223,7 +227,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementRangeInView(cell: ICellViewModel, range: Range): void { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealRangeInView(index, range); @@ -231,7 +235,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementRangeInCenter(cell: ICellViewModel, range: Range): void { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealRangeInCenter(index, range); @@ -239,7 +243,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementRangeInCenterIfOutsideViewport(cell: ICellViewModel, range: Range): void { - const index = this._viewModel?.getViewCellIndex(cell); + const index = this.getViewCellIndex(cell); if (index !== undefined) { this._revealRangeInCenterIfOutsideViewport(index, range); @@ -247,8 +251,12 @@ export class NotebookCellList extends WorkbenchList implements ID } domElementOfElement(element: ICellViewModel): HTMLElement | null { - const index = this._viewModel!.getViewCellIndex(element); - return this.view.domElement(index); + const index = this.getViewCellIndex(element); + if (index !== undefined) { + return this.view.domElement(index); + } + + return null; } focusView() { From 5aa884765c1ad4e6b7bd96321d2fbf116840c3d3 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 15 Apr 2020 08:48:22 -0700 Subject: [PATCH 04/26] differentiate view index and model index --- .../notebook/browser/view/notebookCellList.ts | 122 +++++++++--------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index b5c2bd60892..e9e5254c6b6 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -158,19 +158,19 @@ export class NotebookCellList extends WorkbenchList implements ID this.splice(0, this.length); } - getViewCellIndex(cell: ICellViewModel) { + getViewIndex(cell: ICellViewModel) { return this._viewModel?.getViewCellIndex(cell); } focusElement(cell: ICellViewModel) { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this.setFocus([index]); } } selectElement(cell: ICellViewModel) { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this.setSelection([index]); @@ -179,7 +179,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementInView(cell: ICellViewModel) { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealInView(index); @@ -187,7 +187,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementInCenterIfOutsideViewport(cell: ICellViewModel) { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealInCenterIfOutsideViewport(index); @@ -195,7 +195,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementInCenter(cell: ICellViewModel) { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealInCenter(index); @@ -203,7 +203,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementLineInView(cell: ICellViewModel, line: number): void { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealLineInView(index, line); @@ -211,7 +211,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementLineInCenter(cell: ICellViewModel, line: number) { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealLineInCenter(index, line); @@ -219,7 +219,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementLineInCenterIfOutsideViewport(cell: ICellViewModel, line: number) { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealLineInCenterIfOutsideViewport(index, line); @@ -227,7 +227,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementRangeInView(cell: ICellViewModel, range: Range): void { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealRangeInView(index, range); @@ -235,7 +235,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementRangeInCenter(cell: ICellViewModel, range: Range): void { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealRangeInCenter(index, range); @@ -243,7 +243,7 @@ export class NotebookCellList extends WorkbenchList implements ID } revealElementRangeInCenterIfOutsideViewport(cell: ICellViewModel, range: Range): void { - const index = this.getViewCellIndex(cell); + const index = this.getViewIndex(cell); if (index !== undefined) { this._revealRangeInCenterIfOutsideViewport(index, range); @@ -251,7 +251,7 @@ export class NotebookCellList extends WorkbenchList implements ID } domElementOfElement(element: ICellViewModel): HTMLElement | null { - const index = this.getViewCellIndex(element); + const index = this.getViewIndex(element); if (index !== undefined) { return this.view.domElement(index); } @@ -297,13 +297,13 @@ export class NotebookCellList extends WorkbenchList implements ID super.domFocus(); } - private _revealRange(index: number, range: Range, revealType: CellRevealType, newlyCreated: boolean, alignToBottom: boolean) { - const element = this.view.element(index); + private _revealRange(viewIndex: number, range: Range, revealType: CellRevealType, newlyCreated: boolean, alignToBottom: boolean) { + const element = this.view.element(viewIndex); const scrollTop = this.view.getScrollTop(); const wrapperBottom = scrollTop + this.view.renderHeight; const startLineNumber = range.startLineNumber; const lineOffset = element.getLineScrollTopOffset(startLineNumber); - const elementTop = this.view.elementTop(index); + const elementTop = this.view.elementTop(viewIndex); const lineTop = elementTop + lineOffset; // TODO@rebornix 30 ---> line height * 1.5 @@ -331,16 +331,16 @@ export class NotebookCellList extends WorkbenchList implements ID // List items have real dynamic heights, which means after we set `scrollTop` based on the `elementTop(index)`, the element at `index` might still be removed from the view once all relayouting tasks are done. // For example, we scroll item 10 into the view upwards, in the first round, items 7, 8, 9, 10 are all in the viewport. Then item 7 and 8 resize themselves to be larger and finally item 10 is removed from the view. // To ensure that item 10 is always there, we need to scroll item 10 to the top edge of the viewport. - private _revealRangeInternal(index: number, range: Range, revealType: CellRevealType) { + private _revealRangeInternal(viewIndex: number, range: Range, revealType: CellRevealType) { const scrollTop = this.view.getScrollTop(); const wrapperBottom = scrollTop + this.view.renderHeight; - const elementTop = this.view.elementTop(index); - const element = this.view.element(index); + const elementTop = this.view.elementTop(viewIndex); + const element = this.view.element(viewIndex); if (element.editorAttached) { - this._revealRange(index, range, revealType, false, false); + this._revealRange(viewIndex, range, revealType, false, false); } else { - const elementHeight = this.view.elementHeight(index); + const elementHeight = this.view.elementHeight(viewIndex); let upwards = false; if (elementTop + elementHeight < scrollTop) { @@ -358,24 +358,24 @@ export class NotebookCellList extends WorkbenchList implements ID }); editorAttachedPromise.then(() => { - this._revealRange(index, range, revealType, true, upwards); + this._revealRange(viewIndex, range, revealType, true, upwards); }); } } - private _revealLineInView(index: number, line: number) { - this._revealRangeInternal(index, new Range(line, 1, line, 1), CellRevealType.Line); + private _revealLineInView(viewIndex: number, line: number) { + this._revealRangeInternal(viewIndex, new Range(line, 1, line, 1), CellRevealType.Line); } - private _revealRangeInView(index: number, range: Range): void { - this._revealRangeInternal(index, range, CellRevealType.Range); + private _revealRangeInView(viewIndex: number, range: Range): void { + this._revealRangeInternal(viewIndex, range, CellRevealType.Range); } - private _revealRangeInCenterInternal(index: number, range: Range, revealType: CellRevealType) { - const reveal = (index: number, range: Range, revealType: CellRevealType) => { - const element = this.view.element(index); + private _revealRangeInCenterInternal(viewIndex: number, range: Range, revealType: CellRevealType) { + const reveal = (viewIndex: number, range: Range, revealType: CellRevealType) => { + const element = this.view.element(viewIndex); let lineOffset = element.getLineScrollTopOffset(range.startLineNumber); - let lineOffsetInView = this.view.elementTop(index) + lineOffset; + let lineOffsetInView = this.view.elementTop(viewIndex) + lineOffset; this.view.setScrollTop(lineOffsetInView - this.view.renderHeight / 2); if (revealType === CellRevealType.Range) { @@ -383,31 +383,31 @@ export class NotebookCellList extends WorkbenchList implements ID } }; - const elementTop = this.view.elementTop(index); + const elementTop = this.view.elementTop(viewIndex); const viewItemOffset = elementTop; this.view.setScrollTop(viewItemOffset - this.view.renderHeight / 2); - const element = this.view.element(index); + const element = this.view.element(viewIndex); if (!element.editorAttached) { - getEditorAttachedPromise(element).then(() => reveal(index, range, revealType)); + getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType)); } else { - reveal(index, range, revealType); + reveal(viewIndex, range, revealType); } } - private _revealLineInCenter(index: number, line: number) { - this._revealRangeInCenterInternal(index, new Range(line, 1, line, 1), CellRevealType.Line); + private _revealLineInCenter(viewIndex: number, line: number) { + this._revealRangeInCenterInternal(viewIndex, new Range(line, 1, line, 1), CellRevealType.Line); } - private _revealRangeInCenter(index: number, range: Range): void { - this._revealRangeInCenterInternal(index, range, CellRevealType.Range); + private _revealRangeInCenter(viewIndex: number, range: Range): void { + this._revealRangeInCenterInternal(viewIndex, range, CellRevealType.Range); } - private _revealRangeInCenterIfOutsideViewportInternal(index: number, range: Range, revealType: CellRevealType) { - const reveal = (index: number, range: Range, revealType: CellRevealType) => { - const element = this.view.element(index); + private _revealRangeInCenterIfOutsideViewportInternal(viewIndex: number, range: Range, revealType: CellRevealType) { + const reveal = (viewIndex: number, range: Range, revealType: CellRevealType) => { + const element = this.view.element(viewIndex); let lineOffset = element.getLineScrollTopOffset(range.startLineNumber); - let lineOffsetInView = this.view.elementTop(index) + lineOffset; + let lineOffsetInView = this.view.elementTop(viewIndex) + lineOffset; this.view.setScrollTop(lineOffsetInView - this.view.renderHeight / 2); if (revealType === CellRevealType.Range) { @@ -417,21 +417,21 @@ export class NotebookCellList extends WorkbenchList implements ID const scrollTop = this.view.getScrollTop(); const wrapperBottom = scrollTop + this.view.renderHeight; - const elementTop = this.view.elementTop(index); + const elementTop = this.view.elementTop(viewIndex); const viewItemOffset = elementTop; - const element = this.view.element(index); + const element = this.view.element(viewIndex); if (viewItemOffset < scrollTop || viewItemOffset > wrapperBottom) { // let it render this.view.setScrollTop(viewItemOffset - this.view.renderHeight / 2); // after rendering, it might be pushed down due to markdown cell dynamic height - const elementTop = this.view.elementTop(index); + const elementTop = this.view.elementTop(viewIndex); this.view.setScrollTop(elementTop - this.view.renderHeight / 2); // reveal editor if (!element.editorAttached) { - getEditorAttachedPromise(element).then(() => reveal(index, range, revealType)); + getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType)); } else { // for example markdown } @@ -440,27 +440,27 @@ export class NotebookCellList extends WorkbenchList implements ID element.revealRangeInCenter(range); } else { // for example, markdown cell in preview mode - getEditorAttachedPromise(element).then(() => reveal(index, range, revealType)); + getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType)); } } } - private _revealLineInCenterIfOutsideViewport(index: number, line: number) { - this._revealRangeInCenterIfOutsideViewportInternal(index, new Range(line, 1, line, 1), CellRevealType.Line); + private _revealLineInCenterIfOutsideViewport(viewIndex: number, line: number) { + this._revealRangeInCenterIfOutsideViewportInternal(viewIndex, new Range(line, 1, line, 1), CellRevealType.Line); } - private _revealRangeInCenterIfOutsideViewport(index: number, range: Range): void { - this._revealRangeInCenterIfOutsideViewportInternal(index, range, CellRevealType.Range); + private _revealRangeInCenterIfOutsideViewport(viewIndex: number, range: Range): void { + this._revealRangeInCenterIfOutsideViewportInternal(viewIndex, range, CellRevealType.Range); } - private _revealInternal(index: number, ignoreIfInsideViewport: boolean, revealPosition: CellRevealPosition) { - if (index >= this.view.length) { + private _revealInternal(viewIndex: number, ignoreIfInsideViewport: boolean, revealPosition: CellRevealPosition) { + if (viewIndex >= this.view.length) { return; } const scrollTop = this.view.getScrollTop(); const wrapperBottom = scrollTop + this.view.renderHeight; - const elementTop = this.view.elementTop(index); + const elementTop = this.view.elementTop(viewIndex); if (ignoreIfInsideViewport && elementTop >= scrollTop && elementTop < wrapperBottom) { // inside the viewport @@ -472,21 +472,21 @@ export class NotebookCellList extends WorkbenchList implements ID this.view.setScrollTop(viewItemOffset); // second scroll as markdown cell is dynamic - const newElementTop = this.view.elementTop(index); + const newElementTop = this.view.elementTop(viewIndex); const newViewItemOffset = revealPosition === CellRevealPosition.Top ? newElementTop : (newElementTop - this.view.renderHeight / 2); this.view.setScrollTop(newViewItemOffset); } - private _revealInView(index: number) { - this._revealInternal(index, true, CellRevealPosition.Top); + private _revealInView(viewIndex: number) { + this._revealInternal(viewIndex, true, CellRevealPosition.Top); } - private _revealInCenter(index: number) { - this._revealInternal(index, false, CellRevealPosition.Center); + private _revealInCenter(viewIndex: number) { + this._revealInternal(viewIndex, false, CellRevealPosition.Center); } - private _revealInCenterIfOutsideViewport(index: number) { - this._revealInternal(index, true, CellRevealPosition.Center); + private _revealInCenterIfOutsideViewport(viewIndex: number) { + this._revealInternal(viewIndex, true, CellRevealPosition.Center); } setCellSelection(cell: ICellViewModel, range: Range) { From 990b095467315b3d2c1ce9562f4aa85d4730276c Mon Sep 17 00:00:00 2001 From: ConnorSkees <39542938+ConnorSkees@users.noreply.github.com> Date: Wed, 15 Apr 2020 13:41:40 -0400 Subject: [PATCH 05/26] strip \\?\ prefix from absolute paths --- .../contrib/terminal/browser/links/terminalLinkManager.ts | 2 ++ .../terminal/test/browser/links/terminalLinkManager.test.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts index f32c2106512..5951880b987 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts @@ -544,6 +544,8 @@ export class TerminalLinkManager extends DisposableStore { return null; } link = this.osPath.join(this._processCwd, link); + } else { + link = link.replace(/^\\\\\?\\/, ''); } } else { if (!this._processCwd) { diff --git a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts index ad7fd6a94e6..5d9b0cf45c8 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkManager.test.ts @@ -254,6 +254,7 @@ suite('Workbench - TerminalLinkHandler', () => { assert.equal(linkHandler.preprocessPath('~/src/file3'), 'C:\\Users\\Me\\src\\file3'); assert.equal(linkHandler.preprocessPath('~\\src\\file4'), 'C:\\Users\\Me\\src\\file4'); assert.equal(linkHandler.preprocessPath('C:\\absolute\\path\\file5'), 'C:\\absolute\\path\\file5'); + assert.equal(linkHandler.preprocessPath('\\\\?\\C:\\absolute\\path\\extended\\file6'), 'C:\\absolute\\path\\extended\\file6'); }); test('Windows - spaces', () => { const linkHandler = new TestTerminalLinkManager(new TestXterm() as any, { From 9fb10835a8f5e92819707bc4a5bca61de30514b2 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 15 Apr 2020 16:54:51 -0700 Subject: [PATCH 06/26] Set hidden areas on the list --- .../notebook/browser/notebookBrowser.ts | 69 ++++++ .../notebook/browser/notebookEditor.ts | 6 +- .../notebook/browser/view/notebookCellList.ts | 75 ++++++- .../browser/viewModel/notebookViewModel.ts | 197 +++++++++++++++++- .../common/model/notebookTextModel.ts | 4 + .../contrib/notebook/common/notebookCommon.ts | 1 + .../notebook/test/notebookViewModel.test.ts | 149 ++++++++++++- 7 files changed, 491 insertions(+), 10 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts index 6432f30eabd..abc238d7980 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts @@ -253,6 +253,11 @@ export interface INotebookEditor { */ revealRangeInCenterIfOutsideViewport(cell: ICellViewModel, range: Range): void; + /** + * Set hidden areas on cell text models. + */ + setHiddenAreas(_ranges: ICellRange[]): boolean; + setCellSelection(cell: ICellViewModel, selection: Range): void; /** @@ -299,6 +304,7 @@ export interface INotebookCellList { revealElementRangeInView(element: ICellViewModel, range: Range): void; revealElementRangeInCenter(element: ICellViewModel, range: Range): void; revealElementRangeInCenterIfOutsideViewport(element: ICellViewModel, range: Range): void; + setHiddenAreas(_ranges: ICellRange[]): boolean; domElementOfElement(element: ICellViewModel): HTMLElement | null; focusView(): void; getAbsoluteTopOfElement(element: ICellViewModel): number; @@ -391,3 +397,66 @@ export enum CursorAtBoundary { Bottom, Both } + +/** + * [start, start + length] + */ +export interface ICellRange { + start: number; + length: number; +} + + +/** + * @param _ranges + */ +export function reduceCellRanges(_ranges: ICellRange[]): ICellRange[] { + if (!_ranges.length) { + return []; + } + + let ranges = _ranges.sort((a, b) => a.start - b.start); + let result: ICellRange[] = []; + let currentRangeStart = ranges[0].start; + let currentRangeEnd = ranges[0].start + ranges[0].length; + + for (let i = 0, len = ranges.length; i < len; i++) { + let range = ranges[i]; + + if (range.start > currentRangeEnd) { + result.push({ start: currentRangeStart, length: currentRangeEnd - currentRangeStart }); + currentRangeStart = range.start; + currentRangeEnd = range.start + range.length; + } else if (range.start + range.length > currentRangeEnd) { + currentRangeEnd = range.start + range.length; + } + } + + result.push({ start: currentRangeStart, length: currentRangeEnd - currentRangeStart }); + return result; +} + +export function getVisibleCells(cells: CellViewModel[], hiddenRanges: ICellRange[]) { + if (!hiddenRanges.length) { + return cells; + } + + let start = 0; + let hiddenRangeIndex = 0; + let result: any[] = []; + + while (start < cells.length && hiddenRangeIndex < hiddenRanges.length) { + if (start < hiddenRanges[hiddenRangeIndex].start) { + result.push(...cells.slice(start, hiddenRanges[hiddenRangeIndex].start)); + } + + start = hiddenRanges[hiddenRangeIndex].start + hiddenRanges[hiddenRangeIndex].length; + hiddenRangeIndex++; + } + + if (start < cells.length) { + result.push(...cells.slice(start)); + } + + return result; +} diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 0de0d3c931c..db9be67f1a6 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -30,7 +30,7 @@ import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor'; import { EditorOptions, IEditorCloseEvent, IEditorMemento } from 'vs/workbench/common/editor'; import { CELL_MARGIN, CELL_RUN_GUTTER, EDITOR_TOP_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants'; import { NotebookFindWidget } from 'vs/workbench/contrib/notebook/browser/contrib/notebookFindWidget'; -import { CellEditState, CellFocusMode, ICellViewModel, INotebookEditor, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, INotebookCellList } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellEditState, CellFocusMode, ICellViewModel, INotebookEditor, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, INotebookCellList, ICellRange } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService'; import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList'; @@ -528,6 +528,10 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { return this.notebookViewModel?.changeDecorations(callback); } + setHiddenAreas(_ranges: ICellRange[]): boolean { + return this.list!.setHiddenAreas(_ranges); + } + //#endregion //#region Find Delegate diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index e9e5254c6b6..f8e0f1c2e9b 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -14,12 +14,13 @@ import { IListService, IWorkbenchListOptions, WorkbenchList } from 'vs/platform/ import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { isMacintosh } from 'vs/base/common/platform'; -import { NOTEBOOK_EDITOR_CURSOR_BOUNDARY, IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { NOTEBOOK_EDITOR_CURSOR_BOUNDARY, IOutput, diff } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { Range } from 'vs/editor/common/core/range'; -import { CellRevealType, CellRevealPosition, CursorAtBoundary, ICellViewModel, INotebookCellList } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellRevealType, CellRevealPosition, CursorAtBoundary, ICellViewModel, INotebookCellList, ICellRange, reduceCellRanges, getVisibleCells } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { IStyleController, IListStyles } from 'vs/base/browser/ui/list/listWidget'; +import { TrackedRangeStickiness } from 'vs/editor/common/model'; export class NotebookCellList extends WorkbenchList implements IDisposable, IStyleController, INotebookCellList { get onWillScroll(): Event { return this.view.onWillScroll; } @@ -36,6 +37,7 @@ export class NotebookCellList extends WorkbenchList implements ID readonly onDidRemoveOutput: Event = this._onDidRemoveOutput.event; private _viewModel: NotebookViewModel | null = null; + private _hiddenRangeIds: string[] = []; constructor( private listUser: string, @@ -132,7 +134,7 @@ export class NotebookCellList extends WorkbenchList implements ID }); } - this.splice(diff[0], diff[1], diff[2]); + this.splice2(diff[0], diff[1], diff[2]); }); } else { DOM.scheduleAtNextAnimationFrame(() => { @@ -145,17 +147,78 @@ export class NotebookCellList extends WorkbenchList implements ID }); } - this.splice(diff[0], diff[1], diff[2]); + this.splice2(diff[0], diff[1], diff[2]); }); }); } })); - this.splice(0, 0, model.viewCells as CellViewModel[]); + this.splice2(0, 0, model.viewCells as CellViewModel[]); } clear() { - this.splice(0, this.length); + super.splice(0, this.length); + } + + setHiddenAreas(_ranges: ICellRange[]): boolean { + const newRanges = reduceCellRanges(_ranges); + // delete old tracking ranges + const oldRanges = this._hiddenRangeIds.map(id => this._viewModel!.getTrackedRange(id)).filter(range => range !== null) as ICellRange[]; + if (newRanges.length === oldRanges.length) { + let hasDifference = false; + for (let i = 0; i < newRanges.length; i++) { + if (!(newRanges[i].start === oldRanges[i].start && newRanges[i].length === oldRanges[i].length)) { + hasDifference = true; + break; + } + } + + if (!hasDifference) { + return false; + } + } + + this._hiddenRangeIds.forEach(id => this._viewModel!.setTrackedRange(id, null, TrackedRangeStickiness.GrowsOnlyWhenTypingAfter)); + const hiddenAreaIds = newRanges.map(range => this._viewModel!.setTrackedRange(null, range, TrackedRangeStickiness.GrowsOnlyWhenTypingAfter)).filter(id => id !== null) as string[]; + + this._hiddenRangeIds = hiddenAreaIds; + + this.updateHiddenAreasInView(oldRanges, newRanges); + return true; + } + + /** + * oldRanges and newRanges are all reduced and sorted. + */ + updateHiddenAreasInView(oldRanges: ICellRange[], newRanges: ICellRange[]) { + const oldViewCellEntries: CellViewModel[] = getVisibleCells(this._viewModel!.viewCells as CellViewModel[], oldRanges); + const oldViewCellMapping = new Set(); + oldViewCellEntries.forEach(cell => { + oldViewCellMapping.add(cell.uri.toString()); + }); + + const newViewCellEntries: CellViewModel[] = getVisibleCells(this._viewModel!.viewCells as CellViewModel[], newRanges); + + const viewDiffs = diff(oldViewCellEntries, newViewCellEntries, a => { + return oldViewCellMapping.has(a.uri.toString()); + }); + + viewDiffs.reverse().forEach((diff) => { + // remove output in the webview + for (let i = diff.start; i < diff.start + diff.deleteCount; i++) { + const cell = this.element(i); + cell?.model.outputs.forEach(output => { + this._onDidRemoveOutput.fire(output); + }); + } + + this.splice2(diff.start, diff.deleteCount, diff.toInsert); + }); + } + + splice2(start: number, deleteCount: number, elements: CellViewModel[] = []): void { + // we need to convert start and delete count based on hidden ranges + super.splice(start, deleteCount, elements); } getViewIndex(cell: ICellViewModel) { diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index 7da92b3f0d5..bb0222d9004 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -10,11 +10,11 @@ import { URI } from 'vs/base/common/uri'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { IModelDeltaDecoration } from 'vs/editor/common/model'; +import { IModelDeltaDecoration, TrackedRangeStickiness, IModelDecorationOptions } from 'vs/editor/common/model'; import { WorkspaceTextEdit } from 'vs/editor/common/modes'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; -import { CellFindMatch, CellEditState, ICellViewModel, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { CellFindMatch, CellEditState, ICellViewModel, NotebookLayoutInfo, ICellRange } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; import { DeleteCellEdit, InsertCellEdit, MoveCellEdit } from 'vs/workbench/contrib/notebook/browser/viewModel/cellEdit'; import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel'; @@ -23,6 +23,7 @@ import { CellKind, ICell } from 'vs/workbench/contrib/notebook/common/notebookCo import { NotebookEventDispatcher, NotebookMetadataChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; +import * as strings from 'vs/base/common/strings'; export interface INotebookEditorViewState { editingCells: { [key: number]: boolean }; @@ -59,6 +60,70 @@ export interface INotebookViewCellsUpdateEvent { splices: NotebookViewCellsSplice[]; } +import { IntervalTree, IntervalNode } from 'vs/editor/common/model/intervalTree'; +import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; + +class DecorationsTree { + private readonly _decorationsTree: IntervalTree; + + constructor() { + this._decorationsTree = new IntervalTree(); + } + + public intervalSearch(start: number, end: number, filterOwnerId: number, filterOutValidation: boolean, cachedVersionId: number): IntervalNode[] { + const r1 = this._decorationsTree.intervalSearch(start, end, filterOwnerId, filterOutValidation, cachedVersionId); + return r1; + } + + public search(filterOwnerId: number, filterOutValidation: boolean, overviewRulerOnly: boolean, cachedVersionId: number): IntervalNode[] { + return this._decorationsTree.search(filterOwnerId, filterOutValidation, cachedVersionId); + + } + + public collectNodesFromOwner(ownerId: number): IntervalNode[] { + const r1 = this._decorationsTree.collectNodesFromOwner(ownerId); + return r1; + } + + public collectNodesPostOrder(): IntervalNode[] { + const r1 = this._decorationsTree.collectNodesPostOrder(); + return r1; + } + + public insert(node: IntervalNode): void { + this._decorationsTree.insert(node); + } + + public delete(node: IntervalNode): void { + this._decorationsTree.delete(node); + } + + public resolveNode(node: IntervalNode, cachedVersionId: number): void { + this._decorationsTree.resolveNode(node, cachedVersionId); + } + + public acceptReplace(offset: number, length: number, textLength: number, forceMoveMarkers: boolean): void { + this._decorationsTree.acceptReplace(offset, length, textLength, forceMoveMarkers); + } +} + +const TRACKED_RANGE_OPTIONS = [ + ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges }), + ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges }), + ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.GrowsOnlyWhenTypingBefore }), + ModelDecorationOptions.register({ stickiness: TrackedRangeStickiness.GrowsOnlyWhenTypingAfter }), +]; + +function _normalizeOptions(options: IModelDecorationOptions): ModelDecorationOptions { + if (options instanceof ModelDecorationOptions) { + return options; + } + return ModelDecorationOptions.createDynamic(options); +} + +let MODEL_ID = 0; + + export class NotebookViewModel extends Disposable { private _localStore: DisposableStore = this._register(new DisposableStore()); private _viewCells: CellViewModel[] = []; @@ -117,6 +182,12 @@ export class NotebookViewModel extends Disposable { return this._layoutInfo; } + private _decorationsTree = new DecorationsTree(); + private _decorations: { [decorationId: string]: IntervalNode; } = Object.create(null); + private _lastDecorationId: number = 0; + private readonly _instanceId: string; + public readonly id: string; + constructor( public viewType: string, private _model: NotebookEditorModel, @@ -128,6 +199,10 @@ export class NotebookViewModel extends Disposable { ) { super(); + MODEL_ID++; + this.id = '$notebookViewModel' + MODEL_ID; + this._instanceId = strings.singleLetterHash(MODEL_ID); + // this._register(this._model.onDidChangeCells(e => { // this._onDidChangeViewCells.fire({ // synchronous: true, @@ -168,6 +243,119 @@ export class NotebookViewModel extends Disposable { return this._viewCells.indexOf(cell as CellViewModel); } + getVersionId() { + return this._model.notebook.versionId; + } + + getTrackedRange(id: string): ICellRange | null { + return this.getDecorationRange(id); + } + + getDecorationRange(decorationId: string): ICellRange | null { + const node = this._decorations[decorationId]; + if (!node) { + return null; + } + const versionId = this.getVersionId(); + if (node.cachedVersionId !== versionId) { + this._decorationsTree.resolveNode(node, versionId); + } + if (node.range === null) { + return { start: node.cachedAbsoluteStart - 1, length: node.cachedAbsoluteEnd - node.cachedAbsoluteStart }; + } + + return { start: node.range.startLineNumber - 1, length: node.range.endLineNumber - node.range.startLineNumber }; + } + + setTrackedRange(id: string | null, newRange: ICellRange | null, newStickiness: TrackedRangeStickiness): string | null { + const node = (id ? this._decorations[id] : null); + + if (!node) { + if (!newRange) { + return null; + } + + return this._deltaCellDecorationsImpl(0, [], [{ range: new Range(newRange.start + 1, 1, newRange.start + newRange.length + 1, 1), options: TRACKED_RANGE_OPTIONS[newStickiness] }])[0]; + } + + if (!newRange) { + // node exists, the request is to delete => delete node + this._decorationsTree.delete(node); + delete this._decorations[node.id]; + return null; + } + + this._decorationsTree.delete(node); + node.reset(this.getVersionId(), newRange.start, newRange.start + newRange.length, new Range(newRange.start + 1, 1, newRange.start + newRange.length + 1, 1)); + node.setOptions(TRACKED_RANGE_OPTIONS[newStickiness]); + this._decorationsTree.insert(node); + return node.id; + } + + private _deltaCellDecorationsImpl(ownerId: number, oldDecorationsIds: string[], newDecorations: IModelDeltaDecoration[]): string[] { + const versionId = this.getVersionId(); + + const oldDecorationsLen = oldDecorationsIds.length; + let oldDecorationIndex = 0; + + const newDecorationsLen = newDecorations.length; + let newDecorationIndex = 0; + + let result = new Array(newDecorationsLen); + while (oldDecorationIndex < oldDecorationsLen || newDecorationIndex < newDecorationsLen) { + + let node: IntervalNode | null = null; + + if (oldDecorationIndex < oldDecorationsLen) { + // (1) get ourselves an old node + do { + node = this._decorations[oldDecorationsIds[oldDecorationIndex++]]; + } while (!node && oldDecorationIndex < oldDecorationsLen); + + // (2) remove the node from the tree (if it exists) + if (node) { + this._decorationsTree.delete(node); + // this._onDidChangeDecorations.checkAffectedAndFire(node.options); + } + } + + if (newDecorationIndex < newDecorationsLen) { + // (3) create a new node if necessary + if (!node) { + const internalDecorationId = (++this._lastDecorationId); + const decorationId = `${this._instanceId};${internalDecorationId}`; + node = new IntervalNode(decorationId, 0, 0); + this._decorations[decorationId] = node; + } + + // (4) initialize node + const newDecoration = newDecorations[newDecorationIndex]; + // const range = this._validateRangeRelaxedNoAllocations(newDecoration.range); + const range = newDecoration.range; + const options = _normalizeOptions(newDecoration.options); + // const startOffset = this._buffer.getOffsetAt(range.startLineNumber, range.startColumn); + // const endOffset = this._buffer.getOffsetAt(range.endLineNumber, range.endColumn); + + node.ownerId = ownerId; + node.reset(versionId, range.startLineNumber, range.endLineNumber, Range.lift(range)); + node.setOptions(options); + // this._onDidChangeDecorations.checkAffectedAndFire(options); + + this._decorationsTree.insert(node); + + result[newDecorationIndex] = node.id; + + newDecorationIndex++; + } else { + if (node) { + delete this._decorations[node.id]; + } + } + } + + return result; + } + private _insertCellDelegate(insertIndex: number, insertCell: CellViewModel) { this._viewCells!.splice(insertIndex, 0, insertCell); this._model.insertCell(insertCell.model, insertIndex); @@ -192,6 +380,7 @@ export class NotebookViewModel extends Disposable { deleteCell: this._deleteCellDelegate.bind(this) })); + this._decorationsTree.acceptReplace(index, 0, 1, true); this._onDidChangeViewCells.fire({ synchronous: synchronous, splices: [[index, 0, [newCell]]] }); return newCell; } @@ -206,6 +395,7 @@ export class NotebookViewModel extends Disposable { deleteCell: this._deleteCellDelegate.bind(this) })); + this._decorationsTree.acceptReplace(index, 0, 1, true); this._onDidChangeViewCells.fire({ synchronous: synchronous, splices: [[index, 0, [newCell]]] }); return newCell; } @@ -223,6 +413,9 @@ export class NotebookViewModel extends Disposable { } })); + + this._decorationsTree.acceptReplace(index, 1, 0, true); + this._onDidChangeViewCells.fire({ synchronous: synchronous, splices: [[index, 1, []]] }); viewCell.dispose(); } diff --git a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts index dd089ca4434..00ad9e71fc6 100644 --- a/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts +++ b/src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts @@ -31,6 +31,10 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel private _isUntitled: boolean | undefined = undefined; private _versionId = 0; + get versionId() { + return this._versionId; + } + constructor( public handle: number, public viewType: string, diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index 90e768b9520..f787de61e26 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -164,6 +164,7 @@ export interface INotebookTextModel { viewType: string; // metadata: IMetadata; readonly uri: URI; + readonly versionId: number; languages: string[]; cells: ICell[]; renderers: Set; diff --git a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts index 2d905ea506a..d835dac31bd 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts @@ -8,12 +8,14 @@ import { URI } from 'vs/base/common/uri'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; -import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { CellKind, diff } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { withTestNotebook, TestCell } from 'vs/workbench/contrib/notebook/test/testNotebookEditor'; import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService'; import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher'; +import { TrackedRangeStickiness } from 'vs/editor/common/model'; +import { reduceCellRanges, ICellRange } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; suite('NotebookViewModel', () => { const instantiationService = new TestInstantiationService(); @@ -161,3 +163,148 @@ suite('NotebookViewModel', () => { ); }); }); + +function getVisibleCells(cells: any[], hiddenRanges: ICellRange[]) { + if (!hiddenRanges.length) { + return cells; + } + + let start = 0; + let hiddenRangeIndex = 0; + let result: any[] = []; + + while (start < cells.length && hiddenRangeIndex < hiddenRanges.length) { + if (start < hiddenRanges[hiddenRangeIndex].start) { + result.push(...cells.slice(start, hiddenRanges[hiddenRangeIndex].start)); + } + + start = hiddenRanges[hiddenRangeIndex].start + hiddenRanges[hiddenRangeIndex].length; + hiddenRangeIndex++; + } + + if (start < cells.length) { + result.push(...cells.slice(start)); + } + + return result; +} + +suite('NotebookViewModel Decorations', () => { + const instantiationService = new TestInstantiationService(); + const blukEditService = instantiationService.get(IBulkEditService); + const undoRedoService = instantiationService.stub(IUndoRedoService, () => { }); + instantiationService.spy(IUndoRedoService, 'pushElement'); + + test('tracking range', function () { + withTestNotebook( + instantiationService, + blukEditService, + undoRedoService, + [ + [['var a = 1;'], 'javascript', CellKind.Code, [], {}], + [['var b = 2;'], 'javascript', CellKind.Code, [], { editable: true, runnable: true }], + [['var c = 3;'], 'javascript', CellKind.Code, [], { editable: true, runnable: false }], + [['var d = 4;'], 'javascript', CellKind.Code, [], { editable: false, runnable: true }], + [['var e = 5;'], 'javascript', CellKind.Code, [], { editable: false, runnable: false }], + ], + (editor, viewModel) => { + const trackedId = viewModel.setTrackedRange('test', { start: 1, length: 2 }, TrackedRangeStickiness.GrowsOnlyWhenTypingAfter); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 1, + length: 2 + }); + + viewModel.insertCell(0, new TestCell(viewModel.viewType, 5, ['var d = 6;'], 'javascript', CellKind.Code, []), true); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 2, + length: 2 + }); + + viewModel.deleteCell(0, true); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 1, + length: 2 + }); + + viewModel.insertCell(3, new TestCell(viewModel.viewType, 6, ['var d = 7;'], 'javascript', CellKind.Code, []), true); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 1, + length: 3 + }); + + viewModel.deleteCell(3, true); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 1, + length: 2 + }); + + viewModel.deleteCell(1, true); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 0, + length: 2 + }); + } + ); + }); + + test('reduce range', function () { + assert.deepEqual(reduceCellRanges([ + { start: 0, length: 2 }, + { start: 1, length: 2 }, + { start: 4, length: 2 } + ]), [ + { start: 0, length: 3 }, + { start: 4, length: 2 } + ]); + + assert.deepEqual(reduceCellRanges([ + { start: 0, length: 2 }, + { start: 1, length: 2 }, + { start: 3, length: 2 } + ]), [ + { start: 0, length: 5 } + ]); + }); + + test('diff hidden ranges', function () { + assert.deepEqual(getVisibleCells([1, 2, 3, 4, 5], []), [1, 2, 3, 4, 5]); + + assert.deepEqual( + getVisibleCells( + [1, 2, 3, 4, 5], + [{ start: 1, length: 2 }] + ), + [1, 4, 5] + ); + + assert.deepEqual( + getVisibleCells( + [1, 2, 3, 4, 5, 6, 7, 8, 9], + [ + { start: 1, length: 2 }, + { start: 4, length: 2 } + ] + ), + [1, 4, 7, 8, 9] + ); + + const original = getVisibleCells( + [1, 2, 3, 4, 5, 6, 7, 8, 9], + [ + { start: 1, length: 2 }, + { start: 4, length: 2 } + ] + ); + + const modified = getVisibleCells( + [1, 2, 3, 4, 5, 6, 7, 8, 9], + [ + { start: 2, length: 3 } + ] + ); + + assert.deepEqual(diff(original, modified, (a) => { + return original.indexOf(a) >= 0; + }), [{ start: 1, deleteCount: 1, toInsert: [2, 6] }]); + }); +}); From 579bd98fa4c0c13af936ed8ca6b11dcb5c61e2bd Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 15 Apr 2020 18:02:50 -0700 Subject: [PATCH 07/26] stopPropagation noop for wheel event requested by webview --- .../notebook/browser/view/renderers/backLayerWebView.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts index 7733cf12ff2..f3c8121062e 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts @@ -343,7 +343,11 @@ export class BackLayerWebView extends Disposable { // const top = data.data.top; // console.log('ack top ', top, ' version: ', data.version, ' - ', date.getMinutes() + ':' + date.getSeconds() + ':' + date.getMilliseconds()); } else if (data.type === 'did-scroll-wheel') { - this.notebookEditor.triggerScroll(data.payload); + this.notebookEditor.triggerScroll({ + ...data.payload, + preventDefault: () => { }, + stopPropagation: () => { } + }); } return; } From 382bf5491ce465086311b02dc5aa6e56009d0a74 Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 15 Apr 2020 18:05:45 -0700 Subject: [PATCH 08/26] Show add cell above command in command palette --- .../contrib/notebook/browser/contrib/notebookActions.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts index dbfdec6c4a3..13767b58afb 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts @@ -522,7 +522,8 @@ registerAction2(class extends InsertCellCommand { super( { id: INSERT_CODE_CELL_ABOVE_COMMAND_ID, - title: localize('notebookActions.insertCodeCellAbove', "Insert Code Cell Above") + title: localize('notebookActions.insertCodeCellAbove', "Insert Code Cell Above"), + f1: true }, CellKind.Code, 'above'); @@ -578,6 +579,7 @@ registerAction2(class extends InsertCellCommand { { id: INSERT_MARKDOWN_CELL_ABOVE_COMMAND_ID, title: localize('notebookActions.insertMarkdownCellAbove', "Insert Markdown Cell Above"), + f1: true }, CellKind.Markdown, 'above'); From 6e7c820cc38588a0f7d1cbd1ebc466cebbf70fed Mon Sep 17 00:00:00 2001 From: rebornix Date: Wed, 15 Apr 2020 18:17:17 -0700 Subject: [PATCH 09/26] cell list apis honor hidden regions --- .../browser/contrib/notebookActions.ts | 107 ++++++++++++++++-- .../notebook/browser/notebookEditor.ts | 8 +- .../notebook/browser/view/notebookCellList.ts | 81 +++++++++++-- .../browser/viewModel/notebookViewModel.ts | 10 +- .../notebook/test/notebookViewModel.test.ts | 48 +++++++- 5 files changed, 222 insertions(+), 32 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts b/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts index 13767b58afb..f13fa4996ac 100644 --- a/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts +++ b/src/vs/workbench/contrib/notebook/browser/contrib/notebookActions.ts @@ -171,7 +171,7 @@ registerAction2(class extends Action2 { return; } - const idx = editor.viewModel?.getViewCellIndex(activeCell); + const idx = editor.viewModel?.getCellIndex(activeCell); if (typeof idx !== 'number') { return; } @@ -453,7 +453,7 @@ async function changeActiveCellToKind(kind: CellKind, accessor: ServicesAccessor const text = activeCell.getText(); await editor.insertNotebookCell(activeCell, kind, 'below', text); - const idx = editor.viewModel?.getViewCellIndex(activeCell); + const idx = editor.viewModel?.getCellIndex(activeCell); if (typeof idx !== 'number') { return; } @@ -862,7 +862,7 @@ registerAction2(class extends Action2 { return; } - viewModel.deleteCell(viewModel.getViewCellIndex(context.cell), true); + viewModel.deleteCell(viewModel.getCellIndex(context.cell), true); notebookService.setToCopy([context.cell.model]); } }); @@ -900,7 +900,7 @@ registerAction2(class extends Action2 { return; } - const currCellIndex = viewModel.getViewCellIndex(context!.cell); + const currCellIndex = viewModel.getCellIndex(context!.cell); pasteCells.reverse().forEach(pasteCell => { viewModel.insertCell(currCellIndex, pasteCell, true); @@ -941,7 +941,7 @@ registerAction2(class extends Action2 { return; } - const currCellIndex = viewModel.getViewCellIndex(context!.cell); + const currCellIndex = viewModel.getCellIndex(context!.cell); pasteCells.reverse().forEach(pasteCell => { viewModel.insertCell(currCellIndex + 1, pasteCell, true); @@ -1020,7 +1020,7 @@ registerAction2(class extends Action2 { const editor = context.notebookEditor; const activeCell = context.cell; - const idx = editor.viewModel?.getViewCellIndex(activeCell); + const idx = editor.viewModel?.getCellIndex(activeCell); if (typeof idx !== 'number') { return; } @@ -1059,7 +1059,7 @@ registerAction2(class extends Action2 { const editor = context.notebookEditor; const activeCell = context.cell; - const idx = editor.viewModel?.getViewCellIndex(activeCell); + const idx = editor.viewModel?.getCellIndex(activeCell); if (typeof idx !== 'number') { return; } @@ -1176,3 +1176,96 @@ registerAction2(class extends Action2 { } } }); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.notebook.testSetHiddenRanges1', + title: 'Notebook Cells set hidden ranges: 2,3,4', + category: NOTEBOOK_ACTIONS_CATEGORY, + keybinding: { + when: IsDevelopmentContext, + primary: undefined, + weight: KeybindingWeight.WorkbenchContrib + }, + f1: true + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editorService = accessor.get(IEditorService); + const resource = editorService.activeEditor?.resource; + if (!resource) { + return; + } + + const editor = getActiveNotebookEditor(editorService); + if (!editor) { + return; + } + + editor.setHiddenAreas([{ start: 1, length: 3 }]); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.notebook.testSetHiddenRanges2', + title: 'Notebook Cells set hidden ranges: 4,5', + category: NOTEBOOK_ACTIONS_CATEGORY, + keybinding: { + when: IsDevelopmentContext, + primary: undefined, + weight: KeybindingWeight.WorkbenchContrib + }, + f1: true + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editorService = accessor.get(IEditorService); + const resource = editorService.activeEditor?.resource; + if (!resource) { + return; + } + + const editor = getActiveNotebookEditor(editorService); + if (!editor) { + return; + } + + editor.setHiddenAreas([{ start: 3, length: 2 }]); + } +}); + +registerAction2(class extends Action2 { + constructor() { + super({ + id: 'workbench.action.notebook.resetHiddenAreas', + title: 'Notebook Cells reset hidden ranges', + category: NOTEBOOK_ACTIONS_CATEGORY, + keybinding: { + when: IsDevelopmentContext, + primary: undefined, + weight: KeybindingWeight.WorkbenchContrib + }, + f1: true + }); + } + + async run(accessor: ServicesAccessor): Promise { + const editorService = accessor.get(IEditorService); + const resource = editorService.activeEditor?.resource; + if (!resource) { + return; + } + + const editor = getActiveNotebookEditor(editorService); + if (!editor) { + return; + } + + editor.setHiddenAreas([]); + } +}); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index db9be67f1a6..9824516bd92 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -565,7 +565,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { async insertNotebookCell(cell: ICellViewModel, type: CellKind, direction: 'above' | 'below', initialText: string = ''): Promise { const newLanguages = this.notebookViewModel!.languages; const language = newLanguages && newLanguages.length ? newLanguages[0] : 'markdown'; - const index = this.notebookViewModel!.getViewCellIndex(cell); + const index = this.notebookViewModel!.getCellIndex(cell); const insertIndex = direction === 'above' ? index : index + 1; const newCell = this.notebookViewModel!.createCell(insertIndex, initialText.split(/\r?\n/g), language, type, true); this.list?.focusElement(newCell); @@ -585,12 +585,12 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { async deleteNotebookCell(cell: ICellViewModel): Promise { (cell as CellViewModel).save(); - const index = this.notebookViewModel!.getViewCellIndex(cell); + const index = this.notebookViewModel!.getCellIndex(cell); this.notebookViewModel!.deleteCell(index, true); } async moveCellDown(cell: ICellViewModel): Promise { - const index = this.notebookViewModel!.getViewCellIndex(cell); + const index = this.notebookViewModel!.getCellIndex(cell); if (index === this.notebookViewModel!.viewCells.length - 1) { return; } @@ -600,7 +600,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { } async moveCellUp(cell: ICellViewModel): Promise { - const index = this.notebookViewModel!.getViewCellIndex(cell); + const index = this.notebookViewModel!.getCellIndex(cell); if (index === 0) { return; } diff --git a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts index f8e0f1c2e9b..d329b3de3eb 100644 --- a/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts +++ b/src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts @@ -21,6 +21,7 @@ import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { IStyleController, IListStyles } from 'vs/base/browser/ui/list/listWidget'; import { TrackedRangeStickiness } from 'vs/editor/common/model'; +import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'; export class NotebookCellList extends WorkbenchList implements IDisposable, IStyleController, INotebookCellList { get onWillScroll(): Event { return this.view.onWillScroll; } @@ -38,6 +39,7 @@ export class NotebookCellList extends WorkbenchList implements ID private _viewModel: NotebookViewModel | null = null; private _hiddenRangeIds: string[] = []; + private hiddenRangesPrefixSum: PrefixSumComputer | null = null; constructor( private listUser: string, @@ -124,30 +126,44 @@ export class NotebookCellList extends WorkbenchList implements ID attachViewModel(model: NotebookViewModel) { this._viewModel = model; this._viewModelStore.add(model.onDidChangeViewCells((e) => { + const currentRanges = this._hiddenRangeIds.map(id => this._viewModel!.getTrackedRange(id)).filter(range => range !== null) as ICellRange[]; + const newVisibleViewCells: CellViewModel[] = getVisibleCells(this._viewModel!.viewCells as CellViewModel[], currentRanges); + + const oldVisibleViewCells: CellViewModel[] = []; + const oldViewCellMapping = new Set(); + for (let i = 0; i < this.length; i++) { + oldVisibleViewCells.push(this.element(i)); + oldViewCellMapping.add(this.element(i).uri.toString()); + } + + const viewDiffs = diff(oldVisibleViewCells, newVisibleViewCells, a => { + return oldViewCellMapping.has(a.uri.toString()); + }); + if (e.synchronous) { - e.splices.reverse().forEach((diff) => { + viewDiffs.reverse().forEach((diff) => { // remove output in the webview - for (let i = diff[0]; i < diff[0] + diff[1]; i++) { + for (let i = diff.start; i < diff.start + diff.deleteCount; i++) { const cell = this.element(i); cell?.model.outputs.forEach(output => { this._onDidRemoveOutput.fire(output); }); } - this.splice2(diff[0], diff[1], diff[2]); + this.splice2(diff.start, diff.deleteCount, diff.toInsert); }); } else { DOM.scheduleAtNextAnimationFrame(() => { - e.splices.reverse().forEach((diff) => { + viewDiffs.reverse().forEach((diff) => { // remove output in the webview - for (let i = diff[0]; i < diff[0] + diff[1]; i++) { + for (let i = diff.start; i < diff.start + diff.deleteCount; i++) { const cell = this.element(i); cell?.model.outputs.forEach(output => { this._onDidRemoveOutput.fire(output); }); } - this.splice2(diff[0], diff[1], diff[2]); + this.splice2(diff.start, diff.deleteCount, diff.toInsert); }); }); } @@ -184,6 +200,41 @@ export class NotebookCellList extends WorkbenchList implements ID this._hiddenRangeIds = hiddenAreaIds; this.updateHiddenAreasInView(oldRanges, newRanges); + + // set hidden ranges prefix sum + let start = 0; + let index = 0; + let ret: number[] = []; + + while (index < newRanges.length) { + for (let j = start; j < newRanges[index].start - 1; j++) { + ret.push(1); + } + + ret.push(newRanges[index].length + 1); + start = newRanges[index].start + newRanges[index].length; + index++; + } + + for (let i = start; i < this._viewModel!.viewCells.length; i++) { + ret.push(1); + } + + const values = new Uint32Array(ret.length); + for (let i = 0; i < ret.length; i++) { + values[i] = ret[i]; + } + + this.hiddenRangesPrefixSum = new PrefixSumComputer(values); + // console.log(ret); + // for (let i = 0; i < this.hiddenRangesPrefixSum.getCount(); i++) { + // console.log(this.hiddenRangesPrefixSum.getAccumulatedValue(i)); + // } + + // for (let i = 0; i < this._viewModel!.viewCells.length; i++) { + // console.log(this.hiddenRangesPrefixSum.getIndexOf(i)); + // } + return true; } @@ -221,8 +272,14 @@ export class NotebookCellList extends WorkbenchList implements ID super.splice(start, deleteCount, elements); } + getViewIndex(cell: ICellViewModel) { - return this._viewModel?.getViewCellIndex(cell); + const modelIndex = this._viewModel!.getCellIndex(cell); + if (!this.hiddenRangesPrefixSum) { + return modelIndex; + } + + return this.hiddenRangesPrefixSum.getIndexOf(modelIndex).index; } focusElement(cell: ICellViewModel) { @@ -327,8 +384,8 @@ export class NotebookCellList extends WorkbenchList implements ID } getAbsoluteTopOfElement(element: ICellViewModel): number { - let index = this._viewModel!.getViewCellIndex(element); - if (index < 0 || index >= this.length) { + let index = this.getViewIndex(element); + if (index === undefined || index < 0 || index >= this.length) { throw new ListError(this.listUser, `Invalid index ${index}`); } @@ -341,7 +398,11 @@ export class NotebookCellList extends WorkbenchList implements ID updateElementHeight2(element: ICellViewModel, size: number): void { - const index = this._viewModel!.getViewCellIndex(element); + const index = this.getViewIndex(element); + if (index === undefined) { + return; + } + const focused = this.getSelection(); this.view.updateElementHeight(index, size, focused.length ? focused[0] : null); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts index bb0222d9004..72fc8003eff 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel.ts @@ -239,7 +239,7 @@ export class NotebookViewModel extends Disposable { }); } - getViewCellIndex(cell: ICellViewModel) { + getCellIndex(cell: ICellViewModel) { return this._viewCells.indexOf(cell as CellViewModel); } @@ -261,10 +261,10 @@ export class NotebookViewModel extends Disposable { this._decorationsTree.resolveNode(node, versionId); } if (node.range === null) { - return { start: node.cachedAbsoluteStart - 1, length: node.cachedAbsoluteEnd - node.cachedAbsoluteStart }; + return { start: node.cachedAbsoluteStart - 1, length: node.cachedAbsoluteEnd - node.cachedAbsoluteStart + 1 }; } - return { start: node.range.startLineNumber - 1, length: node.range.endLineNumber - node.range.startLineNumber }; + return { start: node.range.startLineNumber - 1, length: node.range.endLineNumber - node.range.startLineNumber + 1 }; } setTrackedRange(id: string | null, newRange: ICellRange | null, newStickiness: TrackedRangeStickiness): string | null { @@ -275,7 +275,7 @@ export class NotebookViewModel extends Disposable { return null; } - return this._deltaCellDecorationsImpl(0, [], [{ range: new Range(newRange.start + 1, 1, newRange.start + newRange.length + 1, 1), options: TRACKED_RANGE_OPTIONS[newStickiness] }])[0]; + return this._deltaCellDecorationsImpl(0, [], [{ range: new Range(newRange.start + 1, 1, newRange.start + newRange.length, 1), options: TRACKED_RANGE_OPTIONS[newStickiness] }])[0]; } if (!newRange) { @@ -286,7 +286,7 @@ export class NotebookViewModel extends Disposable { } this._decorationsTree.delete(node); - node.reset(this.getVersionId(), newRange.start, newRange.start + newRange.length, new Range(newRange.start + 1, 1, newRange.start + newRange.length + 1, 1)); + node.reset(this.getVersionId(), newRange.start, newRange.start + newRange.length, new Range(newRange.start + 1, 1, newRange.start + newRange.length, 1)); node.setOptions(TRACKED_RANGE_OPTIONS[newStickiness]); this._decorationsTree.insert(node); return node.id; diff --git a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts index d835dac31bd..17aa55859fa 100644 --- a/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts +++ b/src/vs/workbench/contrib/notebook/test/notebookViewModel.test.ts @@ -47,12 +47,12 @@ suite('NotebookViewModel', () => { const cell = viewModel.insertCell(1, new TestCell(viewModel.viewType, 0, ['var c = 3;'], 'javascript', CellKind.Code, []), true); assert.equal(viewModel.viewCells.length, 3); assert.equal(viewModel.notebookDocument.cells.length, 3); - assert.equal(viewModel.getViewCellIndex(cell), 1); + assert.equal(viewModel.getCellIndex(cell), 1); viewModel.deleteCell(1, true); assert.equal(viewModel.viewCells.length, 2); assert.equal(viewModel.notebookDocument.cells.length, 2); - assert.equal(viewModel.getViewCellIndex(cell), -1); + assert.equal(viewModel.getCellIndex(cell), -1); } ); }); @@ -70,18 +70,18 @@ suite('NotebookViewModel', () => { const firstViewCell = viewModel.viewCells[0]; const lastViewCell = viewModel.viewCells[viewModel.viewCells.length - 1]; - const insertIndex = viewModel.getViewCellIndex(firstViewCell) + 1; + const insertIndex = viewModel.getCellIndex(firstViewCell) + 1; const cell = viewModel.insertCell(insertIndex, new TestCell(viewModel.viewType, 3, ['var c = 3;'], 'javascript', CellKind.Code, []), true); - const addedCellIndex = viewModel.getViewCellIndex(cell); + const addedCellIndex = viewModel.getCellIndex(cell); viewModel.deleteCell(addedCellIndex, true); - const secondInsertIndex = viewModel.getViewCellIndex(lastViewCell) + 1; + const secondInsertIndex = viewModel.getCellIndex(lastViewCell) + 1; const cell2 = viewModel.insertCell(secondInsertIndex, new TestCell(viewModel.viewType, 4, ['var d = 4;'], 'javascript', CellKind.Code, []), true); assert.equal(viewModel.viewCells.length, 3); assert.equal(viewModel.notebookDocument.cells.length, 3); - assert.equal(viewModel.getViewCellIndex(cell2), 2); + assert.equal(viewModel.getCellIndex(cell2), 2); } ); }); @@ -247,6 +247,42 @@ suite('NotebookViewModel Decorations', () => { ); }); + test('tracking range 2', function () { + withTestNotebook( + instantiationService, + blukEditService, + undoRedoService, + [ + [['var a = 1;'], 'javascript', CellKind.Code, [], {}], + [['var b = 2;'], 'javascript', CellKind.Code, [], { editable: true, runnable: true }], + [['var c = 3;'], 'javascript', CellKind.Code, [], { editable: true, runnable: false }], + [['var d = 4;'], 'javascript', CellKind.Code, [], { editable: false, runnable: true }], + [['var e = 5;'], 'javascript', CellKind.Code, [], { editable: false, runnable: false }], + [['var e = 6;'], 'javascript', CellKind.Code, [], { editable: false, runnable: false }], + [['var e = 7;'], 'javascript', CellKind.Code, [], { editable: false, runnable: false }], + ], + (editor, viewModel) => { + const trackedId = viewModel.setTrackedRange('test', { start: 1, length: 3 }, TrackedRangeStickiness.GrowsOnlyWhenTypingAfter); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 1, + length: 3 + }); + + viewModel.insertCell(5, new TestCell(viewModel.viewType, 8, ['var d = 9;'], 'javascript', CellKind.Code, []), true); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 1, + length: 3 + }); + + viewModel.insertCell(4, new TestCell(viewModel.viewType, 9, ['var d = 10;'], 'javascript', CellKind.Code, []), true); + assert.deepEqual(viewModel.getTrackedRange(trackedId!), { + start: 1, + length: 4 + }); + } + ); + }); + test('reduce range', function () { assert.deepEqual(reduceCellRanges([ { start: 0, length: 2 }, From ce95e8e06ef257c18c9c10c02615e4f6bbb0ca17 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 16 Apr 2020 13:26:50 +0200 Subject: [PATCH 10/26] tests - increase timeout and retries --- .../test/electron-browser/textFileService.io.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/services/textfile/test/electron-browser/textFileService.io.test.ts b/src/vs/workbench/services/textfile/test/electron-browser/textFileService.io.test.ts index 7be9d0e1c6d..67e5bcc9e29 100644 --- a/src/vs/workbench/services/textfile/test/electron-browser/textFileService.io.test.ts +++ b/src/vs/workbench/services/textfile/test/electron-browser/textFileService.io.test.ts @@ -28,7 +28,7 @@ import { readFileSync, statSync } from 'fs'; import { detectEncodingByBOM } from 'vs/base/test/node/encoding/encoding.test'; import { workbenchInstantiationService, TestNativeTextFileServiceWithEncodingOverrides } from 'vs/workbench/test/electron-browser/workbenchTestServices'; -suite('Files - TextFileService i/o', () => { +suite('Files - TextFileService i/o', function () { const parentDir = getRandomTestPath(tmpdir(), 'vsctests', 'textfileservice'); const disposables = new DisposableStore(); @@ -36,6 +36,14 @@ suite('Files - TextFileService i/o', () => { let service: ITextFileService; let testDir: string; + // Given issues such as https://github.com/microsoft/vscode/issues/78602 + // and https://github.com/microsoft/vscode/issues/92334 we see random test + // failures when accessing the native file system. To diagnose further, we + // retry node.js file access tests up to 3 times to rule out any random disk + // issue and increase the timeout. + this.retries(3); + this.timeout(1000 * 10); + setup(async () => { const instantiationService = workbenchInstantiationService(); From ad54278df419fba9ddc5a1237bc4b6cc21a2e386 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Thu, 16 Apr 2020 04:56:39 -0700 Subject: [PATCH 11/26] Add comment explaining issue --- .../contrib/terminal/browser/links/terminalLinkManager.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts index 5951880b987..406f9191a30 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts @@ -545,6 +545,8 @@ export class TerminalLinkManager extends DisposableStore { } link = this.osPath.join(this._processCwd, link); } else { + // Remove \\?\ from paths so that they share the same underlying + // uri and don't open multiple tabs for the same file link = link.replace(/^\\\\\?\\/, ''); } } else { From c7b69ce12a84001c3af572581a9d8527dcca505c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 16 Apr 2020 14:42:52 +0200 Subject: [PATCH 12/26] use yarn watchd for the default build task --- .vscode/tasks.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 30b783943e0..f68880d6f68 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -3,7 +3,7 @@ "tasks": [ { "type": "npm", - "script": "watch", + "script": "watchd", "label": "Build VS Code", "group": { "kind": "build", @@ -31,6 +31,16 @@ } } }, + { + "type": "npm", + "script": "kill-watchd", + "label": "Kill Build VS Code", + "group": "build", + "presentation": { + "reveal": "never" + }, + "problemMatcher": "$tsc" + }, { "label": "Run tests", "type": "shell", From e14cf0ff92f022d20f00bdd5b9e173af3f108a87 Mon Sep 17 00:00:00 2001 From: Miguel Solorio Date: Thu, 16 Apr 2020 06:59:48 -0700 Subject: [PATCH 13/26] Fix #95437, update account icon --- .../ui/codiconLabel/codicon/codicon.css | 2 +- .../ui/codiconLabel/codicon/codicon.ttf | Bin 58812 -> 58864 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css index 3da8d52b399..3f3f73dba4c 100644 --- a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css +++ b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.css @@ -5,7 +5,7 @@ @font-face { font-family: "codicon"; - src: url("./codicon.ttf?c49b146a6d13d30d08fbc195f20565aa") format("truetype"); + src: url("./codicon.ttf?5d4d76ab2ce5108968ad644d591a16a6") format("truetype"); } .codicon[class*='codicon-'] { diff --git a/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf b/src/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf index 18cc62f911d0fc8c1b366772a76a3f11d7bf328c..ab67bd300fc0c13ca9847283c36157cab45d84f3 100644 GIT binary patch delta 1132 zcmXw1Z%7+=7{1>nCYP98&X`z$BOlYak8Y!Wc}z zJbWGgR}c{l3$}!?uvWO01!oOr9g0@O(})N$Aic;9WCEE*mXS2_R)R=KNkVcJp;%KKU?^tBm=wliaqKcSmV@We zIp60jDWyuk@&o0U%30;QGM!tP+nD=V?o#fC>auED^+a8)Zcr!HQ|eXq4vyjV_#l1{ z-_!^-jAlklYJ0S^d01XY-kOfmUC}+(^ZGmbw1G5C8a9oH(QaHczA!;1i|M*)!L*a# zZC097J?6Oru3*!0!?I!>EYudhEb1#-Ec%VW2_G>`?Ad7B1>0OPUK}dER|1tpOJ+)* z*(v+}DdN;5DIy!lAILq2)-mFkaV%3;sWIv&YOgdw%jl2jd-OVeSY|GZmaUe(Vw6mr znP#@ib>-pmFUl94kdt;ktiV$)oh#v*U`1>%JIijfM{dSF=w5O^_aGk9Gv_(*-tr!t z?l`@{DLF4U#Vv79D!=h*eY|hAN>}w25A$(;f#0q!tRAgC^mqBE{44&y14JMhm<~J( zs)9qoc;IJ0?XzaeF4;2Q=S9-SRHd-v?CkUbO$ zjf8#-?Vg)Ix8F!KUTvIiqMEKWrNdabF}%@?H7AjIXH#Kl(lgyl@; zmH`R`gwqFD7h{4|VidMe05~gb6nHPpyx5!+Y(e1@$M+D4QIH8BY$>9`$z}x1$y%)v z3ATfQ{^ap~vOf@{sTKf~Qh`|LyFGE+cM3F9^s%g_+Q$N+#6qzFYk6mpMJ3H*KmSXv zC-aT99I2P1j>{VvNZ(xw-k&e3%$>6E$A*WfEf&^JS_r)fkf)t?M@Hq=TaWX_k@ej#{1R0$;5!p?LJ1?B`@SOL3e*e6u zugL4K$d8@e4agh@Kx_eEC3E+q4||29U+hnWH538Y$5lPx5ycahO$M;@7?cK4t2e-?6ByA=WbMfb|xkBEkfMAr7Pki6fV6 zKKl`SmVJt6VHaz5b9a#p!5+$492$K+{wUAz(ABJVZtjF0ns_~ZOF z{+|M&U`&V#1Hwt+S&_GBxtLoVDt;!yM4yS$VpKdVUK3{}h-60cLUJsnNpDN1rLRl; zCFin4K$eo1%GXN!N*5G8imS4h%BXTi`J?g@E5rJ+Jr!Tos7k3W)q3@~`ncR$K32Y7 z!L8V@ge!+DPc&N1W6hrCs%oHWtZE*Q;c@(1e6QMB{g*bZ9oMdC4|PUBisw*vL0NHC`r6z~nRynNG|>^Q3vld}I+?dMvY+O-r^GtxeS)SnpX6 z>b!NUb>}vjZNxTfTe5#?zj9!X#d=Wxd40y|a85gSTy)o<>(K3UkGL1yzj$CzmnZ32 z_gr{;z4HyihE&6muiy8~m%Y(-W3CZv^fwMP4K=Mb?fVlXKj!cD&oy^9k2Y@ykbosH z5O@;Uy*YJrzXfiIwIo})t)bR*>sinkTn(PJIon3tc0#g{KQtYB5qjH>v=6rLhR4F` z@L@O`0TDDZ6nPmHM}yJ14!mQeW2NIF=8H|mHe*MfrJd2v-#Rb4c5h*~;=~$K07w8p z&Jeq4294l7FbIIzWOhKrg{g3;#^@j!bb2XCpyTFKiIPGBYQCbzMEt2R1x7ebNWfEI zDh@`p5{+CYsT7AedLqDNROK>qb6f$RsCOnpn3ybQA~|y@L4sKpwNz12jG#(qRHuu$ z${;zL&t!%A@_2$Gh|BR+>1rD6Ryo3fiUhnL3Pn|Rj~y>6#_b+k_16#j?pSR$>z%$V zA?oS~@n9@|-{bXq?#HiAuhl~}R^28QAQFwpA=5=&WlCp6?=p+{AtpodO*hJdYqYqJ s!+{iXtJtG}Styh$@!GB_1ner9%YFxe{>RnlC=hZ@`H%PfCy93ZUnNsS5dZ)H From ab24124841766a6f7ab993a3ad83ed8c436366a7 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Thu, 16 Apr 2020 14:48:30 +0200 Subject: [PATCH 14/26] use map over switch, "more strict" signature, don't send default type, https://github.com/microsoft/vscode/issues/95325 --- .../api/browser/mainThreadLanguageFeatures.ts | 2 +- .../workbench/api/common/extHost.protocol.ts | 2 +- .../api/common/extHostLanguageFeatures.ts | 2 +- .../api/common/extHostTypeConverters.ts | 124 +++++++++--------- 4 files changed, 66 insertions(+), 64 deletions(-) diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index 0f52d714290..0584726e363 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -406,7 +406,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha return { label: data[ISuggestDataDtoField.label2] || data[ISuggestDataDtoField.label], - kind: data[ISuggestDataDtoField.kind], + kind: data[ISuggestDataDtoField.kind] || modes.CompletionItemKind.Property, tags: data[ISuggestDataDtoField.kindModifier], detail: data[ISuggestDataDtoField.detail], documentation: data[ISuggestDataDtoField.documentation], diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 279cb6cbc13..bf71fbba84b 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1104,7 +1104,7 @@ export const enum ISuggestDataDtoField { export interface ISuggestDataDto { [ISuggestDataDtoField.label]: string; [ISuggestDataDtoField.label2]?: string | modes.CompletionItemLabel; - [ISuggestDataDtoField.kind]: modes.CompletionItemKind; + [ISuggestDataDtoField.kind]?: modes.CompletionItemKind; [ISuggestDataDtoField.detail]?: string; [ISuggestDataDtoField.documentation]?: string | IMarkdownString; [ISuggestDataDtoField.sortText]?: string; diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 1f8d2bc15f0..e97f9f1d862 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -956,7 +956,7 @@ class SuggestAdapter { // [extHostProtocol.ISuggestDataDtoField.label]: item.label, [extHostProtocol.ISuggestDataDtoField.label2]: item.label2, - [extHostProtocol.ISuggestDataDtoField.kind]: typeConvert.CompletionItemKind.from(item.kind), + [extHostProtocol.ISuggestDataDtoField.kind]: item.kind ? typeConvert.CompletionItemKind.from(item.kind) : undefined, [extHostProtocol.ISuggestDataDtoField.kindModifier]: item.tags && item.tags.map(typeConvert.CompletionItemTag.from), [extHostProtocol.ISuggestDataDtoField.detail]: item.detail, [extHostProtocol.ISuggestDataDtoField.documentation]: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation), diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 2093ebadf37..2aaa1d3e7e2 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -808,70 +808,72 @@ export namespace CompletionItemTag { export namespace CompletionItemKind { - export function from(kind: types.CompletionItemKind | undefined): modes.CompletionItemKind { - switch (kind) { - case types.CompletionItemKind.Method: return modes.CompletionItemKind.Method; - case types.CompletionItemKind.Function: return modes.CompletionItemKind.Function; - case types.CompletionItemKind.Constructor: return modes.CompletionItemKind.Constructor; - case types.CompletionItemKind.Field: return modes.CompletionItemKind.Field; - case types.CompletionItemKind.Variable: return modes.CompletionItemKind.Variable; - case types.CompletionItemKind.Class: return modes.CompletionItemKind.Class; - case types.CompletionItemKind.Interface: return modes.CompletionItemKind.Interface; - case types.CompletionItemKind.Struct: return modes.CompletionItemKind.Struct; - case types.CompletionItemKind.Module: return modes.CompletionItemKind.Module; - case types.CompletionItemKind.Property: return modes.CompletionItemKind.Property; - case types.CompletionItemKind.Unit: return modes.CompletionItemKind.Unit; - case types.CompletionItemKind.Value: return modes.CompletionItemKind.Value; - case types.CompletionItemKind.Constant: return modes.CompletionItemKind.Constant; - case types.CompletionItemKind.Enum: return modes.CompletionItemKind.Enum; - case types.CompletionItemKind.EnumMember: return modes.CompletionItemKind.EnumMember; - case types.CompletionItemKind.Keyword: return modes.CompletionItemKind.Keyword; - case types.CompletionItemKind.Snippet: return modes.CompletionItemKind.Snippet; - case types.CompletionItemKind.Text: return modes.CompletionItemKind.Text; - case types.CompletionItemKind.Color: return modes.CompletionItemKind.Color; - case types.CompletionItemKind.File: return modes.CompletionItemKind.File; - case types.CompletionItemKind.Reference: return modes.CompletionItemKind.Reference; - case types.CompletionItemKind.Folder: return modes.CompletionItemKind.Folder; - case types.CompletionItemKind.Event: return modes.CompletionItemKind.Event; - case types.CompletionItemKind.Operator: return modes.CompletionItemKind.Operator; - case types.CompletionItemKind.TypeParameter: return modes.CompletionItemKind.TypeParameter; - case types.CompletionItemKind.Issue: return modes.CompletionItemKind.Issue; - case types.CompletionItemKind.User: return modes.CompletionItemKind.User; - } - return modes.CompletionItemKind.Property; + const _from = new Map([ + [types.CompletionItemKind.Method, modes.CompletionItemKind.Method], + [types.CompletionItemKind.Function, modes.CompletionItemKind.Function], + [types.CompletionItemKind.Constructor, modes.CompletionItemKind.Constructor], + [types.CompletionItemKind.Field, modes.CompletionItemKind.Field], + [types.CompletionItemKind.Variable, modes.CompletionItemKind.Variable], + [types.CompletionItemKind.Class, modes.CompletionItemKind.Class], + [types.CompletionItemKind.Interface, modes.CompletionItemKind.Interface], + [types.CompletionItemKind.Struct, modes.CompletionItemKind.Struct], + [types.CompletionItemKind.Module, modes.CompletionItemKind.Module], + [types.CompletionItemKind.Property, modes.CompletionItemKind.Property], + [types.CompletionItemKind.Unit, modes.CompletionItemKind.Unit], + [types.CompletionItemKind.Value, modes.CompletionItemKind.Value], + [types.CompletionItemKind.Constant, modes.CompletionItemKind.Constant], + [types.CompletionItemKind.Enum, modes.CompletionItemKind.Enum], + [types.CompletionItemKind.EnumMember, modes.CompletionItemKind.EnumMember], + [types.CompletionItemKind.Keyword, modes.CompletionItemKind.Keyword], + [types.CompletionItemKind.Snippet, modes.CompletionItemKind.Snippet], + [types.CompletionItemKind.Text, modes.CompletionItemKind.Text], + [types.CompletionItemKind.Color, modes.CompletionItemKind.Color], + [types.CompletionItemKind.File, modes.CompletionItemKind.File], + [types.CompletionItemKind.Reference, modes.CompletionItemKind.Reference], + [types.CompletionItemKind.Folder, modes.CompletionItemKind.Folder], + [types.CompletionItemKind.Event, modes.CompletionItemKind.Event], + [types.CompletionItemKind.Operator, modes.CompletionItemKind.Operator], + [types.CompletionItemKind.TypeParameter, modes.CompletionItemKind.TypeParameter], + [types.CompletionItemKind.Issue, modes.CompletionItemKind.Issue], + [types.CompletionItemKind.User, modes.CompletionItemKind.User], + ]); + + export function from(kind: types.CompletionItemKind): modes.CompletionItemKind { + return _from.get(kind) ?? modes.CompletionItemKind.Property; } + const _to = new Map([ + [modes.CompletionItemKind.Method, types.CompletionItemKind.Method], + [modes.CompletionItemKind.Function, types.CompletionItemKind.Function], + [modes.CompletionItemKind.Constructor, types.CompletionItemKind.Constructor], + [modes.CompletionItemKind.Field, types.CompletionItemKind.Field], + [modes.CompletionItemKind.Variable, types.CompletionItemKind.Variable], + [modes.CompletionItemKind.Class, types.CompletionItemKind.Class], + [modes.CompletionItemKind.Interface, types.CompletionItemKind.Interface], + [modes.CompletionItemKind.Struct, types.CompletionItemKind.Struct], + [modes.CompletionItemKind.Module, types.CompletionItemKind.Module], + [modes.CompletionItemKind.Property, types.CompletionItemKind.Property], + [modes.CompletionItemKind.Unit, types.CompletionItemKind.Unit], + [modes.CompletionItemKind.Value, types.CompletionItemKind.Value], + [modes.CompletionItemKind.Constant, types.CompletionItemKind.Constant], + [modes.CompletionItemKind.Enum, types.CompletionItemKind.Enum], + [modes.CompletionItemKind.EnumMember, types.CompletionItemKind.EnumMember], + [modes.CompletionItemKind.Keyword, types.CompletionItemKind.Keyword], + [modes.CompletionItemKind.Snippet, types.CompletionItemKind.Snippet], + [modes.CompletionItemKind.Text, types.CompletionItemKind.Text], + [modes.CompletionItemKind.Color, types.CompletionItemKind.Color], + [modes.CompletionItemKind.File, types.CompletionItemKind.File], + [modes.CompletionItemKind.Reference, types.CompletionItemKind.Reference], + [modes.CompletionItemKind.Folder, types.CompletionItemKind.Folder], + [modes.CompletionItemKind.Event, types.CompletionItemKind.Event], + [modes.CompletionItemKind.Operator, types.CompletionItemKind.Operator], + [modes.CompletionItemKind.TypeParameter, types.CompletionItemKind.TypeParameter], + [modes.CompletionItemKind.User, types.CompletionItemKind.User], + [modes.CompletionItemKind.Issue, types.CompletionItemKind.Issue], + ]); + export function to(kind: modes.CompletionItemKind): types.CompletionItemKind { - switch (kind) { - case modes.CompletionItemKind.Method: return types.CompletionItemKind.Method; - case modes.CompletionItemKind.Function: return types.CompletionItemKind.Function; - case modes.CompletionItemKind.Constructor: return types.CompletionItemKind.Constructor; - case modes.CompletionItemKind.Field: return types.CompletionItemKind.Field; - case modes.CompletionItemKind.Variable: return types.CompletionItemKind.Variable; - case modes.CompletionItemKind.Class: return types.CompletionItemKind.Class; - case modes.CompletionItemKind.Interface: return types.CompletionItemKind.Interface; - case modes.CompletionItemKind.Struct: return types.CompletionItemKind.Struct; - case modes.CompletionItemKind.Module: return types.CompletionItemKind.Module; - case modes.CompletionItemKind.Property: return types.CompletionItemKind.Property; - case modes.CompletionItemKind.Unit: return types.CompletionItemKind.Unit; - case modes.CompletionItemKind.Value: return types.CompletionItemKind.Value; - case modes.CompletionItemKind.Constant: return types.CompletionItemKind.Constant; - case modes.CompletionItemKind.Enum: return types.CompletionItemKind.Enum; - case modes.CompletionItemKind.EnumMember: return types.CompletionItemKind.EnumMember; - case modes.CompletionItemKind.Keyword: return types.CompletionItemKind.Keyword; - case modes.CompletionItemKind.Snippet: return types.CompletionItemKind.Snippet; - case modes.CompletionItemKind.Text: return types.CompletionItemKind.Text; - case modes.CompletionItemKind.Color: return types.CompletionItemKind.Color; - case modes.CompletionItemKind.File: return types.CompletionItemKind.File; - case modes.CompletionItemKind.Reference: return types.CompletionItemKind.Reference; - case modes.CompletionItemKind.Folder: return types.CompletionItemKind.Folder; - case modes.CompletionItemKind.Event: return types.CompletionItemKind.Event; - case modes.CompletionItemKind.Operator: return types.CompletionItemKind.Operator; - case modes.CompletionItemKind.TypeParameter: return types.CompletionItemKind.TypeParameter; - case modes.CompletionItemKind.User: return types.CompletionItemKind.User; - case modes.CompletionItemKind.Issue: return types.CompletionItemKind.Issue; - } - return types.CompletionItemKind.Property; + return _to.get(kind) ?? types.CompletionItemKind.Property; } } From 6c143da1a86468a75c420181150a51532e923f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 16 Apr 2020 16:19:28 +0200 Subject: [PATCH 15/26] check for change --- src/vs/workbench/api/common/extHostSCM.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index fb3f7725d3a..4d08d987564 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -194,6 +194,11 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox { set visible(visible: boolean) { visible = !!visible; + + if (this._visible === visible) { + return; + } + this._visible = visible; this._proxy.$setInputBoxVisibility(this._sourceControlHandle, visible); } From 2548906f4c2d4f5c5a1e59af79aa7ba5cbe74244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Thu, 16 Apr 2020 16:20:28 +0200 Subject: [PATCH 16/26] remove extra imports --- .../contrib/userDataSync/browser/userDataSyncAuthentication.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncAuthentication.ts b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncAuthentication.ts index bb936003353..20c2c4b5f6c 100644 --- a/src/vs/workbench/contrib/userDataSync/browser/userDataSyncAuthentication.ts +++ b/src/vs/workbench/contrib/userDataSync/browser/userDataSyncAuthentication.ts @@ -13,8 +13,6 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { localize } from 'vs/nls'; import { distinct } from 'vs/base/common/arrays'; -import Severity from 'vs/base/common/severity'; -import { Action } from 'vs/base/common/actions'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { AuthenticationSession, AuthenticationSessionsChangeEvent } from 'vs/editor/common/modes'; import { Emitter, Event } from 'vs/base/common/event'; From 77e79529e184e3e54a85b5e9c1f0b6de2e3174c3 Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Thu, 16 Apr 2020 11:48:34 -0400 Subject: [PATCH 17/26] Removes bogus code --- extensions/git/src/git.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 8ae6053734e..f3de788998f 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -435,14 +435,13 @@ export class Git { const [, letter] = match; try { - let networkPath = await new Promise(resolve => + const networkPath = await new Promise(resolve => realpath.native(`${letter}:`, { encoding: 'utf8' }, (err, resolvedPath) => // eslint-disable-next-line eqeqeq resolve(err != null ? undefined : resolvedPath), ), ); if (networkPath !== undefined) { - networkPath = `${networkPath}\\`; return path.normalize( repoUri.fsPath.replace( networkPath, From c6d841c90f8945c94745735f6703a9b76a2817cb Mon Sep 17 00:00:00 2001 From: isidor Date: Thu, 16 Apr 2020 17:53:46 +0200 Subject: [PATCH 18/26] statusbar: put aria-label on label container not on parent fixes #94962 --- src/vs/workbench/browser/parts/statusbar/statusbarPart.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 6e18a38dfe4..a86fe3980a0 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -695,7 +695,7 @@ class StatusbarEntryItem extends Disposable { } if (!this.entry || entry.ariaLabel !== this.entry.ariaLabel) { - this.container.setAttribute('aria-label', entry.ariaLabel); + this.labelContainer.setAttribute('aria-label', entry.ariaLabel); } // Update: Tooltip (on the container, because label can be disabled) From d7bfe46f2238f9f131d78de564e2576bb4adca3a Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Thu, 16 Apr 2020 17:56:27 +0200 Subject: [PATCH 19/26] use new semver-umd module --- package.json | 2 +- remote/package.json | 2 +- remote/web/package.json | 2 +- remote/web/yarn.lock | 8 ++++---- remote/yarn.lock | 8 ++++---- yarn.lock | 8 ++++---- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 07aef019358..e642009dff2 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "native-watchdog": "1.3.0", "node-pty": "0.10.0-beta8", "onigasm-umd": "2.2.5", - "semver-umd": "^5.5.5", + "semver-umd": "^5.5.6", "spdlog": "^0.11.1", "sudo-prompt": "9.1.1", "v8-inspect-profiler": "^0.0.20", diff --git a/remote/package.json b/remote/package.json index 6ed1fa0c3bd..794ce654a27 100644 --- a/remote/package.json +++ b/remote/package.json @@ -14,7 +14,7 @@ "native-watchdog": "1.3.0", "node-pty": "0.10.0-beta8", "onigasm-umd": "2.2.5", - "semver-umd": "^5.5.5", + "semver-umd": "^5.5.6", "spdlog": "^0.11.1", "vscode-nsfw": "1.2.8", "vscode-proxy-agent": "^0.5.2", diff --git a/remote/web/package.json b/remote/web/package.json index ba587deca03..65aee5c9b39 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "dependencies": { "onigasm-umd": "2.2.5", - "semver-umd": "^5.5.5", + "semver-umd": "^5.5.6", "vscode-textmate": "4.4.0", "xterm": "4.6.0-beta.4", "xterm-addon-search": "0.6.0", diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index e1ffafbe05f..24495cfcd4a 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -19,10 +19,10 @@ oniguruma@^7.2.0: dependencies: nan "^2.14.0" -semver-umd@^5.5.5: - version "5.5.5" - resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.5.tgz#a2e4280d0e92a2b27695c18811f0e939e144d86f" - integrity sha512-8rUq0nnTzlexpAdYmm8UDYsLkBn0MnBkfrGWPmyDBDDzv71dPOH07szOOaLj/5hO3BYmumYwS+wp3C60zLzh5g== +semver-umd@^5.5.6: + version "5.5.6" + resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.6.tgz#1d185bbd2caec825c564b54907cd09e14083f228" + integrity sha512-6ARYXVi4Y4VO5HfyCjT/6xyykBtJwEXSGQ8ON4UPQSFOjZUDsbAE0J614QcBBsLTTyQMEqvsXN804vAqpydjzw== vscode-textmate@4.4.0: version "4.4.0" diff --git a/remote/yarn.lock b/remote/yarn.lock index 4dbea32fc9d..89fe959a97f 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -317,10 +317,10 @@ readdirp@~3.2.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -semver-umd@^5.5.5: - version "5.5.5" - resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.5.tgz#a2e4280d0e92a2b27695c18811f0e939e144d86f" - integrity sha512-8rUq0nnTzlexpAdYmm8UDYsLkBn0MnBkfrGWPmyDBDDzv71dPOH07szOOaLj/5hO3BYmumYwS+wp3C60zLzh5g== +semver-umd@^5.5.6: + version "5.5.6" + resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.6.tgz#1d185bbd2caec825c564b54907cd09e14083f228" + integrity sha512-6ARYXVi4Y4VO5HfyCjT/6xyykBtJwEXSGQ8ON4UPQSFOjZUDsbAE0J614QcBBsLTTyQMEqvsXN804vAqpydjzw== semver@^5.3.0: version "5.6.0" diff --git a/yarn.lock b/yarn.lock index 4069aa5ee95..0d730f0f0e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8224,10 +8224,10 @@ semver-greatest-satisfied-range@^1.1.0: dependencies: sver-compat "^1.5.0" -semver-umd@^5.5.5: - version "5.5.5" - resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.5.tgz#a2e4280d0e92a2b27695c18811f0e939e144d86f" - integrity sha512-8rUq0nnTzlexpAdYmm8UDYsLkBn0MnBkfrGWPmyDBDDzv71dPOH07szOOaLj/5hO3BYmumYwS+wp3C60zLzh5g== +semver-umd@^5.5.6: + version "5.5.6" + resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.6.tgz#1d185bbd2caec825c564b54907cd09e14083f228" + integrity sha512-6ARYXVi4Y4VO5HfyCjT/6xyykBtJwEXSGQ8ON4UPQSFOjZUDsbAE0J614QcBBsLTTyQMEqvsXN804vAqpydjzw== "semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0: version "5.4.1" From 7d6996b44bb6c5e1a59c9844c1b29161c915a6c6 Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 16 Apr 2020 09:30:40 -0700 Subject: [PATCH 20/26] Cell View State restore --- .../workbench/contrib/notebook/browser/notebookEditor.ts | 4 ++-- .../workbench/contrib/notebook/test/testNotebookEditor.ts | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 9824516bd92..845711847b4 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -428,8 +428,8 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { if (this.list) { state.scrollPosition = { left: this.list.scrollLeft, top: this.list.scrollTop }; let cellHeights: { [key: number]: number } = {}; - for (let i = 0; i < this.list.length; i++) { - const elm = this.list.element(i)!; + for (let i = 0; i < this.viewModel!.viewCells.length; i++) { + const elm = this.viewModel!.viewCells[i] as CellViewModel; if (elm.cellKind === CellKind.Code) { cellHeights[i] = elm.layoutInfo.totalHeight; } else { diff --git a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts index 3494687cd5c..43ca6e0265a 100644 --- a/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/test/testNotebookEditor.ts @@ -9,7 +9,7 @@ import { CellKind, IOutput, CellUri, NotebookCellMetadata } from 'vs/workbench/c import { NotebookViewModel, IModelDecorationsChangeAccessor, CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; -import { INotebookEditor, NotebookLayoutInfo, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; +import { INotebookEditor, NotebookLayoutInfo, ICellViewModel, ICellRange } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { BareFontInfo } from 'vs/editor/common/config/fontInfo'; @@ -49,6 +49,11 @@ export class TestNotebookEditor implements INotebookEditor { constructor( ) { } + + setHiddenAreas(_ranges: ICellRange[]): boolean { + throw new Error('Method not implemented.'); + } + getInnerWebview(): Webview | undefined { throw new Error('Method not implemented.'); } From 5f0d752fb5b36b6b6dff5718b7ab5f818c369642 Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Thu, 16 Apr 2020 12:08:22 -0500 Subject: [PATCH 21/26] Fix outputs overlapping cell status bar --- .../contrib/notebook/browser/viewModel/codeCellViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts index 34d4b4a8ff6..47aefbe9bbb 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel.ts @@ -110,7 +110,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod const outputTotalHeight = this._outputsTop!.getTotalValue(); const totalHeight = EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_MARGIN + outputTotalHeight + BOTTOM_CELL_TOOLBAR_HEIGHT + CELL_STATUSBAR_HEIGHT; const indicatorHeight = this.editorHeight + CELL_STATUSBAR_HEIGHT + outputTotalHeight; - const outputContainerOffset = EDITOR_TOOLBAR_HEIGHT + EDITOR_TOP_MARGIN + this.editorHeight; + const outputContainerOffset = EDITOR_TOOLBAR_HEIGHT + EDITOR_TOP_MARGIN + this.editorHeight + CELL_STATUSBAR_HEIGHT; const bottomToolbarOffset = totalHeight - BOTTOM_CELL_TOOLBAR_HEIGHT; const editorWidth = state.outerWidth !== undefined ? state.outerWidth - CELL_MARGIN * 2 - CELL_RUN_GUTTER : this._layoutInfo?.editorWidth; this._layoutInfo = { From 0dd9d94be65a3c73553c8fcde91c9e542d3f7d8a Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 16 Apr 2020 10:11:29 -0700 Subject: [PATCH 22/26] Rollback Re #95466 --- .../workbench/contrib/notebook/browser/media/notebook.css | 8 ++++---- .../workbench/contrib/notebook/browser/notebookEditor.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/media/notebook.css b/src/vs/workbench/contrib/notebook/browser/media/notebook.css index cf4e285480b..547a5fe3efa 100644 --- a/src/vs/workbench/contrib/notebook/browser/media/notebook.css +++ b/src/vs/workbench/contrib/notebook/browser/media/notebook.css @@ -135,11 +135,11 @@ cursor: pointer; } -.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows .monaco-list-row { +.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row { width: 100%; } -.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows .monaco-list-row > .monaco-toolbar { +.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .monaco-toolbar { visibility: hidden; display: inline-block; @@ -151,7 +151,7 @@ box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.2); } -.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows .monaco-list-row > .monaco-toolbar .action-item { +.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .monaco-toolbar .action-item { width: 24px; height: 24px; display: flex; @@ -159,7 +159,7 @@ margin: 1px 2px; } -.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows .monaco-list-row > .monaco-toolbar .action-item .action-label { +.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .monaco-toolbar .action-item .action-label { display: flex; align-items: center; margin: auto; diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index d5f4eb70382..070694ffe45 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -882,8 +882,8 @@ registerThemingParticipant((theme, collector) => { } // Cell Margin - collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN}px; }`); - collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row { padding-top: ${EDITOR_TOP_MARGIN}px; }`); + collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-editor-part > div.cell { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN}px; }`); + collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-editor-part { padding-top: ${EDITOR_TOP_MARGIN}px; }`); collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`); collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-bottom-toolbar-container { width: calc(100% - ${CELL_MARGIN * 2 + CELL_RUN_GUTTER}px); margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`); From fcc10e46c315a05bff1b08cdd218b463866b8c34 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 15 Apr 2020 19:21:08 -0700 Subject: [PATCH 23/26] Always explicitly clear signature help disposables on hide --- src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts index e0528d52ea3..43859c89cff 100644 --- a/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts +++ b/src/vs/editor/contrib/parameterHints/parameterHintsWidget.ts @@ -153,6 +153,8 @@ export class ParameterHintsWidget extends Disposable implements IContentWidget { } private hide(): void { + this.renderDisposeables.clear(); + if (!this.visible) { return; } From b89738c83bca6e67e73d0c59ab890b3e47905f79 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 16 Apr 2020 09:00:08 -0700 Subject: [PATCH 24/26] Scope prepareRename to TS 3.1+ Fixes #95399 --- .../src/features/rename.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/typescript-language-features/src/features/rename.ts b/extensions/typescript-language-features/src/features/rename.ts index db68acf38f3..9074faa4372 100644 --- a/extensions/typescript-language-features/src/features/rename.ts +++ b/extensions/typescript-language-features/src/features/rename.ts @@ -8,6 +8,7 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; import type * as Proto from '../protocol'; import { ITypeScriptServiceClient, ServerResponse } from '../typescriptService'; +import API from '../utils/api'; import * as typeConverters from '../utils/typeConverters'; import FileConfigurationManager from './fileConfigurationManager'; @@ -24,6 +25,10 @@ class TypeScriptRenameProvider implements vscode.RenameProvider { position: vscode.Position, token: vscode.CancellationToken ): Promise { + if (this.client.apiVersion.lt(API.v310)) { + return null; + } + const response = await this.execRename(document, position, token); if (response?.type !== 'response' || !response.body) { return null; @@ -34,12 +39,7 @@ class TypeScriptRenameProvider implements vscode.RenameProvider { return Promise.reject(renameInfo.localizedErrorMessage); } - const triggerSpan = renameInfo.triggerSpan; // added in TS 3.1 - if (triggerSpan) { - return typeConverters.Range.fromTextSpan(triggerSpan); - } - - return null; + return typeConverters.Range.fromTextSpan(renameInfo.triggerSpan); } public async provideRenameEdits( From c189b2bb05b05d26d74e202e0fff6574e151075b Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Thu, 16 Apr 2020 10:16:44 -0700 Subject: [PATCH 25/26] Remove use of memoize Fixes #95324 --- .../src/features/completions.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/extensions/typescript-language-features/src/features/completions.ts b/extensions/typescript-language-features/src/features/completions.ts index 4d7f2cf1626..e1ef02c998c 100644 --- a/extensions/typescript-language-features/src/features/completions.ts +++ b/extensions/typescript-language-features/src/features/completions.ts @@ -13,7 +13,6 @@ import { nulToken } from '../utils/cancellation'; import { applyCodeAction } from '../utils/codeAction'; import { Command, CommandManager } from '../utils/commandManager'; import { ConfigurationDependentRegistration } from '../utils/dependentRegistration'; -import { memoize } from '../utils/memoize'; import * as Previewer from '../utils/previewer'; import { snippetForFunctionCall } from '../utils/snippetForFunctionCall'; import { TelemetryReporter } from '../utils/telemetry'; @@ -68,7 +67,9 @@ class MyCompletionItem extends vscode.CompletionItem { this.preselect = tsEntry.isRecommended; this.position = position; this.useCodeSnippet = completionContext.useCodeSnippetsOnMethodSuggest && (this.kind === vscode.CompletionItemKind.Function || this.kind === vscode.CompletionItemKind.Method); + this.range = this.getRangeFromReplacementSpan(tsEntry, completionContext, position); + this.commitCharacters = MyCompletionItem.getCommitCharacters(completionContext, tsEntry); this.insertText = tsEntry.insertText; this.filterText = this.getFilterText(completionContext.line, tsEntry.insertText); @@ -268,14 +269,13 @@ class MyCompletionItem extends vscode.CompletionItem { } } - @memoize - public get commitCharacters(): string[] | undefined { - if (this.completionContext.isNewIdentifierLocation || !this.completionContext.isInValidCommitCharacterContext) { + private static getCommitCharacters(context: CompletionContext, entry: Proto.CompletionEntry): string[] | undefined { + if (context.isNewIdentifierLocation || !context.isInValidCommitCharacterContext) { return undefined; } const commitCharacters: string[] = []; - switch (this.tsEntry.kind) { + switch (entry.kind) { case PConst.Kind.memberGetAccessor: case PConst.Kind.memberSetAccessor: case PConst.Kind.constructSignature: @@ -299,7 +299,7 @@ class MyCompletionItem extends vscode.CompletionItem { case PConst.Kind.keyword: case PConst.Kind.parameter: commitCharacters.push('.', ',', ';'); - if (this.completionContext.enableCallCompletions) { + if (context.enableCallCompletions) { commitCharacters.push('('); } break; From 483e822b2eff4006037a14c1ebb86333bb30a3ae Mon Sep 17 00:00:00 2001 From: rebornix Date: Thu, 16 Apr 2020 10:20:12 -0700 Subject: [PATCH 26/26] Re #95466. Fix cell margin. --- src/vs/workbench/contrib/notebook/browser/notebookEditor.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts index 070694ffe45..f37098e51c9 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditor.ts @@ -882,13 +882,13 @@ registerThemingParticipant((theme, collector) => { } // Cell Margin - collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-editor-part > div.cell { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN}px; }`); - collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-editor-part { padding-top: ${EDITOR_TOP_MARGIN}px; }`); + collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > div.cell { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN}px; }`); + collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row { padding-top: ${EDITOR_TOP_MARGIN}px; }`); collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`); collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-bottom-toolbar-container { width: calc(100% - ${CELL_MARGIN * 2 + CELL_RUN_GUTTER}px); margin: 0px ${CELL_MARGIN}px 0px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`); collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-editor-container { width: calc(100% - ${CELL_RUN_GUTTER}px); }`); collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .markdown-editor-container { margin-left: ${CELL_RUN_GUTTER}px; }`); - collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`); + collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`); collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .run-button-container { width: ${CELL_RUN_GUTTER}px; }`); });