Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/bulkEdit/browser/conflicts.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 { IFileService } from '../../../../platform/files/common/files.js';
7
import { URI } from '../../../../base/common/uri.js';
8
import { IModelService } from '../../../../editor/common/services/model.js';
9
import { ResourceMap } from '../../../../base/common/map.js';
10
import { DisposableStore } from '../../../../base/common/lifecycle.js';
11
import { Emitter, Event } from '../../../../base/common/event.js';
12
import { ITextModel } from '../../../../editor/common/model.js';
13
import { ResourceEdit, ResourceFileEdit, ResourceTextEdit } from '../../../../editor/browser/services/bulkEditService.js';
14
import { ResourceNotebookCellEdit } from './bulkCellEdits.js';
15
import { ILogService } from '../../../../platform/log/common/log.js';
16
17
export class ConflictDetector {
18
19
private readonly _conflicts = new ResourceMap<boolean>();
20
private readonly _disposables = new DisposableStore();
21
22
private readonly _onDidConflict = new Emitter<this>();
23
readonly onDidConflict: Event<this> = this._onDidConflict.event;
24
25
constructor(
26
edits: ResourceEdit[],
27
@IFileService fileService: IFileService,
28
@IModelService modelService: IModelService,
29
@ILogService logService: ILogService,
30
) {
31
32
const _workspaceEditResources = new ResourceMap<boolean>();
33
34
for (const edit of edits) {
35
if (edit instanceof ResourceTextEdit) {
36
_workspaceEditResources.set(edit.resource, true);
37
if (typeof edit.versionId === 'number') {
38
const model = modelService.getModel(edit.resource);
39
if (model && model.getVersionId() !== edit.versionId) {
40
this._conflicts.set(edit.resource, true);
41
this._onDidConflict.fire(this);
42
}
43
}
44
45
} else if (edit instanceof ResourceFileEdit) {
46
if (edit.newResource) {
47
_workspaceEditResources.set(edit.newResource, true);
48
49
} else if (edit.oldResource) {
50
_workspaceEditResources.set(edit.oldResource, true);
51
}
52
} else if (edit instanceof ResourceNotebookCellEdit) {
53
_workspaceEditResources.set(edit.resource, true);
54
55
} else {
56
logService.warn('UNKNOWN edit type', edit);
57
}
58
}
59
60
// listen to file changes
61
this._disposables.add(fileService.onDidFilesChange(e => {
62
63
for (const uri of _workspaceEditResources.keys()) {
64
// conflict happens when a file that we are working
65
// on changes on disk. ignore changes for which a model
66
// exists because we have a better check for models
67
if (!modelService.getModel(uri) && e.contains(uri)) {
68
this._conflicts.set(uri, true);
69
this._onDidConflict.fire(this);
70
break;
71
}
72
}
73
}));
74
75
// listen to model changes...?
76
const onDidChangeModel = (model: ITextModel) => {
77
78
// conflict
79
if (_workspaceEditResources.has(model.uri)) {
80
this._conflicts.set(model.uri, true);
81
this._onDidConflict.fire(this);
82
}
83
};
84
for (const model of modelService.getModels()) {
85
this._disposables.add(model.onDidChangeContent(() => onDidChangeModel(model)));
86
}
87
}
88
89
dispose(): void {
90
this._disposables.dispose();
91
this._onDidConflict.dispose();
92
}
93
94
list(): URI[] {
95
return [...this._conflicts.keys()];
96
}
97
98
hasConflicts(): boolean {
99
return this._conflicts.size > 0;
100
}
101
}
102
103