Path: blob/main/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { groupBy } from '../../../../base/common/arrays.js';6import { CancellationToken } from '../../../../base/common/cancellation.js';7import { compare } from '../../../../base/common/strings.js';8import { isObject } from '../../../../base/common/types.js';9import { URI } from '../../../../base/common/uri.js';10import { ResourceEdit } from '../../../../editor/browser/services/bulkEditService.js';11import { WorkspaceEditMetadata } from '../../../../editor/common/languages.js';12import { IProgress } from '../../../../platform/progress/common/progress.js';13import { UndoRedoGroup, UndoRedoSource } from '../../../../platform/undoRedo/common/undoRedo.js';14import { getNotebookEditorFromEditorPane } from '../../notebook/browser/notebookBrowser.js';15import { CellUri, ICellPartialMetadataEdit, ICellReplaceEdit, IDocumentMetadataEdit, ISelectionState, IWorkspaceNotebookCellEdit, SelectionStateType } from '../../notebook/common/notebookCommon.js';16import { INotebookEditorModelResolverService } from '../../notebook/common/notebookEditorModelResolverService.js';17import { IEditorService } from '../../../services/editor/common/editorService.js';1819export class ResourceNotebookCellEdit extends ResourceEdit implements IWorkspaceNotebookCellEdit {2021static is(candidate: any): candidate is IWorkspaceNotebookCellEdit {22if (candidate instanceof ResourceNotebookCellEdit) {23return true;24}25return URI.isUri((<IWorkspaceNotebookCellEdit>candidate).resource)26&& isObject((<IWorkspaceNotebookCellEdit>candidate).cellEdit);27}2829static lift(edit: IWorkspaceNotebookCellEdit): ResourceNotebookCellEdit {30if (edit instanceof ResourceNotebookCellEdit) {31return edit;32}33return new ResourceNotebookCellEdit(edit.resource, edit.cellEdit, edit.notebookVersionId, edit.metadata);34}3536constructor(37readonly resource: URI,38readonly cellEdit: ICellPartialMetadataEdit | IDocumentMetadataEdit | ICellReplaceEdit,39readonly notebookVersionId: number | undefined = undefined,40metadata?: WorkspaceEditMetadata41) {42super(metadata);43}44}4546export class BulkCellEdits {4748constructor(49private readonly _undoRedoGroup: UndoRedoGroup,50undoRedoSource: UndoRedoSource | undefined,51private readonly _progress: IProgress<void>,52private readonly _token: CancellationToken,53private readonly _edits: ResourceNotebookCellEdit[],54@IEditorService private readonly _editorService: IEditorService,55@INotebookEditorModelResolverService private readonly _notebookModelService: INotebookEditorModelResolverService,56) {57this._edits = this._edits.map(e => {58if (e.resource.scheme === CellUri.scheme) {59const uri = CellUri.parse(e.resource)?.notebook;60if (!uri) {61throw new Error(`Invalid notebook URI: ${e.resource}`);62}6364return new ResourceNotebookCellEdit(uri, e.cellEdit, e.notebookVersionId, e.metadata);65} else {66return e;67}68});69}7071async apply(): Promise<readonly URI[]> {72const resources: URI[] = [];73const editsByNotebook = groupBy(this._edits, (a, b) => compare(a.resource.toString(), b.resource.toString()));7475for (const group of editsByNotebook) {76if (this._token.isCancellationRequested) {77break;78}79const [first] = group;80const ref = await this._notebookModelService.resolve(first.resource);8182// check state83if (typeof first.notebookVersionId === 'number' && ref.object.notebook.versionId !== first.notebookVersionId) {84ref.dispose();85throw new Error(`Notebook '${first.resource}' has changed in the meantime`);86}8788// apply edits89const edits = group.map(entry => entry.cellEdit);90const computeUndo = !ref.object.isReadonly();91const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane);92const initialSelectionState: ISelectionState | undefined = editor?.textModel?.uri.toString() === ref.object.notebook.uri.toString() ? {93kind: SelectionStateType.Index,94focus: editor.getFocus(),95selections: editor.getSelections()96} : undefined;97ref.object.notebook.applyEdits(edits, true, initialSelectionState, () => undefined, this._undoRedoGroup, computeUndo);98ref.dispose();99100this._progress.report(undefined);101102resources.push(first.resource);103}104105return resources;106}107}108109110