Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { groupBy } from '../../../../base/common/arrays.js';
7
import { CancellationToken } from '../../../../base/common/cancellation.js';
8
import { compare } from '../../../../base/common/strings.js';
9
import { isObject } from '../../../../base/common/types.js';
10
import { URI } from '../../../../base/common/uri.js';
11
import { ResourceEdit } from '../../../../editor/browser/services/bulkEditService.js';
12
import { WorkspaceEditMetadata } from '../../../../editor/common/languages.js';
13
import { IProgress } from '../../../../platform/progress/common/progress.js';
14
import { UndoRedoGroup, UndoRedoSource } from '../../../../platform/undoRedo/common/undoRedo.js';
15
import { getNotebookEditorFromEditorPane } from '../../notebook/browser/notebookBrowser.js';
16
import { CellUri, ICellPartialMetadataEdit, ICellReplaceEdit, IDocumentMetadataEdit, ISelectionState, IWorkspaceNotebookCellEdit, SelectionStateType } from '../../notebook/common/notebookCommon.js';
17
import { INotebookEditorModelResolverService } from '../../notebook/common/notebookEditorModelResolverService.js';
18
import { IEditorService } from '../../../services/editor/common/editorService.js';
19
20
export class ResourceNotebookCellEdit extends ResourceEdit implements IWorkspaceNotebookCellEdit {
21
22
static is(candidate: any): candidate is IWorkspaceNotebookCellEdit {
23
if (candidate instanceof ResourceNotebookCellEdit) {
24
return true;
25
}
26
return URI.isUri((<IWorkspaceNotebookCellEdit>candidate).resource)
27
&& isObject((<IWorkspaceNotebookCellEdit>candidate).cellEdit);
28
}
29
30
static lift(edit: IWorkspaceNotebookCellEdit): ResourceNotebookCellEdit {
31
if (edit instanceof ResourceNotebookCellEdit) {
32
return edit;
33
}
34
return new ResourceNotebookCellEdit(edit.resource, edit.cellEdit, edit.notebookVersionId, edit.metadata);
35
}
36
37
constructor(
38
readonly resource: URI,
39
readonly cellEdit: ICellPartialMetadataEdit | IDocumentMetadataEdit | ICellReplaceEdit,
40
readonly notebookVersionId: number | undefined = undefined,
41
metadata?: WorkspaceEditMetadata
42
) {
43
super(metadata);
44
}
45
}
46
47
export class BulkCellEdits {
48
49
constructor(
50
private readonly _undoRedoGroup: UndoRedoGroup,
51
undoRedoSource: UndoRedoSource | undefined,
52
private readonly _progress: IProgress<void>,
53
private readonly _token: CancellationToken,
54
private readonly _edits: ResourceNotebookCellEdit[],
55
@IEditorService private readonly _editorService: IEditorService,
56
@INotebookEditorModelResolverService private readonly _notebookModelService: INotebookEditorModelResolverService,
57
) {
58
this._edits = this._edits.map(e => {
59
if (e.resource.scheme === CellUri.scheme) {
60
const uri = CellUri.parse(e.resource)?.notebook;
61
if (!uri) {
62
throw new Error(`Invalid notebook URI: ${e.resource}`);
63
}
64
65
return new ResourceNotebookCellEdit(uri, e.cellEdit, e.notebookVersionId, e.metadata);
66
} else {
67
return e;
68
}
69
});
70
}
71
72
async apply(): Promise<readonly URI[]> {
73
const resources: URI[] = [];
74
const editsByNotebook = groupBy(this._edits, (a, b) => compare(a.resource.toString(), b.resource.toString()));
75
76
for (const group of editsByNotebook) {
77
if (this._token.isCancellationRequested) {
78
break;
79
}
80
const [first] = group;
81
const ref = await this._notebookModelService.resolve(first.resource);
82
83
// check state
84
if (typeof first.notebookVersionId === 'number' && ref.object.notebook.versionId !== first.notebookVersionId) {
85
ref.dispose();
86
throw new Error(`Notebook '${first.resource}' has changed in the meantime`);
87
}
88
89
// apply edits
90
const edits = group.map(entry => entry.cellEdit);
91
const computeUndo = !ref.object.isReadonly();
92
const editor = getNotebookEditorFromEditorPane(this._editorService.activeEditorPane);
93
const initialSelectionState: ISelectionState | undefined = editor?.textModel?.uri.toString() === ref.object.notebook.uri.toString() ? {
94
kind: SelectionStateType.Index,
95
focus: editor.getFocus(),
96
selections: editor.getSelections()
97
} : undefined;
98
ref.object.notebook.applyEdits(edits, true, initialSelectionState, () => undefined, this._undoRedoGroup, computeUndo);
99
ref.dispose();
100
101
this._progress.report(undefined);
102
103
resources.push(first.resource);
104
}
105
106
return resources;
107
}
108
}
109
110