From f413297170178f16ab218202153b629d59a98be1 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 6 Jul 2022 18:33:04 +0200 Subject: joh/plastic fowl (#154275) * * derive workspace dto with util * be strict when defining reference version ids (must be set to a value or undefined) * relax `ResourceNotebookCellEdit` --- src/vs/editor/browser/services/bulkEditService.ts | 64 ++++++++++++++++------ src/vs/editor/common/languages.ts | 14 ++--- .../codeAction/test/browser/codeAction.test.ts | 2 +- src/vs/monaco.d.ts | 16 +++--- .../workbench/api/browser/mainThreadBulkEdits.ts | 31 +++++------ src/vs/workbench/api/common/extHost.protocol.ts | 47 +++------------- .../api/common/extHostDocumentSaveParticipant.ts | 8 +-- .../workbench/api/common/extHostTypeConverters.ts | 43 +++++++-------- .../api/test/browser/extHostBulkEdits.test.ts | 9 +-- .../browser/extHostDocumentSaveParticipant.test.ts | 6 +- .../api/test/browser/mainThreadEditors.test.ts | 23 ++++---- .../contrib/bulkEdit/browser/bulkCellEdits.ts | 26 +++++++-- .../browser/viewModel/notebookViewModelImpl.ts | 7 ++- .../contrib/notebook/common/notebookCommon.ts | 10 +++- 14 files changed, 159 insertions(+), 147 deletions(-) diff --git a/src/vs/editor/browser/services/bulkEditService.ts b/src/vs/editor/browser/services/bulkEditService.ts index 1fa168aedb1..1ec6fde3bfb 100644 --- a/src/vs/editor/browser/services/bulkEditService.ts +++ b/src/vs/editor/browser/services/bulkEditService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { TextEdit, WorkspaceEdit, WorkspaceEditMetadata, WorkspaceFileEdit, WorkspaceFileEditOptions, WorkspaceTextEdit } from 'vs/editor/common/languages'; +import { TextEdit, WorkspaceEdit, WorkspaceEditMetadata, IWorkspaceFileEdit, WorkspaceFileEditOptions, IWorkspaceTextEdit } from 'vs/editor/common/languages'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress'; import { IDisposable } from 'vs/base/common/lifecycle'; @@ -15,49 +15,77 @@ import { CancellationToken } from 'vs/base/common/cancellation'; export const IBulkEditService = createDecorator('IWorkspaceEditService'); -function isWorkspaceFileEdit(thing: any): thing is WorkspaceFileEdit { - return isObject(thing) && (Boolean((thing).newUri) || Boolean((thing).oldUri)); -} - -function isWorkspaceTextEdit(thing: any): thing is WorkspaceTextEdit { - return isObject(thing) && URI.isUri((thing).resource) && isObject((thing).edit); -} - export class ResourceEdit { protected constructor(readonly metadata?: WorkspaceEditMetadata) { } static convert(edit: WorkspaceEdit): ResourceEdit[] { - return edit.edits.map(edit => { - if (isWorkspaceTextEdit(edit)) { - return new ResourceTextEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata); + if (ResourceTextEdit.is(edit)) { + return ResourceTextEdit.lift(edit); } - if (isWorkspaceFileEdit(edit)) { - return new ResourceFileEdit(edit.oldUri, edit.newUri, edit.options, edit.metadata); + + if (ResourceFileEdit.is(edit)) { + return ResourceFileEdit.lift(edit); } throw new Error('Unsupported edit'); }); } } -export class ResourceTextEdit extends ResourceEdit { +export class ResourceTextEdit extends ResourceEdit implements IWorkspaceTextEdit { + + static is(candidate: any): candidate is IWorkspaceTextEdit { + if (candidate instanceof ResourceTextEdit) { + return true; + } + return isObject(candidate) + && URI.isUri((candidate).resource) + && isObject((candidate).textEdit); + } + + static lift(edit: IWorkspaceTextEdit): ResourceTextEdit { + if (edit instanceof ResourceTextEdit) { + return edit; + } else { + return new ResourceTextEdit(edit.resource, edit.textEdit, edit.versionId, edit.metadata); + } + } + constructor( readonly resource: URI, readonly textEdit: TextEdit & { insertAsSnippet?: boolean }, - readonly versionId?: number, + readonly versionId: number | undefined = undefined, metadata?: WorkspaceEditMetadata, ) { super(metadata); } } -export class ResourceFileEdit extends ResourceEdit { +export class ResourceFileEdit extends ResourceEdit implements IWorkspaceFileEdit { + + static is(candidate: any): candidate is IWorkspaceFileEdit { + if (candidate instanceof ResourceFileEdit) { + return true; + } else { + return isObject(candidate) + && (Boolean((candidate).newResource) || Boolean((candidate).oldResource)); + } + } + + static lift(edit: IWorkspaceFileEdit): ResourceFileEdit { + if (edit instanceof ResourceFileEdit) { + return edit; + } else { + return new ResourceFileEdit(edit.oldResource, edit.newResource, edit.options, edit.metadata); + } + } + constructor( readonly oldResource: URI | undefined, readonly newResource: URI | undefined, - readonly options?: WorkspaceFileEditOptions, + readonly options: WorkspaceFileEditOptions = {}, metadata?: WorkspaceEditMetadata ) { super(metadata); diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 0d97ad7329e..10baf2667c9 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -1412,22 +1412,22 @@ export interface WorkspaceFileEditOptions { maxSize?: number; } -export interface WorkspaceFileEdit { - oldUri?: URI; - newUri?: URI; +export interface IWorkspaceFileEdit { + oldResource?: URI; + newResource?: URI; options?: WorkspaceFileEditOptions; metadata?: WorkspaceEditMetadata; } -export interface WorkspaceTextEdit { +export interface IWorkspaceTextEdit { resource: URI; - edit: TextEdit; - modelVersionId?: number; + textEdit: TextEdit & { insertAsSnippet?: boolean }; + versionId: number | undefined; metadata?: WorkspaceEditMetadata; } export interface WorkspaceEdit { - edits: Array; + edits: Array; } export interface Rejection { diff --git a/src/vs/editor/contrib/codeAction/test/browser/codeAction.test.ts b/src/vs/editor/contrib/codeAction/test/browser/codeAction.test.ts index d1be6b9d645..93005d11387 100644 --- a/src/vs/editor/contrib/codeAction/test/browser/codeAction.test.ts +++ b/src/vs/editor/contrib/codeAction/test/browser/codeAction.test.ts @@ -73,7 +73,7 @@ suite('CodeAction', () => { bcd: { diagnostics: [], edit: new class implements languages.WorkspaceEdit { - edits!: languages.WorkspaceTextEdit[]; + edits!: languages.IWorkspaceTextEdit[]; }, title: 'abc' } diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 713083bfe0c..0ff87c1fdb8 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -7015,22 +7015,24 @@ declare namespace monaco.languages { maxSize?: number; } - export interface WorkspaceFileEdit { - oldUri?: Uri; - newUri?: Uri; + export interface IWorkspaceFileEdit { + oldResource?: Uri; + newResource?: Uri; options?: WorkspaceFileEditOptions; metadata?: WorkspaceEditMetadata; } - export interface WorkspaceTextEdit { + export interface IWorkspaceTextEdit { resource: Uri; - edit: TextEdit; - modelVersionId?: number; + textEdit: TextEdit & { + insertAsSnippet?: boolean; + }; + versionId: number | undefined; metadata?: WorkspaceEditMetadata; } export interface WorkspaceEdit { - edits: Array; + edits: Array; } export interface Rejection { diff --git a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts index e3e5d652a16..b47e47a7286 100644 --- a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts +++ b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts @@ -4,29 +4,28 @@ *--------------------------------------------------------------------------------------------*/ import { IBulkEditService, ResourceEdit, ResourceFileEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService'; -import { IWorkspaceEditDto, MainThreadBulkEditsShape, MainContext, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol'; +import { IWorkspaceEditDto, MainThreadBulkEditsShape, MainContext, reviveWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol'; import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; import { ILogService } from 'vs/platform/log/common/log'; -import { revive } from 'vs/base/common/marshalling'; import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits'; -import { NotebookDto } from 'vs/workbench/api/browser/mainThreadNotebookDto'; -export function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] { - if (!data?.edits) { +export function reviveWorkspaceEditDto2(data: IWorkspaceEditDto): ResourceEdit[] { + const edits = reviveWorkspaceEditDto(data)?.edits; + if (!edits) { return []; } - - const result: ResourceEdit[] = []; - for (const edit of revive(data).edits) { - if (edit._type === WorkspaceEditType.File) { - result.push(new ResourceFileEdit(edit.oldUri, edit.newUri, edit.options, edit.metadata)); - } else if (edit._type === WorkspaceEditType.Text) { - result.push(new ResourceTextEdit(edit.resource, edit.edit, edit.modelVersionId, edit.metadata)); - } else if (edit._type === WorkspaceEditType.Cell) { - result.push(new ResourceNotebookCellEdit(edit.resource, NotebookDto.fromCellEditOperationDto(edit.edit), edit.notebookVersionId, edit.metadata)); + return edits.map(edit => { + if (ResourceTextEdit.is(edit)) { + return ResourceTextEdit.lift(edit); } - } - return result; + if (ResourceFileEdit.is(edit)) { + return ResourceFileEdit.lift(edit); + } + if (ResourceNotebookCellEdit.is(edit)) { + return ResourceNotebookCellEdit.lift(edit); + } + throw new Error('Unsupported edit'); + }); } @extHostNamedCustomer(MainContext.MainThreadBulkEdits) diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index a7b203695df..2d062111195 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1587,27 +1587,6 @@ export interface IWorkspaceEditEntryMetadataDto { iconPath?: { id: string } | UriComponents | { light: UriComponents; dark: UriComponents }; } -export const enum WorkspaceEditType { - File = 1, - Text = 2, - Cell = 3, -} - -export interface IWorkspaceFileEditDto { - _type: WorkspaceEditType.File; - oldUri?: UriComponents; - newUri?: UriComponents; - options?: languages.WorkspaceFileEditOptions; - metadata?: IWorkspaceEditEntryMetadataDto; -} - -export interface IWorkspaceTextEditDto { - _type: WorkspaceEditType.Text; - resource: UriComponents; - edit: languages.TextEdit & { insertAsSnippet?: boolean }; - modelVersionId?: number; - metadata?: IWorkspaceEditEntryMetadataDto; -} export type ICellEditOperationDto = notebookCommon.ICellPartialMetadataEdit @@ -1619,31 +1598,19 @@ export type ICellEditOperationDto = cells: NotebookCellDataDto[]; }; -export interface IWorkspaceCellEditDto { - _type: WorkspaceEditType.Cell; - resource: UriComponents; - notebookVersionId?: number; - metadata?: IWorkspaceEditEntryMetadataDto; - edit: ICellEditOperationDto; -} +export type IWorkspaceCellEditDto = Dto> & { cellEdit: ICellEditOperationDto }; + +export type IWorkspaceFileEditDto = Dto; + +export type IWorkspaceTextEditDto = Dto; export interface IWorkspaceEditDto { edits: Array; } -export function reviveWorkspaceEditDto(data: IWorkspaceEditDto | undefined): languages.WorkspaceEdit { +export function reviveWorkspaceEditDto(data: IWorkspaceEditDto | undefined): languages.WorkspaceEdit | undefined { if (data && data.edits) { - for (const edit of data.edits) { - if (typeof (edit).resource === 'object') { - (edit).resource = URI.revive((edit).resource); - } else { - (edit).newUri = URI.revive((edit).newUri); - (edit).oldUri = URI.revive((edit).oldUri); - } - if (edit.metadata && edit.metadata.iconPath) { - edit.metadata = revive(edit.metadata); - } - } + revive(data); } return data; } diff --git a/src/vs/workbench/api/common/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/common/extHostDocumentSaveParticipant.ts index 05f7cb963d6..7a90e5db0f9 100644 --- a/src/vs/workbench/api/common/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/common/extHostDocumentSaveParticipant.ts @@ -6,7 +6,7 @@ import { Event } from 'vs/base/common/event'; import { URI, UriComponents } from 'vs/base/common/uri'; import { illegalState } from 'vs/base/common/errors'; -import { ExtHostDocumentSaveParticipantShape, IWorkspaceEditDto, WorkspaceEditType, MainThreadBulkEditsShape } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostDocumentSaveParticipantShape, IWorkspaceEditDto, MainThreadBulkEditsShape } from 'vs/workbench/api/common/extHost.protocol'; import { TextEdit } from 'vs/workbench/api/common/extHostTypes'; import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters'; import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; @@ -146,12 +146,12 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic if (Array.isArray(value) && (value).every(e => e instanceof TextEdit)) { for (const { newText, newEol, range } of value) { dto.edits.push({ - _type: WorkspaceEditType.Text, resource: document.uri, - edit: { + versionId: undefined, + textEdit: { range: range && Range.from(range), text: newText, - eol: newEol && EndOfLine.from(newEol) + eol: newEol && EndOfLine.from(newEol), } }); } diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 9b733dc8951..f7917e317d2 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -589,47 +589,44 @@ export namespace WorkspaceEdit { if (entry._type === types.FileEditType.File) { // file operation - result.edits.push({ - _type: extHostProtocol.WorkspaceEditType.File, - oldUri: entry.from, - newUri: entry.to, + result.edits.push({ + oldResource: entry.from, + newResource: entry.to, options: entry.options, metadata: entry.metadata }); } else if (entry._type === types.FileEditType.Text) { - // text edits - const dto = { - _type: extHostProtocol.WorkspaceEditType.Text, + const edit = { resource: entry.uri, - edit: TextEdit.from(entry.edit), - modelVersionId: !toCreate.has(entry.uri) ? versionInfo?.getTextDocumentVersion(entry.uri) : undefined, + textEdit: TextEdit.from(entry.edit), + versionId: !toCreate.has(entry.uri) ? versionInfo?.getTextDocumentVersion(entry.uri) : undefined, metadata: entry.metadata }; if (allowSnippetTextEdit && entry.edit.newText2 instanceof types.SnippetString) { - dto.edit.insertAsSnippet = true; - dto.edit.text = entry.edit.newText2.value; + edit.textEdit.insertAsSnippet = true; + edit.textEdit.text = entry.edit.newText2.value; } - result.edits.push(dto); + result.edits.push(edit); } else if (entry._type === types.FileEditType.Cell) { - result.edits.push({ - _type: extHostProtocol.WorkspaceEditType.Cell, + // cell edit + result.edits.push({ metadata: entry.metadata, resource: entry.uri, - edit: entry.edit, + cellEdit: entry.edit, notebookMetadata: entry.notebookMetadata, notebookVersionId: versionInfo?.getNotebookDocumentVersion(entry.uri) }); } else if (entry._type === types.FileEditType.CellReplace) { - result.edits.push({ - _type: extHostProtocol.WorkspaceEditType.Cell, + // cell replace + result.edits.push({ metadata: entry.metadata, resource: entry.uri, notebookVersionId: versionInfo?.getNotebookDocumentVersion(entry.uri), - edit: { + cellEdit: { editType: notebooks.CellEditType.Replace, index: entry.index, count: entry.count, @@ -645,16 +642,16 @@ export namespace WorkspaceEdit { export function to(value: extHostProtocol.IWorkspaceEditDto) { const result = new types.WorkspaceEdit(); for (const edit of value.edits) { - if ((edit).edit) { + if ((edit).textEdit) { result.replace( URI.revive((edit).resource), - Range.to((edit).edit.range), - (edit).edit.text + Range.to((edit).textEdit.range), + (edit).textEdit.text ); } else { result.renameFile( - URI.revive((edit).oldUri!), - URI.revive((edit).newUri!), + URI.revive((edit).oldResource!), + URI.revive((edit).newResource!), (edit).options ); } diff --git a/src/vs/workbench/api/test/browser/extHostBulkEdits.test.ts b/src/vs/workbench/api/test/browser/extHostBulkEdits.test.ts index 3b393b35347..906405cd6b7 100644 --- a/src/vs/workbench/api/test/browser/extHostBulkEdits.test.ts +++ b/src/vs/workbench/api/test/browser/extHostBulkEdits.test.ts @@ -4,13 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; import * as extHostTypes from 'vs/workbench/api/common/extHostTypes'; -import { MainContext, IWorkspaceEditDto, WorkspaceEditType, MainThreadBulkEditsShape } from 'vs/workbench/api/common/extHost.protocol'; +import { MainContext, IWorkspaceEditDto, MainThreadBulkEditsShape, IWorkspaceTextEditDto } from 'vs/workbench/api/common/extHost.protocol'; import { URI } from 'vs/base/common/uri'; import { mock } from 'vs/base/test/common/mock'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { SingleProxyRPCProtocol, TestRPCProtocol } from 'vs/workbench/api/test/common/testRPCProtocol'; import { NullLogService } from 'vs/platform/log/common/log'; -import { assertType } from 'vs/base/common/types'; import { ExtHostBulkEdits } from 'vs/workbench/api/common/extHostBulkEdits'; import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; @@ -50,8 +49,7 @@ suite('ExtHostBulkEdits.applyWorkspaceEdit', () => { await bulkEdits.applyWorkspaceEdit(edit, nullExtensionDescription); assert.strictEqual(workspaceResourceEdits.edits.length, 1); const [first] = workspaceResourceEdits.edits; - assertType(first._type === WorkspaceEditType.Text); - assert.strictEqual(first.modelVersionId, 1337); + assert.strictEqual((first).versionId, 1337); }); test('does not use version id if document is not available', async () => { @@ -60,8 +58,7 @@ suite('ExtHostBulkEdits.applyWorkspaceEdit', () => { await bulkEdits.applyWorkspaceEdit(edit, nullExtensionDescription); assert.strictEqual(workspaceResourceEdits.edits.length, 1); const [first] = workspaceResourceEdits.edits; - assertType(first._type === WorkspaceEditType.Text); - assert.ok(typeof first.modelVersionId === 'undefined'); + assert.ok(typeof (first).versionId === 'undefined'); }); }); diff --git a/src/vs/workbench/api/test/browser/extHostDocumentSaveParticipant.test.ts b/src/vs/workbench/api/test/browser/extHostDocumentSaveParticipant.test.ts index 70e338176d7..c50aabb812f 100644 --- a/src/vs/workbench/api/test/browser/extHostDocumentSaveParticipant.test.ts +++ b/src/vs/workbench/api/test/browser/extHostDocumentSaveParticipant.test.ts @@ -266,8 +266,8 @@ suite('ExtHostDocumentSaveParticipant', () => { sub.dispose(); assert.strictEqual(dto.edits.length, 2); - assert.ok((dto.edits[0]).edit); - assert.ok((dto.edits[1]).edit); + assert.ok((dto.edits[0]).textEdit); + assert.ok((dto.edits[1]).textEdit); }); }); @@ -317,7 +317,7 @@ suite('ExtHostDocumentSaveParticipant', () => { for (const edit of dto.edits) { const uri = URI.revive((edit).resource); - const { text, range } = (edit).edit; + const { text, range } = (edit).textEdit; documents.$acceptModelChanged(uri, { changes: [{ range, diff --git a/src/vs/workbench/api/test/browser/mainThreadEditors.test.ts b/src/vs/workbench/api/test/browser/mainThreadEditors.test.ts index dac02ac748e..859c9c28ee8 100644 --- a/src/vs/workbench/api/test/browser/mainThreadEditors.test.ts +++ b/src/vs/workbench/api/test/browser/mainThreadEditors.test.ts @@ -9,7 +9,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/ import { ModelService } from 'vs/editor/common/services/modelService'; import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; -import { IWorkspaceTextEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol'; +import { IWorkspaceTextEditDto } from 'vs/workbench/api/common/extHost.protocol'; import { mock } from 'vs/base/test/common/mock'; import { Event } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; @@ -197,10 +197,9 @@ suite('MainThreadEditors', () => { const model = modelService.createModel('something', null, resource); const workspaceResourceEdit: IWorkspaceTextEditDto = { - _type: WorkspaceEditType.Text, resource: resource, - modelVersionId: model.getVersionId(), - edit: { + versionId: model.getVersionId(), + textEdit: { text: 'asdfg', range: new Range(1, 1, 1, 1) } @@ -219,19 +218,17 @@ suite('MainThreadEditors', () => { const model = modelService.createModel('something', null, resource); const workspaceResourceEdit1: IWorkspaceTextEditDto = { - _type: WorkspaceEditType.Text, resource: resource, - modelVersionId: model.getVersionId(), - edit: { + versionId: model.getVersionId(), + textEdit: { text: 'asdfg', range: new Range(1, 1, 1, 1) } }; const workspaceResourceEdit2: IWorkspaceTextEditDto = { - _type: WorkspaceEditType.Text, resource: resource, - modelVersionId: model.getVersionId(), - edit: { + versionId: model.getVersionId(), + textEdit: { text: 'asdfg', range: new Range(1, 1, 1, 1) } @@ -251,9 +248,9 @@ suite('MainThreadEditors', () => { test(`applyWorkspaceEdit with only resource edit`, () => { return bulkEdits.$tryApplyWorkspaceEdit({ edits: [ - { _type: WorkspaceEditType.File, oldUri: resource, newUri: resource, options: undefined }, - { _type: WorkspaceEditType.File, oldUri: undefined, newUri: resource, options: undefined }, - { _type: WorkspaceEditType.File, oldUri: resource, newUri: undefined, options: undefined } + { oldResource: resource, newResource: resource, options: undefined }, + { oldResource: undefined, newResource: resource, options: undefined }, + { oldResource: resource, newResource: undefined, options: undefined } ] }).then((result) => { assert.strictEqual(result, true); diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts index 1f533a82ccc..0e870b7b639 100644 --- a/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts +++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts @@ -6,20 +6,36 @@ import { groupBy } from 'vs/base/common/arrays'; import { CancellationToken } from 'vs/base/common/cancellation'; import { compare } from 'vs/base/common/strings'; +import { isObject } from 'vs/base/common/types'; import { URI } from 'vs/base/common/uri'; import { ResourceEdit } from 'vs/editor/browser/services/bulkEditService'; import { WorkspaceEditMetadata } from 'vs/editor/common/languages'; import { IProgress } from 'vs/platform/progress/common/progress'; import { UndoRedoGroup, UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo'; -import { ICellEditOperation } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ICellPartialMetadataEdit, ICellReplaceEdit, IDocumentMetadataEdit, IWorkspaceNotebookCellEdit } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService'; -export class ResourceNotebookCellEdit extends ResourceEdit { +export class ResourceNotebookCellEdit extends ResourceEdit implements IWorkspaceNotebookCellEdit { + + static is(candidate: any): candidate is IWorkspaceNotebookCellEdit { + if (candidate instanceof ResourceNotebookCellEdit) { + return true; + } + return URI.isUri((candidate).resource) + && isObject((candidate).cellEdit); + } + + static lift(edit: IWorkspaceNotebookCellEdit): ResourceNotebookCellEdit { + if (edit instanceof ResourceNotebookCellEdit) { + return edit; + } + return new ResourceNotebookCellEdit(edit.resource, edit.cellEdit, edit.notebookVersionId, edit.metadata); + } constructor( readonly resource: URI, - readonly cellEdit: ICellEditOperation, - readonly versionId?: number, + readonly cellEdit: ICellPartialMetadataEdit | IDocumentMetadataEdit | ICellReplaceEdit, + readonly notebookVersionId: number | undefined = undefined, metadata?: WorkspaceEditMetadata ) { super(metadata); @@ -49,7 +65,7 @@ export class BulkCellEdits { const ref = await this._notebookModelService.resolve(first.resource); // check state - if (typeof first.versionId === 'number' && ref.object.notebook.versionId !== first.versionId) { + if (typeof first.notebookVersionId === 'number' && ref.object.notebook.versionId !== first.notebookVersionId) { ref.dispose(); throw new Error(`Notebook '${first.resource}' has changed in the meantime`); } diff --git a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl.ts b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl.ts index 951fbe0e2e2..a024bbe93a6 100644 --- a/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl.ts @@ -17,7 +17,7 @@ import { FindMatch, IModelDecorationOptions, IModelDeltaDecoration, TrackedRange import { MultiModelEditStackElement, SingleModelEditStackElement } from 'vs/editor/common/model/editStack'; import { IntervalNode, IntervalTree } from 'vs/editor/common/model/intervalTree'; import { ModelDecorationOptions } from 'vs/editor/common/model/textModel'; -import { WorkspaceTextEdit } from 'vs/editor/common/languages'; +import { IWorkspaceTextEdit } from 'vs/editor/common/languages'; import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { FoldingRegions } from 'vs/editor/contrib/folding/browser/foldingRanges'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -924,14 +924,15 @@ export class NotebookViewModel extends Disposable implements EditorFoldingStateD return; } - const textEdits: WorkspaceTextEdit[] = []; + const textEdits: IWorkspaceTextEdit[] = []; this._lastNotebookEditResource.push(matches[0].cell.uri); matches.forEach(match => { match.matches.forEach((singleMatch, index) => { if ((singleMatch as OutputFindMatch).index === undefined) { textEdits.push({ - edit: { range: (singleMatch as FindMatch).range, text: texts[index] }, + versionId: undefined, + textEdit: { range: (singleMatch as FindMatch).range, text: texts[index] }, resource: match.cell.uri }); } diff --git a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts index d0ccff06ccd..a95ecc6fb84 100644 --- a/src/vs/workbench/contrib/notebook/common/notebookCommon.ts +++ b/src/vs/workbench/contrib/notebook/common/notebookCommon.ts @@ -17,7 +17,7 @@ import { ISplice } from 'vs/base/common/sequence'; import { URI, UriComponents } from 'vs/base/common/uri'; import { ILineChange } from 'vs/editor/common/diff/diffComputer'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { Command } from 'vs/editor/common/languages'; +import { Command, WorkspaceEditMetadata } from 'vs/editor/common/languages'; import { IReadonlyTextBuffer } from 'vs/editor/common/model'; import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; @@ -497,6 +497,14 @@ export interface ICellMoveEdit { export type IImmediateCellEditOperation = ICellOutputEditByHandle | ICellPartialMetadataEditByHandle | ICellOutputItemEdit | ICellPartialInternalMetadataEdit | ICellPartialInternalMetadataEditByHandle | ICellPartialMetadataEdit; export type ICellEditOperation = IImmediateCellEditOperation | ICellReplaceEdit | ICellOutputEdit | ICellMetadataEdit | ICellPartialMetadataEdit | ICellPartialInternalMetadataEdit | IDocumentMetadataEdit | ICellMoveEdit | ICellOutputItemEdit | ICellLanguageEdit; + +export interface IWorkspaceNotebookCellEdit { + metadata?: WorkspaceEditMetadata; + resource: URI; + notebookVersionId: number | undefined; + cellEdit: ICellPartialMetadataEdit | IDocumentMetadataEdit | ICellReplaceEdit; +} + export interface NotebookData { readonly cells: ICellDto2[]; readonly metadata: NotebookDocumentMetadata; -- cgit v1.2.3