Merge branch 'notebook/dev' into main

This commit is contained in:
rebornix 2021-04-07 17:34:21 -07:00
commit 74a43ce149
No known key found for this signature in database
GPG key ID: 181FC90D15393C20
20 changed files with 225 additions and 136 deletions

View file

@ -45,7 +45,7 @@ export interface ICommandAction {
tooltip?: string;
icon?: Icon;
precondition?: ContextKeyExpression;
toggled?: ContextKeyExpression | { condition: ContextKeyExpression, icon?: Icon, tooltip?: string };
toggled?: ContextKeyExpression | { condition: ContextKeyExpression, icon?: Icon, tooltip?: string, title?: string | ILocalizedString };
}
export type ISerializableCommandAction = UriDto<ICommandAction>;
@ -386,12 +386,16 @@ export class MenuItemAction implements IAction {
if (item.toggled) {
const toggled = ((item.toggled as { condition: ContextKeyExpression }).condition ? item.toggled : { condition: item.toggled }) as {
condition: ContextKeyExpression, icon?: Icon, tooltip?: string | ILocalizedString
condition: ContextKeyExpression, icon?: Icon, tooltip?: string | ILocalizedString, title?: string | ILocalizedString
};
this.checked = contextKeyService.contextMatchesRules(toggled.condition);
if (this.checked && toggled.tooltip) {
this.tooltip = typeof toggled.tooltip === 'string' ? toggled.tooltip : toggled.tooltip.value;
}
if (toggled.title) {
this.label = typeof toggled.title === 'string' ? toggled.title : toggled.title.value;
}
}
this.item = item;

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { CellEditType, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { TestCell, withTestNotebook } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
@ -16,7 +16,7 @@ suite('Notebook Undo/Redo', () => {
['body', 'markdown', CellKind.Markdown, [], {}],
],
async (editor, accessor) => {
const textModelService = accessor.get(ITextModelService);
const modeService = accessor.get(IModeService);
const viewModel = editor.viewModel;
assert.strictEqual(viewModel.length, 2);
assert.strictEqual(viewModel.getVersionId(), 0);
@ -41,7 +41,7 @@ suite('Notebook Undo/Redo', () => {
viewModel.notebookDocument.applyEdits([{
editType: CellEditType.Replace, index: 0, count: 0, cells: [
new TestCell(viewModel.viewType, 3, '# header 2', 'markdown', CellKind.Code, [], textModelService),
new TestCell(viewModel.viewType, 3, '# header 2', 'markdown', CellKind.Code, [], modeService),
]
}], true, undefined, () => undefined, undefined, true);
assert.strictEqual(viewModel.getVersionId(), 4);
@ -61,7 +61,7 @@ suite('Notebook Undo/Redo', () => {
['body', 'markdown', CellKind.Markdown, [], {}],
],
async (editor, accessor) => {
const textModelService = accessor.get(ITextModelService);
const modeService = accessor.get(IModeService);
const viewModel = editor.viewModel;
viewModel.notebookDocument.applyEdits([{
editType: CellEditType.Replace, index: 0, count: 2, cells: []
@ -70,7 +70,7 @@ suite('Notebook Undo/Redo', () => {
assert.doesNotThrow(() => {
viewModel.notebookDocument.applyEdits([{
editType: CellEditType.Replace, index: 0, count: 2, cells: [
new TestCell(viewModel.viewType, 3, '# header 2', 'markdown', CellKind.Code, [], textModelService),
new TestCell(viewModel.viewType, 3, '# header 2', 'markdown', CellKind.Code, [], modeService),
]
}], true, undefined, () => undefined, undefined, true);
});
@ -104,7 +104,7 @@ suite('Notebook Undo/Redo', () => {
['body', 'markdown', CellKind.Markdown, [], {}],
],
async (editor, accessor) => {
const textModelService = accessor.get(ITextModelService);
const modeService = accessor.get(IModeService);
const viewModel = editor.viewModel;
viewModel.notebookDocument.applyEdits([{
editType: CellEditType.Replace, index: 0, count: 2, cells: []
@ -112,7 +112,7 @@ suite('Notebook Undo/Redo', () => {
viewModel.notebookDocument.applyEdits([{
editType: CellEditType.Replace, index: 0, count: 2, cells: [
new TestCell(viewModel.viewType, 3, '# header 2', 'markdown', CellKind.Code, [], textModelService),
new TestCell(viewModel.viewType, 3, '# header 2', 'markdown', CellKind.Code, [], modeService),
]
}], true, undefined, () => undefined, undefined, true);

View file

@ -1004,7 +1004,7 @@ export class DeletedElement extends SingleSideDiffElement {
}
}));
originalCell.textModel.resolveTextModelRef().then(ref => {
this.textModelService.createModelReference(originalCell.uri).then(ref => {
if (this._isDisposed) {
return;
}
@ -1157,7 +1157,7 @@ export class InsertElement extends SingleSideDiffElement {
}
}));
modifiedCell.textModel.resolveTextModelRef().then(ref => {
this.textModelService.createModelReference(modifiedCell.uri).then(ref => {
if (this._isDisposed) {
return;
}
@ -1525,8 +1525,8 @@ export class ModifiedElement extends AbstractElementRenderer {
const originalCell = this.cell.original!;
const modifiedCell = this.cell.modified!;
const originalRef = await originalCell.textModel.resolveTextModelRef();
const modifiedRef = await modifiedCell.textModel.resolveTextModelRef();
const originalRef = await this.textModelService.createModelReference(originalCell.uri);
const modifiedRef = await this.textModelService.createModelReference(modifiedCell.uri);
if (this._isDisposed) {
return;

View file

@ -28,6 +28,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { NotebookEditorOptions, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IBorrowValue, INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/notebookEditorService';
import { clearMarks, getAndClearMarks, mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState';
@ -131,7 +132,8 @@ export class NotebookEditor extends EditorPane {
}
async setInput(input: NotebookEditorInput, options: EditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken): Promise<void> {
const startTime = Date.now();
clearMarks(input.resource);
mark(input.resource, 'startTime');
const group = this.group!;
this._saveEditorViewState(this.input);
@ -154,9 +156,9 @@ export class NotebookEditor extends EditorPane {
// only now `setInput` and yield/await. this is AFTER the actual widget is ready. This is very important
// so that others synchronously receive a notebook editor with the correct widget being set
await super.setInput(input, options, context, token);
const model = await input.resolve();
const inputResolveTime = Date.now() - startTime;
mark(input.resource, 'inputLoaded');
// Check for cancellation
if (token.isCancellationRequested) {
return undefined;
@ -179,6 +181,7 @@ export class NotebookEditor extends EditorPane {
}
await this._notebookService.resolveNotebookEditor(model.viewType, model.resource, this._widget.value!.getId());
mark(input.resource, 'webviewCommLoaded');
const viewState = this._loadNotebookEditorViewState(input);
@ -191,29 +194,60 @@ export class NotebookEditor extends EditorPane {
containsGroup: (group) => this.group?.id === group.group.id
}));
mark(input.resource, 'editorLoaded');
type WorkbenchNotebookOpenClassification = {
scheme: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
ext: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
viewType: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
loadInput: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
loadEditor: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
extensionActivated: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
inputLoaded: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
webviewCommLoaded: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
customMarkdownLoaded: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
editorLoaded: { classification: 'SystemMetaData', purpose: 'FeatureInsight'; };
};
type WorkbenchNotebookOpenEvent = {
scheme: string;
ext: string;
viewType: string;
loadInput: number;
loadEditor: number;
extensionActivated: number;
inputLoaded: number;
webviewCommLoaded: number;
customMarkdownLoaded: number;
editorLoaded: number;
};
this.telemetryService.publicLog2<WorkbenchNotebookOpenEvent, WorkbenchNotebookOpenClassification>('notebook/editorOpenPerf', {
scheme: model.notebook.uri.scheme,
ext: extname(model.notebook.uri),
viewType: model.notebook.viewType,
loadInput: inputResolveTime,
loadEditor: Date.now() - startTime,
});
const perfMarks = getAndClearMarks(input.resource);
if (perfMarks) {
const startTime = perfMarks['startTime'];
const extensionActivated = perfMarks['extensionActivated'];
const inputLoaded = perfMarks['inputLoaded'];
const webviewCommLoaded = perfMarks['webviewCommLoaded'];
const customMarkdownLoaded = perfMarks['customMarkdownLoaded'];
const editorLoaded = perfMarks['editorLoaded'];
if (
startTime !== undefined
&& extensionActivated !== undefined
&& inputLoaded !== undefined
&& webviewCommLoaded !== undefined
&& customMarkdownLoaded !== undefined
&& editorLoaded !== undefined
) {
this.telemetryService.publicLog2<WorkbenchNotebookOpenEvent, WorkbenchNotebookOpenClassification>('notebook/editorOpenPerf', {
scheme: model.notebook.uri.scheme,
ext: extname(model.notebook.uri),
viewType: model.notebook.viewType,
extensionActivated: extensionActivated - startTime,
inputLoaded: inputLoaded - startTime,
webviewCommLoaded: webviewCommLoaded - startTime,
customMarkdownLoaded: customMarkdownLoaded - startTime,
editorLoaded: editorLoaded - startTime
});
}
}
}
clearInput(): void {

View file

@ -74,6 +74,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ITASExperimentService } from 'vs/workbench/services/experiment/common/experimentService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { isWeb } from 'vs/base/common/platform';
import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
const $ = DOM.$;
@ -1230,6 +1231,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
this._list.attachViewModel(this.viewModel);
}
mark(textModel.uri, 'customMarkdownLoaded');
// model attached
this._localCellStateListeners = this.viewModel.viewCells.map(cell => cell.onDidChangeLayout(e => {
if (e.totalHeight !== undefined || e.outerWidth) {

View file

@ -14,7 +14,7 @@ import { EDITOR_BOTTOM_PADDING, EDITOR_BOTTOM_PADDING_WITHOUT_STATUSBAR } from '
import { EditorTopPaddingChangeEvent, getEditorTopPadding, getNotebookEditorFromEditorPane, ICellViewModel, NOTEBOOK_CELL_LINE_NUMBERS, NOTEBOOK_EDITOR_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { localize } from 'vs/nls';
import { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@ -138,7 +138,7 @@ registerAction2(class ToggleLineNumberAction extends Action2 {
constructor() {
super({
id: 'notebook.toggleLineNumbers',
title: { value: localize('notebook.showLineNumbers', "Show Notebook Line Numbers"), original: 'Toggle Notebook Line Numbers' },
title: { value: localize('notebook.toggleLineNumbers', "Toggle Notebook Line Numbers"), original: 'Toggle Notebook Line Numbers' },
precondition: NOTEBOOK_EDITOR_FOCUSED,
menu: [{
id: MenuId.EditorTitle,
@ -146,8 +146,11 @@ registerAction2(class ToggleLineNumberAction extends Action2 {
order: 0
}],
category: NOTEBOOK_ACTIONS_CATEGORY,
f1: false,
toggled: ContextKeyExpr.notEquals('config.notebook.lineNumbers', 'off')
f1: true,
toggled: {
condition: ContextKeyExpr.notEquals('config.notebook.lineNumbers', 'off'),
title: { value: localize('notebook.showLineNumbers', "Show Notebook Line Numbers"), original: 'Show Notebook Line Numbers' },
}
});
}
@ -163,13 +166,6 @@ registerAction2(class ToggleLineNumberAction extends Action2 {
}
});
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: 'notebook.toggleLineNumbers',
title: { value: localize('notebook.toggleLineNumbers', "Toggle Notebook Line Numbers"), original: 'Toggle Notebook Line Numbers' }
}
});
registerAction2(class ToggleActiveLineNumberAction extends Action2 {
constructor() {
super({

View file

@ -25,6 +25,9 @@ export class CodeCell extends Disposable {
private _activeCellRunPlaceholder: IDisposable | null = null;
private _untrustedStatusItem: IDisposable | null = null;
private _renderedInputCollapseState: boolean | undefined;
private _renderedOutputCollapseState: boolean | undefined;
constructor(
private notebookEditor: IActiveNotebookEditor,
private viewCell: CodeCellViewModel,
@ -84,9 +87,6 @@ export class CodeCell extends Disposable {
templateData.container.classList.toggle('cell-editor-focus', viewCell.focusMode === CellFocusMode.Editor);
};
const updateForCollapseState = () => {
this.viewUpdate();
};
this._register(viewCell.onDidChangeState((e) => {
if (e.focusModeChanged) {
updateForFocusMode();
@ -99,10 +99,9 @@ export class CodeCell extends Disposable {
if (e.metadataChanged) {
templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel.metadata).editable) });
// TODO@rob this isn't nice
this.viewCell.layoutChange({});
updateForCollapseState();
this.relayoutCell();
if (this.updateForCollapseState()) {
this.relayoutCell();
}
}
}));
@ -222,7 +221,7 @@ export class CodeCell extends Disposable {
this._outputContainerRenderer = this.instantiationService.createInstance(CellOutputContainer, notebookEditor, viewCell, templateData);
this._outputContainerRenderer.render(editorHeight);
// Need to do this after the intial renderOutput
updateForCollapseState();
this.updateForCollapseState();
const updatePlaceholder = () => {
if (this.notebookEditor.viewModel
@ -261,7 +260,14 @@ export class CodeCell extends Disposable {
updatePlaceholder();
}
private viewUpdate(): void {
private updateForCollapseState(): boolean {
if (this.viewCell.metadata.outputCollapsed === this._renderedOutputCollapseState &&
this.viewCell.metadata.inputCollapsed === this._renderedInputCollapseState) {
return false;
}
this.viewCell.layoutChange({});
if (this.viewCell.metadata?.inputCollapsed && this.viewCell.metadata.outputCollapsed) {
this.viewUpdateAllCollapsed();
} else if (this.viewCell.metadata?.inputCollapsed) {
@ -271,6 +277,11 @@ export class CodeCell extends Disposable {
} else {
this.viewUpdateExpanded();
}
this._renderedOutputCollapseState = this.viewCell.metadata.outputCollapsed;
this._renderedInputCollapseState = this.viewCell.metadata.inputCollapsed;
return true;
}
private viewUpdateInputCollapsed(): void {

View file

@ -17,7 +17,7 @@ import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChang
import { CellKind, NotebookCellMetadata, NotebookDocumentMetadata, INotebookSearchOptions, ShowCellStatusBarKey } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
export abstract class BaseCellViewModel extends Disposable {
@ -124,7 +124,8 @@ export abstract class BaseCellViewModel extends Disposable {
readonly viewType: string,
readonly model: NotebookCellTextModel,
public id: string,
private readonly _configurationService: IConfigurationService
private readonly _configurationService: IConfigurationService,
private readonly _modelService: ITextModelService,
) {
super();
@ -148,7 +149,6 @@ export abstract class BaseCellViewModel extends Disposable {
return showCellStatusBar ? CELL_STATUSBAR_HEIGHT : 0;
}
// abstract resolveTextModel(): Promise<model.ITextModel>;
abstract hasDynamicHeight(): boolean;
abstract getHeight(lineHeight: number): number;
abstract onDeselect(): void;
@ -210,7 +210,6 @@ export abstract class BaseCellViewModel extends Disposable {
});
this._textEditor = undefined;
this.model.textModel = undefined;
this._cursorChangeListener?.dispose();
this._cursorChangeListener = null;
this._onDidChangeEditorAttachState.fire();
@ -436,7 +435,23 @@ export abstract class BaseCellViewModel extends Disposable {
return this.model.textBuffer;
}
abstract resolveTextModel(): Promise<model.ITextModel>;
/**
* Text model is used for editing.
*/
async resolveTextModel(): Promise<model.ITextModel> {
if (!this._textModelRef || !this.textModel) {
this._textModelRef = await this._modelService.createModelReference(this.uri);
if (!this._textModelRef) {
throw new Error(`Cannot resolve text model for ${this.uri}`);
}
this._register(this.textModel!.onDidChangeContent(() => this.onDidChangeTextModelContent()));
}
return this.textModel!;
}
protected abstract onDidChangeTextModelContent(): void;
protected cellStartFind(value: string, options: INotebookSearchOptions): model.FindMatch[] | null {
let cellMatches: model.FindMatch[] = [];

View file

@ -6,7 +6,7 @@
import { Emitter, Event } from 'vs/base/common/event';
import * as UUID from 'vs/base/common/uuid';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as model from 'vs/editor/common/model';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_BOTTOM_MARGIN, CELL_MARGIN, CELL_RUN_GUTTER, CELL_TOP_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT } from 'vs/workbench/contrib/notebook/browser/constants';
@ -92,9 +92,10 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
initialNotebookLayoutInfo: NotebookLayoutInfo | null,
readonly eventDispatcher: NotebookEventDispatcher,
@IConfigurationService configurationService: IConfigurationService,
@INotebookService private _notebookService: INotebookService
@INotebookService private readonly _notebookService: INotebookService,
@ITextModelService modelService: ITextModelService,
) {
super(viewType, model, UUID.generateUuid(), configurationService);
super(viewType, model, UUID.generateUuid(), configurationService, modelService);
this._outputViewModels = this.model.outputs.map(output => new CellOutputViewModel(this, output, this._notebookService));
this._register(this.model.onDidChangeOutputs((splices) => {
@ -140,7 +141,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
let totalHeight: number;
if (!state.editorHeight && this._layoutInfo.layoutState === CodeCellLayoutState.FromCache) {
// No new editorHeight info - keep cached totalHeight and estimate editorHeight
editorHeight = this.estimateEditorHeight(state.font?.lineHeight);
editorHeight = this.estimateEditorHeight(state.font?.lineHeight ?? this._layoutInfo.fontInfo?.lineHeight);
totalHeight = this._layoutInfo.totalHeight;
newState = CodeCellLayoutState.FromCache;
} else if (state.editorHeight || this._layoutInfo.layoutState === CodeCellLayoutState.Measured) {
@ -149,7 +150,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
totalHeight = this.computeTotalHeight(this._editorHeight, outputTotalHeight, outputShowMoreContainerHeight);
newState = CodeCellLayoutState.Measured;
} else {
editorHeight = this.estimateEditorHeight(state.font?.lineHeight);
editorHeight = this.estimateEditorHeight(state.font?.lineHeight ?? this._layoutInfo.fontInfo?.lineHeight);
totalHeight = this.computeTotalHeight(editorHeight, outputTotalHeight, outputShowMoreContainerHeight);
newState = CodeCellLayoutState.Estimated;
}
@ -162,7 +163,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth;
this._layoutInfo = {
fontInfo: state.font || null,
fontInfo: state.font ?? this._layoutInfo.fontInfo ?? null,
editorHeight,
editorWidth,
outputContainerOffset,
@ -184,7 +185,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
const editorWidth = state.outerWidth !== undefined ? this.computeEditorWidth(state.outerWidth) : this._layoutInfo?.editorWidth;
this._layoutInfo = {
fontInfo: state.font || null,
fontInfo: state.font ?? this._layoutInfo.fontInfo ?? null,
editorHeight: this._layoutInfo.editorHeight,
editorWidth,
outputContainerOffset,
@ -256,21 +257,11 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
return EDITOR_TOOLBAR_HEIGHT + CELL_TOP_MARGIN + editorHeight + this.getEditorStatusbarHeight() + outputsTotalHeight + outputShowMoreContainerHeight + BOTTOM_CELL_TOOLBAR_GAP + CELL_BOTTOM_MARGIN;
}
/**
* Text model is used for editing.
*/
async resolveTextModel(): Promise<model.ITextModel> {
if (!this._textModelRef || !this.textModel) {
this._textModelRef = await this.model.resolveTextModelRef();
this._register(this.textModel!.onDidChangeContent(() => {
if (this.editState !== CellEditState.Editing) {
this.editState = CellEditState.Editing;
this._onDidChangeState.fire({ contentChanged: true });
}
}));
protected onDidChangeTextModelContent(): void {
if (this.editState !== CellEditState.Editing) {
this.editState = CellEditState.Editing;
this._onDidChangeState.fire({ contentChanged: true });
}
return this.textModel!;
}
onDeselect() {

View file

@ -6,7 +6,6 @@
import { Emitter, Event } from 'vs/base/common/event';
import * as UUID from 'vs/base/common/uuid';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as model from 'vs/editor/common/model';
import * as nls from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { BOTTOM_CELL_TOOLBAR_GAP, BOTTOM_CELL_TOOLBAR_HEIGHT, CELL_MARGIN, CODE_CELL_LEFT_MARGIN, COLLAPSED_INDICATOR_HEIGHT, MARKDOWN_CELL_BOTTOM_MARGIN, MARKDOWN_CELL_TOP_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants';
@ -17,14 +16,13 @@ import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod
import { NotebookCellStateChangedEvent, NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { CellKind, INotebookSearchOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
export class MarkdownCellViewModel extends BaseCellViewModel implements ICellViewModel {
readonly cellKind = CellKind.Markdown;
private _html: HTMLElement | null = null;
private _layoutInfo: MarkdownCellLayoutInfo;
private _version = 0;
get layoutInfo() {
return this._layoutInfo;
}
@ -93,7 +91,7 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
}
public get version(): number {
return this._version;
return this.textModel?.getVersionId() ?? 0;
}
constructor(
@ -104,8 +102,9 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
readonly eventDispatcher: NotebookEventDispatcher,
private readonly _mdRenderer: MarkdownRenderer,
@IConfigurationService configurationService: IConfigurationService,
@ITextModelService textModelService: ITextModelService,
) {
super(viewType, model, UUID.generateUuid(), configurationService);
super(viewType, model, UUID.generateUuid(), configurationService, textModelService);
this._layoutInfo = {
editorHeight: 0,
@ -224,19 +223,9 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
return null;
}
async resolveTextModel(): Promise<model.ITextModel> {
if (!this._textModelRef || !this.textModel) {
this._textModelRef = await this.model.resolveTextModelRef();
this._version = this.textModel!.getVersionId();
this._register(this.textModel!.onDidChangeContent(() => {
this._html = null;
if (this.textModel) {
this._version = this.textModel.getVersionId();
}
this._onDidChangeState.fire({ contentChanged: true });
}));
}
return this.textModel!;
protected onDidChangeTextModelContent(): void {
this._html = null;
this._onDidChangeState.fire({ contentChanged: true });
}
onDeselect() {

View file

@ -33,7 +33,7 @@ import { IPosition, Position } from 'vs/editor/common/core/position';
import { MultiModelEditStackElement, SingleModelEditStackElement } from 'vs/editor/common/model/editStack';
import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits';
import { NotebookCellSelectionCollection } from 'vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
export interface INotebookEditorViewState {
editingCells: { [key: number]: boolean };
@ -230,7 +230,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
@IUndoRedoService private readonly _undoService: IUndoRedoService,
@IModelService modelService: IModelService,
@ITextModelService private readonly _textModelService: ITextModelService,
) {
super();
@ -1089,7 +1089,7 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD
async withElement(element: SingleModelEditStackElement | MultiModelEditStackElement, callback: () => Promise<void>) {
const viewCells = this._viewCells.filter(cell => element.matchesResource(cell.uri));
const refs = await Promise.all(viewCells.map(cell => cell.model.resolveTextModelRef()));
const refs = await Promise.all(viewCells.map(cell => this._textModelService.createModelReference(cell.uri)));
await callback();
refs.forEach(ref => ref.dispose());
}

View file

@ -11,10 +11,10 @@ import * as UUID from 'vs/base/common/uuid';
import * as model from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { hash } from 'vs/base/common/hash';
import { PieceTreeTextBuffer } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBuffer';
import { NotebookCellOutputTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel';
import { IModeService } from 'vs/editor/common/services/modeService';
export class NotebookCellTextModel extends Disposable implements ICell {
private _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>();
@ -53,6 +53,11 @@ export class NotebookCellTextModel extends Disposable implements ICell {
}
set language(newLanguage: string) {
if (this._textModel && this._textModel.getLanguageIdentifier().language !== newLanguage) {
const newMode = this._modeService.create(newLanguage);
this._textModel.setMode(newMode.languageIdentifier);
}
if (this._language === newLanguage) {
return;
}
@ -60,6 +65,7 @@ export class NotebookCellTextModel extends Disposable implements ICell {
this._language = newLanguage;
this._hash = null;
this._onDidChangeLanguage.fire(newLanguage);
this._onDidChangeContent.fire();
}
private _textBuffer!: model.IReadonlyTextBuffer;
@ -106,7 +112,6 @@ export class NotebookCellTextModel extends Disposable implements ICell {
// Listen to language changes on the model
this._textModelDisposables.add(this._textModel.onDidChangeLanguage(e => {
this.language = e.newLanguage;
this._onDidChangeContent.fire();
}));
this._textModelDisposables.add(this._textModel.onWillDispose(() => this.textModel = undefined));
}
@ -121,7 +126,7 @@ export class NotebookCellTextModel extends Disposable implements ICell {
outputs: IOutputDto[],
metadata: NotebookCellMetadata | undefined,
public readonly transientOptions: TransientOptions,
private readonly _modelService: ITextModelService
private readonly _modeService: IModeService
) {
super();
this._outputs = outputs.map(op => new NotebookCellOutputTextModel(op));
@ -197,12 +202,6 @@ export class NotebookCellTextModel extends Disposable implements ICell {
};
}
async resolveTextModelRef() {
const ref = await this._modelService.createModelReference(this.uri);
this.textModel = ref.object.textEditorModel;
return ref;
}
dispose() {
// Manually release reference to previous text buffer to avoid large leaks
// in case someone leaks a CellTextModel reference

View file

@ -10,13 +10,14 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent, NotebookRawContentEvent, IOutputDto, ICellOutput, IOutputItemDto, ISelectionState, NullablePartialNotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement, UndoRedoGroup, IWorkspaceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
import { MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { ISequence, LcsDiff } from 'vs/base/common/diff/diff';
import { hash } from 'vs/base/common/hash';
import { NotebookCellOutputTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellOutputTextModel';
import { IModelService } from 'vs/editor/common/services/modelService';
import { Schemas } from 'vs/base/common/network';
import { isEqual } from 'vs/base/common/resources';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ITextModel } from 'vs/editor/common/model';
class StackOperation implements IWorkspaceUndoRedoElement {
@ -224,29 +225,30 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
cells: ICellDto2[],
metadata: NotebookDocumentMetadata,
options: TransientOptions,
@IUndoRedoService private _undoService: IUndoRedoService,
@ITextModelService private _textModelService: ITextModelService,
@IUndoRedoService private readonly _undoService: IUndoRedoService,
@IModelService _modelService: IModelService,
@IModeService private readonly _modeService: IModeService,
) {
super();
this.transientOptions = options;
this.metadata = metadata;
this._initialize(cells);
this._register(_modelService.onModelAdded(e => {
if (e.uri.scheme === Schemas.vscodeNotebookCell) {
const cellUri = CellUri.parse(e.uri);
const maybeUpdateCellTextModel = (textModel: ITextModel) => {
if (textModel.uri.scheme === Schemas.vscodeNotebookCell) {
const cellUri = CellUri.parse(textModel.uri);
if (cellUri && isEqual(cellUri.notebook, this.uri)) {
const cellIdx = this._getCellIndexByHandle(cellUri.handle);
if (cellIdx >= 0) {
const cell = this.cells[cellIdx];
if (cell) {
cell.textModel = e;
cell.textModel = textModel;
}
}
}
}
}));
};
this._register(_modelService.onModelAdded(e => maybeUpdateCellTextModel(e)));
this._eventEmitter = new DelayedEmitter(
this._onDidChangeContent,
@ -271,7 +273,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
const mainCells = cells.map(cell => {
const cellHandle = this._cellhandlePool++;
const cellUri = CellUri.generate(this.uri, cellHandle);
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this.transientOptions, this._textModelService);
return new NotebookCellTextModel(cellUri, cellHandle, cell.source, cell.language, cell.cellKind, cell.outputs || [], cell.metadata, this.transientOptions, this._modeService);
});
for (let i = 0; i < mainCells.length; i++) {
@ -431,7 +433,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
const cell = new NotebookCellTextModel(
cellUri, cellHandle,
cellDto.source, cellDto.language, cellDto.cellKind, cellDto.outputs || [], cellDto.metadata, this.transientOptions,
this._textModelService
this._modeService
);
const dirtyStateListener = cell.onDidChangeContent(() => {
this._increaseVersionId();

View file

@ -15,6 +15,7 @@ import { IReference } from 'vs/base/common/lifecycle';
import { IResolvedNotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { ILabelService } from 'vs/platform/label/common/label';
import { Schemas } from 'vs/base/common/network';
import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
interface NotebookEditorInputOptions {
startDirty?: boolean;
@ -160,6 +161,8 @@ export class NotebookEditorInput extends EditorInput {
return null;
}
mark(this.resource, 'extensionActivated');
if (!this._editorModelReference) {
this._editorModelReference = await this._notebookModelResolverService.resolve(this.resource, this.viewType);
if (this.isDisposed()) {

View file

@ -0,0 +1,37 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
export type PerfName = 'startTime' | 'extensionActivated' | 'inputLoaded' | 'webviewCommLoaded' | 'customMarkdownLoaded' | 'editorLoaded';
type PerformanceMark = { [key in PerfName]?: number };
const perfMarks = new Map<string, PerformanceMark>();
export function mark(resource: URI, name: PerfName): void {
const key = resource.toString();
if (!perfMarks.has(key)) {
let perfMark: PerformanceMark = {};
perfMark[name] = Date.now();
perfMarks.set(key, perfMark);
} else {
perfMarks.get(key)![name] = Date.now();
}
}
export function clearMarks(resource: URI): void {
const key = resource.toString();
perfMarks.delete(key);
}
export function getAndClearMarks(resource: URI): PerformanceMark | null {
const key = resource.toString();
const perfMark = perfMarks.get(key) || null;
perfMarks.delete(key);
return perfMark;
}

View file

@ -7,11 +7,11 @@ import * as assert from 'assert';
import { NOTEBOOK_DISPLAY_ORDER, sortMimeTypes, CellKind, diff, CellUri, cellRangesToIndexes, cellIndexesToRanges } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { TestCell, setupInstantiationService } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
import { URI } from 'vs/base/common/uri';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IModeService } from 'vs/editor/common/services/modeService';
suite('NotebookCommon', () => {
const instantiationService = setupInstantiationService();
const textModelService = instantiationService.get(ITextModelService);
const modeService = instantiationService.get(IModeService);
test('sortMimeTypes default orders', function () {
const defaultDisplayOrder = NOTEBOOK_DISPLAY_ORDER;
@ -208,7 +208,7 @@ suite('NotebookCommon', () => {
for (let i = 0; i < 5; i++) {
cells.push(
new TestCell('notebook', i, `var a = ${i};`, 'javascript', CellKind.Code, [], textModelService)
new TestCell('notebook', i, `var a = ${i};`, 'javascript', CellKind.Code, [], modeService)
);
}
@ -234,8 +234,8 @@ suite('NotebookCommon', () => {
]
);
const cellA = new TestCell('notebook', 6, 'var a = 6;', 'javascript', CellKind.Code, [], textModelService);
const cellB = new TestCell('notebook', 7, 'var a = 7;', 'javascript', CellKind.Code, [], textModelService);
const cellA = new TestCell('notebook', 6, 'var a = 6;', 'javascript', CellKind.Code, [], modeService);
const cellB = new TestCell('notebook', 7, 'var a = 7;', 'javascript', CellKind.Code, [], modeService);
const modifiedCells = [
cells[0],

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { FoldingModel, updateFoldingStateAtIndex } from 'vs/workbench/contrib/notebook/browser/contrib/fold/foldingModel';
import { NotebookCellSelectionCollection } from 'vs/workbench/contrib/notebook/browser/viewModel/cellSelectionCollection';
import { CellEditType, CellKind, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
@ -22,7 +22,7 @@ suite('NotebookSelection', () => {
suite('NotebookCellList focus/selection', () => {
const instantiationService = setupInstantiationService();
const textModelService = instantiationService.get(ITextModelService);
const modeService = instantiationService.get(IModeService);
test('notebook cell list setFocus', async function () {
await withTestNotebook(
@ -212,8 +212,8 @@ suite('NotebookCellList focus/selection', () => {
// mimic undo
viewModel.notebookDocument.applyEdits([{
editType: CellEditType.Replace, index: 0, count: 0, cells: [
new TestCell(viewModel.viewType, 7, '# header f', 'markdown', CellKind.Code, [], textModelService),
new TestCell(viewModel.viewType, 8, 'var g = 5;', 'javascript', CellKind.Code, [], textModelService)
new TestCell(viewModel.viewType, 7, '# header f', 'markdown', CellKind.Code, [], modeService),
new TestCell(viewModel.viewType, 8, 'var g = 5;', 'javascript', CellKind.Code, [], modeService)
]
}], true, undefined, () => undefined, undefined, false);
viewModel.updateFoldingRanges(foldingModel.regions);

View file

@ -8,11 +8,11 @@ import { Range } from 'vs/editor/common/core/range';
import { CellKind, CellEditType, NotebookTextModelChangedEvent, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { withTestNotebook, TestCell, setupInstantiationService } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IModeService } from 'vs/editor/common/services/modeService';
suite('NotebookTextModel', () => {
const instantiationService = setupInstantiationService();
const textModelService = instantiationService.get(ITextModelService);
const modeService = instantiationService.get(IModeService);
instantiationService.spy(IUndoRedoService, 'pushElement');
test('insert', async function () {
@ -27,8 +27,8 @@ suite('NotebookTextModel', () => {
const viewModel = editor.viewModel;
const textModel = editor.viewModel.notebookDocument;
textModel.applyEdits([
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 3, count: 0, cells: [new TestCell(viewModel.viewType, 6, 'var f = 6;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], modeService)] },
{ editType: CellEditType.Replace, index: 3, count: 0, cells: [new TestCell(viewModel.viewType, 6, 'var f = 6;', 'javascript', CellKind.Code, [], modeService)] },
], true, undefined, () => undefined, undefined);
assert.strictEqual(textModel.cells.length, 6);
@ -51,8 +51,8 @@ suite('NotebookTextModel', () => {
const viewModel = editor.viewModel;
const textModel = editor.viewModel.notebookDocument;
textModel.applyEdits([
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 6, 'var f = 6;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], modeService)] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 6, 'var f = 6;', 'javascript', CellKind.Code, [], modeService)] },
], true, undefined, () => undefined, undefined);
assert.strictEqual(textModel.cells.length, 6);
@ -97,7 +97,7 @@ suite('NotebookTextModel', () => {
const textModel = editor.viewModel.notebookDocument;
textModel.applyEdits([
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [] },
{ editType: CellEditType.Replace, index: 3, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 3, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], modeService)] },
], true, undefined, () => undefined, undefined);
assert.strictEqual(textModel.cells.length, 4);
@ -121,7 +121,7 @@ suite('NotebookTextModel', () => {
const textModel = editor.viewModel.notebookDocument;
textModel.applyEdits([
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], modeService)] },
], true, undefined, () => undefined, undefined);
assert.strictEqual(textModel.cells.length, 4);
@ -144,7 +144,7 @@ suite('NotebookTextModel', () => {
const viewModel = editor.viewModel;
const textModel = editor.viewModel.notebookDocument;
textModel.applyEdits([
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], modeService)] },
], true, undefined, () => undefined, undefined);
assert.strictEqual(textModel.cells.length, 4);
@ -319,7 +319,7 @@ suite('NotebookTextModel', () => {
textModel.applyEdits([
{ editType: CellEditType.Replace, index: 1, count: 1, cells: [] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], textModelService)] },
{ editType: CellEditType.Replace, index: 1, count: 0, cells: [new TestCell(viewModel.viewType, 5, 'var e = 5;', 'javascript', CellKind.Code, [], modeService)] },
], true, undefined, () => ({ kind: SelectionStateType.Index, focus: { start: 0, end: 1 }, selections: [{ start: 0, end: 1 }] }), undefined);
assert.strictEqual(textModel.cells.length, 4);

View file

@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { TrackedRangeStickiness } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
@ -27,15 +28,16 @@ suite('NotebookViewModel', () => {
const bulkEditService = instantiationService.get(IBulkEditService);
const undoRedoService = instantiationService.get(IUndoRedoService);
const modelService = instantiationService.get(IModelService);
const modeService = instantiationService.get(IModeService);
instantiationService.stub(IConfigurationService, new TestConfigurationService());
instantiationService.stub(IThemeService, new TestThemeService());
test('ctor', function () {
const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], notebookDocumentMetadataDefaults, { transientMetadata: {}, transientOutputs: false }, undoRedoService, textModelService, modelService);
const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], notebookDocumentMetadataDefaults, { transientMetadata: {}, transientOutputs: false }, undoRedoService, modelService, modeService);
const model = new NotebookEditorTestModel(notebook);
const eventDispatcher = new NotebookEventDispatcher();
const viewModel = new NotebookViewModel('notebook', model.notebook, eventDispatcher, null, instantiationService, bulkEditService, undoRedoService, modelService);
const viewModel = new NotebookViewModel('notebook', model.notebook, eventDispatcher, null, instantiationService, bulkEditService, undoRedoService, textModelService);
assert.strictEqual(viewModel.viewType, 'notebook');
});

View file

@ -34,6 +34,8 @@ import { ListViewInfoAccessor } from 'vs/workbench/contrib/notebook/browser/note
import { mock } from 'vs/base/test/common/mock';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { BrowserClipboardService } from 'vs/platform/clipboard/browser/clipboardService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
export class TestCell extends NotebookCellTextModel {
constructor(
@ -43,9 +45,9 @@ export class TestCell extends NotebookCellTextModel {
language: string,
cellKind: CellKind,
outputs: IOutputDto[],
modelService: ITextModelService
modeService: IModeService,
) {
super(CellUri.generate(URI.parse('test:///fake/notebook'), handle), handle, source, language, cellKind, outputs, undefined, { transientMetadata: {}, transientOutputs: false }, modelService);
super(CellUri.generate(URI.parse('test:///fake/notebook'), handle), handle, source, language, cellKind, outputs, undefined, { transientMetadata: {}, transientOutputs: false }, modeService);
}
}
@ -123,6 +125,7 @@ export class NotebookEditorTestModel extends EditorModel implements INotebookEdi
export function setupInstantiationService() {
const instantiationService = new TestInstantiationService();
instantiationService.stub(IModeService, new ModeServiceImpl());
instantiationService.stub(IUndoRedoService, instantiationService.createInstance(UndoRedoService));
instantiationService.stub(IConfigurationService, new TestConfigurationService());
instantiationService.stub(IThemeService, new TestThemeService());