Path: blob/main/src/vs/workbench/contrib/bulkEdit/browser/conflicts.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 { IFileService } from '../../../../platform/files/common/files.js';6import { URI } from '../../../../base/common/uri.js';7import { IModelService } from '../../../../editor/common/services/model.js';8import { ResourceMap } from '../../../../base/common/map.js';9import { DisposableStore } from '../../../../base/common/lifecycle.js';10import { Emitter, Event } from '../../../../base/common/event.js';11import { ITextModel } from '../../../../editor/common/model.js';12import { ResourceEdit, ResourceFileEdit, ResourceTextEdit } from '../../../../editor/browser/services/bulkEditService.js';13import { ResourceNotebookCellEdit } from './bulkCellEdits.js';14import { ILogService } from '../../../../platform/log/common/log.js';1516export class ConflictDetector {1718private readonly _conflicts = new ResourceMap<boolean>();19private readonly _disposables = new DisposableStore();2021private readonly _onDidConflict = new Emitter<this>();22readonly onDidConflict: Event<this> = this._onDidConflict.event;2324constructor(25edits: ResourceEdit[],26@IFileService fileService: IFileService,27@IModelService modelService: IModelService,28@ILogService logService: ILogService,29) {3031const _workspaceEditResources = new ResourceMap<boolean>();3233for (const edit of edits) {34if (edit instanceof ResourceTextEdit) {35_workspaceEditResources.set(edit.resource, true);36if (typeof edit.versionId === 'number') {37const model = modelService.getModel(edit.resource);38if (model && model.getVersionId() !== edit.versionId) {39this._conflicts.set(edit.resource, true);40this._onDidConflict.fire(this);41}42}4344} else if (edit instanceof ResourceFileEdit) {45if (edit.newResource) {46_workspaceEditResources.set(edit.newResource, true);4748} else if (edit.oldResource) {49_workspaceEditResources.set(edit.oldResource, true);50}51} else if (edit instanceof ResourceNotebookCellEdit) {52_workspaceEditResources.set(edit.resource, true);5354} else {55logService.warn('UNKNOWN edit type', edit);56}57}5859// listen to file changes60this._disposables.add(fileService.onDidFilesChange(e => {6162for (const uri of _workspaceEditResources.keys()) {63// conflict happens when a file that we are working64// on changes on disk. ignore changes for which a model65// exists because we have a better check for models66if (!modelService.getModel(uri) && e.contains(uri)) {67this._conflicts.set(uri, true);68this._onDidConflict.fire(this);69break;70}71}72}));7374// listen to model changes...?75const onDidChangeModel = (model: ITextModel) => {7677// conflict78if (_workspaceEditResources.has(model.uri)) {79this._conflicts.set(model.uri, true);80this._onDidConflict.fire(this);81}82};83for (const model of modelService.getModels()) {84this._disposables.add(model.onDidChangeContent(() => onDidChangeModel(model)));85}86}8788dispose(): void {89this._disposables.dispose();90this._onDidConflict.dispose();91}9293list(): URI[] {94return [...this._conflicts.keys()];95}9697hasConflicts(): boolean {98return this._conflicts.size > 0;99}100}101102103