提交 36650056 编写于 作者: J Johannes Rieken

add undo options (undo group id, isUndoing) to working copy service and bulk edit logic

上级 71fce013
......@@ -70,6 +70,7 @@ export interface IBulkEditOptions {
label?: string;
quotableLabel?: string;
undoRedoSource?: UndoRedoSource;
undoRedoGroupId?: number;
}
export interface IBulkEditResult {
......
......@@ -37,8 +37,8 @@ export class MainThreadBulkEdits implements MainThreadBulkEditsShape {
dispose(): void { }
$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto): Promise<boolean> {
$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto, undoRedoGroupId?: number): Promise<boolean> {
const edits = reviveWorkspaceEditDto2(dto);
return this._bulkEditService.apply(edits).then(() => true, _err => false);
return this._bulkEditService.apply(edits, { undoRedoGroupId }).then(() => true, _err => false);
}
}
......@@ -54,11 +54,13 @@ export class MainThreadFileSystemEventService {
// BEFORE file operation
workingCopyFileService.addFileOperationParticipant({
participate: (files, operation, progress, timeout, token) => {
return proxy.$onWillRunFileOperation(operation, files, timeout, token);
this._listener.add(workingCopyFileService.addFileOperationParticipant({
participate: async (files, operation, undoRedoGroupId, isUndoing, _progress, timeout, token) => {
if (!isUndoing) {
return proxy.$onWillRunFileOperation(operation, files, undoRedoGroupId, timeout, token);
}
}
});
}));
// AFTER file operation
this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => proxy.$onDidRunFileOperation(e.operation, e.files)));
......
......@@ -269,7 +269,7 @@ export interface ITextDocumentShowOptions {
}
export interface MainThreadBulkEditsShape extends IDisposable {
$tryApplyWorkspaceEdit(workspaceEditDto: IWorkspaceEditDto): Promise<boolean>;
$tryApplyWorkspaceEdit(workspaceEditDto: IWorkspaceEditDto, undoRedoGroupId?: number): Promise<boolean>;
}
export interface MainThreadTextEditorsShape extends IDisposable {
......@@ -1139,7 +1139,7 @@ export interface SourceTargetPair {
export interface ExtHostFileSystemEventServiceShape {
$onFileEvent(events: FileSystemEvents): void;
$onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<any>;
$onWillRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[], undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise<any>;
$onDidRunFileOperation(operation: files.FileOperation, files: SourceTargetPair[]): void;
}
......
......@@ -178,23 +178,23 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
};
}
async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], timeout: number, token: CancellationToken): Promise<any> {
async $onWillRunFileOperation(operation: FileOperation, files: SourceTargetPair[], undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise<any> {
switch (operation) {
case FileOperation.MOVE:
await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, timeout, token);
await this._fireWillEvent(this._onWillRenameFile, { files: files.map(f => ({ oldUri: URI.revive(f.source!), newUri: URI.revive(f.target) })) }, undoRedoGroupId, timeout, token);
break;
case FileOperation.DELETE:
await this._fireWillEvent(this._onWillDeleteFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token);
await this._fireWillEvent(this._onWillDeleteFile, { files: files.map(f => URI.revive(f.target)) }, undoRedoGroupId, timeout, token);
break;
case FileOperation.CREATE:
await this._fireWillEvent(this._onWillCreateFile, { files: files.map(f => URI.revive(f.target)) }, timeout, token);
await this._fireWillEvent(this._onWillCreateFile, { files: files.map(f => URI.revive(f.target)) }, undoRedoGroupId, timeout, token);
break;
default:
//ignore, dont send
}
}
private async _fireWillEvent<E extends IWaitUntil>(emitter: AsyncEmitter<E>, data: Omit<E, 'waitUntil'>, timeout: number, token: CancellationToken): Promise<any> {
private async _fireWillEvent<E extends IWaitUntil>(emitter: AsyncEmitter<E>, data: Omit<E, 'waitUntil'>, undoRedoGroupId: number | undefined, timeout: number, token: CancellationToken): Promise<any> {
const edits: WorkspaceEdit[] = [];
......@@ -222,7 +222,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors);
dto.edits = dto.edits.concat(edits);
}
return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit(dto);
return this._mainThreadBulkEdits.$tryApplyWorkspaceEdit(dto, undoRedoGroupId);
}
}
}
......@@ -17,6 +17,7 @@ import { BulkTextEdits } from 'vs/workbench/contrib/bulkEdit/browser/bulkTextEdi
import { BulkFileEdits } from 'vs/workbench/contrib/bulkEdit/browser/bulkFileEdits';
import { BulkCellEdits, ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits';
import { UndoRedoGroup, UndoRedoSource } from 'vs/platform/undoRedo/common/undoRedo';
import { LinkedList } from 'vs/base/common/linkedList';
class BulkEdit {
......@@ -25,6 +26,7 @@ class BulkEdit {
private readonly _editor: ICodeEditor | undefined,
private readonly _progress: IProgress<IProgressStep>,
private readonly _edits: ResourceEdit[],
private readonly _undoRedoGroup: UndoRedoGroup,
private readonly _undoRedoSource: UndoRedoSource | undefined,
@IInstantiationService private readonly _instaService: IInstantiationService,
@ILogService private readonly _logService: ILogService,
......@@ -62,17 +64,15 @@ class BulkEdit {
this._progress.report({ total: this._edits.length });
const progress: IProgress<void> = { report: _ => this._progress.report({ increment: 1 }) };
const undoRedoGroup = new UndoRedoGroup();
let index = 0;
for (let range of ranges) {
const group = this._edits.slice(index, index + range);
if (group[0] instanceof ResourceFileEdit) {
await this._performFileEdits(<ResourceFileEdit[]>group, undoRedoGroup, this._undoRedoSource, progress);
await this._performFileEdits(<ResourceFileEdit[]>group, this._undoRedoGroup, this._undoRedoSource, progress);
} else if (group[0] instanceof ResourceTextEdit) {
await this._performTextEdits(<ResourceTextEdit[]>group, undoRedoGroup, this._undoRedoSource, progress);
await this._performTextEdits(<ResourceTextEdit[]>group, this._undoRedoGroup, this._undoRedoSource, progress);
} else if (group[0] instanceof ResourceNotebookCellEdit) {
await this._performCellEdits(<ResourceNotebookCellEdit[]>group, undoRedoGroup, this._undoRedoSource, progress);
await this._performCellEdits(<ResourceNotebookCellEdit[]>group, this._undoRedoGroup, this._undoRedoSource, progress);
} else {
console.log('UNKNOWN EDIT');
}
......@@ -103,6 +103,7 @@ export class BulkEditService implements IBulkEditService {
declare readonly _serviceBrand: undefined;
private readonly _activeUndoRedoGroups = new LinkedList<UndoRedoGroup>();
private _previewHandler?: IBulkEditPreviewHandler;
constructor(
......@@ -148,11 +149,30 @@ export class BulkEditService implements IBulkEditService {
codeEditor = undefined;
}
// undo-redo-group: if a group id is passed then try to find it
// in the list of active edits. otherwise (or when not found)
// create a separate undo-redo-group
let undoRedoGroup: UndoRedoGroup | undefined;
let undoRedoGroupRemove = () => { };
if (typeof options?.undoRedoGroupId === 'number') {
for (let candidate of this._activeUndoRedoGroups) {
if (candidate.id === options.undoRedoGroupId) {
undoRedoGroup = candidate;
break;
}
}
}
if (!undoRedoGroup) {
undoRedoGroup = new UndoRedoGroup();
undoRedoGroupRemove = this._activeUndoRedoGroups.push(undoRedoGroup);
}
const bulkEdit = this._instaService.createInstance(
BulkEdit,
options?.quotableLabel || options?.label,
codeEditor, options?.progress ?? Progress.None,
edits,
undoRedoGroup,
options?.undoRedoSource
);
......@@ -164,6 +184,8 @@ export class BulkEditService implements IBulkEditService {
// console.log(err);
this._logService.error(err);
throw err;
} finally {
undoRedoGroupRemove();
}
}
}
......
......@@ -17,6 +17,11 @@ import { VSBuffer } from 'vs/base/common/buffer';
import { ResourceFileEdit } from 'vs/editor/browser/services/bulkEditService';
import * as resources from 'vs/base/common/resources';
interface IFileOperationUndoRedoInfo {
undoRedoGroupId?: number;
isUndoing?: boolean;
}
interface IFileOperation {
uris: URI[];
perform(): Promise<IFileOperation>;
......@@ -36,6 +41,7 @@ class RenameOperation implements IFileOperation {
readonly newUri: URI,
readonly oldUri: URI,
readonly options: WorkspaceFileEditOptions,
readonly undoRedoInfo: IFileOperationUndoRedoInfo,
@IWorkingCopyFileService private readonly _workingCopyFileService: IWorkingCopyFileService,
@IFileService private readonly _fileService: IFileService,
) { }
......@@ -50,8 +56,8 @@ class RenameOperation implements IFileOperation {
return new Noop(); // not overwriting, but ignoring, and the target file exists
}
await this._workingCopyFileService.move([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite });
return new RenameOperation(this.oldUri, this.newUri, this.options, this._workingCopyFileService, this._fileService);
await this._workingCopyFileService.move([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo });
return new RenameOperation(this.oldUri, this.newUri, this.options, { isUndoing: true }, this._workingCopyFileService, this._fileService);
}
toString(): string {
......@@ -70,6 +76,7 @@ class CopyOperation implements IFileOperation {
readonly newUri: URI,
readonly oldUri: URI,
readonly options: WorkspaceFileEditOptions,
readonly undoRedoInfo: IFileOperationUndoRedoInfo,
@IWorkingCopyFileService private readonly _workingCopyFileService: IWorkingCopyFileService,
@IFileService private readonly _fileService: IFileService,
@IInstantiationService private readonly _instaService: IInstantiationService
......@@ -85,8 +92,8 @@ class CopyOperation implements IFileOperation {
return new Noop(); // not overwriting, but ignoring, and the target file exists
}
await this._workingCopyFileService.copy([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite });
return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, true);
await this._workingCopyFileService.copy([{ source: this.oldUri, target: this.newUri }], { overwrite: this.options.overwrite, ...this.undoRedoInfo });
return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, true);
}
toString(): string {
......@@ -99,6 +106,7 @@ class CreateOperation implements IFileOperation {
constructor(
readonly newUri: URI,
readonly options: WorkspaceFileEditOptions,
readonly undoRedoInfo: IFileOperationUndoRedoInfo,
readonly contents: VSBuffer | undefined,
@IFileService private readonly _fileService: IFileService,
@IWorkingCopyFileService private readonly _workingCopyFileService: IWorkingCopyFileService,
......@@ -115,11 +123,11 @@ class CreateOperation implements IFileOperation {
return new Noop(); // not overwriting, but ignoring, and the target file exists
}
if (this.options.folder) {
await this._workingCopyFileService.createFolder(this.newUri);
await this._workingCopyFileService.createFolder(this.newUri, { ...this.undoRedoInfo });
} else {
await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite });
await this._workingCopyFileService.create(this.newUri, this.contents, { overwrite: this.options.overwrite, ...this.undoRedoInfo });
}
return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, !this.options.folder);
return this._instaService.createInstance(DeleteOperation, this.newUri, this.options, { isUndoing: true }, !this.options.folder);
}
toString(): string {
......@@ -133,6 +141,7 @@ class DeleteOperation implements IFileOperation {
constructor(
readonly oldUri: URI,
readonly options: WorkspaceFileEditOptions,
readonly undoRedoInfo: IFileOperationUndoRedoInfo,
private readonly _undoesCreateOperation: boolean,
@IWorkingCopyFileService private readonly _workingCopyFileService: IWorkingCopyFileService,
@IFileService private readonly _fileService: IFileService,
......@@ -164,8 +173,8 @@ class DeleteOperation implements IFileOperation {
}
const useTrash = this._fileService.hasCapability(this.oldUri, FileSystemProviderCapabilities.Trash) && this._configurationService.getValue<boolean>('files.enableTrash');
await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive });
return this._instaService.createInstance(CreateOperation, this.oldUri, this.options, contents);
await this._workingCopyFileService.delete([this.oldUri], { useTrash, recursive: this.options.recursive, ...this.undoRedoInfo });
return this._instaService.createInstance(CreateOperation, this.oldUri, this.options, { isUndoing: true }, contents);
}
toString(): string {
......@@ -221,6 +230,7 @@ export class BulkFileEdits {
async apply(): Promise<void> {
const undoOperations: IFileOperation[] = [];
const undoRedoInfo = { undoRedoGroupId: this._undoRedoGroup.id };
for (const edit of this._edits) {
this._progress.report(undefined);
......@@ -228,15 +238,15 @@ export class BulkFileEdits {
let op: IFileOperation | undefined;
if (edit.newResource && edit.oldResource && !options.copy) {
// rename
op = this._instaService.createInstance(RenameOperation, edit.newResource, edit.oldResource, options);
op = this._instaService.createInstance(RenameOperation, edit.newResource, edit.oldResource, options, undoRedoInfo);
} else if (edit.newResource && edit.oldResource && options.copy) {
op = this._instaService.createInstance(CopyOperation, edit.newResource, edit.oldResource, options);
op = this._instaService.createInstance(CopyOperation, edit.newResource, edit.oldResource, options, undoRedoInfo);
} else if (!edit.newResource && edit.oldResource) {
// delete file
op = this._instaService.createInstance(DeleteOperation, edit.oldResource, options, false);
op = this._instaService.createInstance(DeleteOperation, edit.oldResource, options, undoRedoInfo, false);
} else if (edit.newResource && !edit.oldResource) {
// create file
op = this._instaService.createInstance(CreateOperation, edit.newResource, options, undefined);
op = this._instaService.createInstance(CreateOperation, edit.newResource, options, undoRedoInfo, undefined);
}
if (op) {
const undoOp = await op.perform();
......
......@@ -33,7 +33,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable {
return toDisposable(() => remove());
}
async participate(files: { source?: URI, target: URI }[], operation: FileOperation): Promise<void> {
async participate(files: { source?: URI, target: URI }[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined): Promise<void> {
const timeout = this.configurationService.getValue<number>('files.participants.timeout');
if (timeout <= 0) {
return; // disabled
......@@ -53,7 +53,7 @@ export class WorkingCopyFileOperationParticipant extends Disposable {
}
try {
const promise = participant.participate(files, operation, progress, timeout, cts.token);
const promise = participant.participate(files, operation, undoRedoGroupId, isUndoing, progress, timeout, cts.token);
await raceTimeout(promise, timeout, () => cts.dispose(true /* cancel */));
} catch (err) {
this.logService.warn(err);
......
......@@ -60,6 +60,8 @@ export interface IWorkingCopyFileOperationParticipant {
participate(
files: SourceTargetPair[],
operation: FileOperation,
undoRedoGroupId: number | undefined,
isUndoing: boolean | undefined,
progress: IProgress<IProgressStep>,
timeout: number,
token: CancellationToken
......@@ -130,7 +132,7 @@ export interface IWorkingCopyFileService {
* Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
* `onDidRunWorkingCopyFileOperation` events to participate.
*/
create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata>;
create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata>;
/**
* Will create a folder and any parent folder that needs to be created.
......@@ -141,7 +143,7 @@ export interface IWorkingCopyFileService {
* Note: events will only be emitted for the provided resource, but not any
* parent folders that are being created as part of the operation.
*/
createFolder(resource: URI): Promise<IFileStatWithMetadata>;
createFolder(resource: URI, options?: { undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata>;
/**
* Will move working copies matching the provided resources and corresponding children
......@@ -150,7 +152,7 @@ export interface IWorkingCopyFileService {
* Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
* `onDidRunWorkingCopyFileOperation` events to participate.
*/
move(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata[]>;
move(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata[]>;
/**
* Will copy working copies matching the provided resources and corresponding children
......@@ -159,7 +161,7 @@ export interface IWorkingCopyFileService {
* Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
* `onDidRunWorkingCopyFileOperation` events to participate.
*/
copy(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata[]>;
copy(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata[]>;
/**
* Will delete working copies matching the provided resources and children
......@@ -168,7 +170,7 @@ export interface IWorkingCopyFileService {
* Working copy owners can listen to the `onWillRunWorkingCopyFileOperation` and
* `onDidRunWorkingCopyFileOperation` events to participate.
*/
delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean }): Promise<void>;
delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<void>;
//#endregion
......@@ -237,15 +239,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
//#region File operations
create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata> {
create(resource: URI, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata> {
return this.doCreateFileOrFolder(resource, true, contents, options);
}
createFolder(resource: URI, options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata> {
return this.doCreateFileOrFolder(resource, false);
createFolder(resource: URI, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata> {
return this.doCreateFileOrFolder(resource, false, undefined, options);
}
async doCreateFileOrFolder(resource: URI, isFile: boolean, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata> {
async doCreateFileOrFolder(resource: URI, isFile: boolean, contents?: VSBuffer | VSBufferReadable | VSBufferReadableStream, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata> {
// validate create operation before starting
if (isFile) {
......@@ -256,7 +258,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
}
// file operation participant
await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE);
await this.runFileOperationParticipants([{ target: resource }], FileOperation.CREATE, options?.undoRedoGroupId, options?.isUndoing);
// before events
const event = { correlationId: this.correlationIds++, operation: FileOperation.CREATE, files: [{ target: resource }] };
......@@ -284,15 +286,15 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
return stat;
}
async move(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata[]> {
async move(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata[]> {
return this.doMoveOrCopy(files, true, options);
}
async copy(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata[]> {
async copy(files: Required<SourceTargetPair>[], options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata[]> {
return this.doMoveOrCopy(files, false, options);
}
private async doMoveOrCopy(files: Required<SourceTargetPair>[], move: boolean, options?: { overwrite?: boolean }): Promise<IFileStatWithMetadata[]> {
private async doMoveOrCopy(files: Required<SourceTargetPair>[], move: boolean, options?: { overwrite?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<IFileStatWithMetadata[]> {
const overwrite = options?.overwrite;
const stats: IFileStatWithMetadata[] = [];
......@@ -305,7 +307,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
}
// file operation participant
await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY);
await this.runFileOperationParticipants(files, move ? FileOperation.MOVE : FileOperation.COPY, options?.undoRedoGroupId, options?.isUndoing);
// before event
const event = { correlationId: this.correlationIds++, operation: move ? FileOperation.MOVE : FileOperation.COPY, files };
......@@ -344,7 +346,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
return stats;
}
async delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean }): Promise<void> {
async delete(resources: URI[], options?: { useTrash?: boolean, recursive?: boolean, undoRedoGroupId?: number, isUndoing?: boolean }): Promise<void> {
// validate delete operation before starting
for (const resource of resources) {
......@@ -356,7 +358,7 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
// file operation participant
const files = resources.map(target => ({ target }));
await this.runFileOperationParticipants(files, FileOperation.DELETE);
await this.runFileOperationParticipants(files, FileOperation.DELETE, options?.undoRedoGroupId, options?.isUndoing);
// before events
const event = { correlationId: this.correlationIds++, operation: FileOperation.DELETE, files };
......@@ -398,8 +400,8 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
return this.fileOperationParticipants.addFileOperationParticipant(participant);
}
private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation): Promise<void> {
return this.fileOperationParticipants.participate(files, operation);
private runFileOperationParticipants(files: SourceTargetPair[], operation: FileOperation, undoRedoGroupId: number | undefined, isUndoing: boolean | undefined): Promise<void> {
return this.fileOperationParticipants.participate(files, operation, undoRedoGroupId, isUndoing);
}
//#endregion
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册