Show progress indication when saving an editor takes long (fix #193230) (#214128)

This commit is contained in:
Benjamin Pasero 2024-06-03 12:56:51 +02:00 committed by GitHub
parent 7e451df2cf
commit b5bd304ac8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 106 additions and 93 deletions

View file

@ -33,6 +33,7 @@ import { IAccessibilityService } from 'vs/platform/accessibility/common/accessib
import { PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { IProgress, IProgressService, IProgressStep, ProgressLocation } from 'vs/platform/progress/common/progress';
interface IBackupMetaData extends IWorkingCopyBackupMeta {
mtime: number;
@ -123,7 +124,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
@ILanguageDetectionService languageDetectionService: ILanguageDetectionService,
@IAccessibilityService accessibilityService: IAccessibilityService,
@IPathService private readonly pathService: IPathService,
@IExtensionService private readonly extensionService: IExtensionService
@IExtensionService private readonly extensionService: IExtensionService,
@IProgressService private readonly progressService: IProgressService
) {
super(modelService, languageService, languageDetectionService, accessibilityService);
@ -756,7 +758,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
options.reason = SaveReason.EXPLICIT;
}
let versionId = this.versionId;
const versionId = this.versionId;
this.trace(`doSave(${versionId}) - enter with versionId ${versionId}`);
// Return early if saved from within save participant to break recursion
@ -818,6 +820,22 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
const saveCancellation = new CancellationTokenSource();
return this.progressService.withProgress({
title: localize('saveParticipants', "Saving '{0}'", this.name),
location: ProgressLocation.Window,
cancellable: true,
delay: this.isDirty() ? 3000 : 5000,
type: 'loading'
}, progress => {
return this.doSaveSequential(versionId, options, progress, saveCancellation);
}, () => {
saveCancellation.cancel();
}).finally(() => {
saveCancellation.dispose();
});
}
private doSaveSequential(versionId: number, options: ITextFileSaveAsOptions, progress: IProgress<IProgressStep>, saveCancellation: CancellationTokenSource): Promise<void> {
return this.saveSequentializer.run(versionId, (async () => {
// A save participant can still change the model now and since we are so close to saving
@ -852,7 +870,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
if (!saveCancellation.token.isCancellationRequested) {
this.ignoreSaveFromSaveParticipants = true;
try {
await this.textFileService.files.runSaveParticipants(this, { reason: options.reason ?? SaveReason.EXPLICIT, savedFrom: options.from }, saveCancellation.token);
await this.textFileService.files.runSaveParticipants(this, { reason: options.reason ?? SaveReason.EXPLICIT, savedFrom: options.from }, progress, saveCancellation.token);
} finally {
this.ignoreSaveFromSaveParticipants = false;
}
@ -898,6 +916,7 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Save to Disk. We mark the save operation as currently running with
// the latest versionId because it might have changed from a save
// participant triggering
progress.report({ message: localize('saveTextFile', "Writing into file...") });
this.trace(`doSave(${versionId}) - before write()`);
const lastResolvedFileStat = assertIsDefined(this.lastResolvedFileStat);
const resolvedTextFileEditorModel = this;

View file

@ -24,6 +24,7 @@ import { extname, joinPath } from 'vs/base/common/resources';
import { createTextBufferFactoryFromSnapshot } from 'vs/editor/common/model/textModel';
import { PLAINTEXT_EXTENSION, PLAINTEXT_LANGUAGE_ID } from 'vs/editor/common/languages/modesRegistry';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress';
export class TextFileEditorModelManager extends Disposable implements ITextFileEditorModelManager {
@ -540,8 +541,8 @@ export class TextFileEditorModelManager extends Disposable implements ITextFileE
return this.saveParticipants.addSaveParticipant(participant);
}
runSaveParticipants(model: ITextFileEditorModel, context: IStoredFileWorkingCopySaveParticipantContext, token: CancellationToken): Promise<void> {
return this.saveParticipants.participate(model, context, token);
runSaveParticipants(model: ITextFileEditorModel, context: IStoredFileWorkingCopySaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> {
return this.saveParticipants.participate(model, context, progress, token);
}
//#endregion

View file

@ -3,11 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { raceCancellation } from 'vs/base/common/async';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ILogService } from 'vs/platform/log/common/log';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress';
import { ITextFileSaveParticipant, ITextFileEditorModel, ITextFileSaveParticipantContext } from 'vs/workbench/services/textfile/common/textfiles';
import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { insert } from 'vs/base/common/arrays';
@ -17,7 +16,6 @@ export class TextFileSaveParticipant extends Disposable {
private readonly saveParticipants: ITextFileSaveParticipant[] = [];
constructor(
@IProgressService private readonly progressService: IProgressService,
@ILogService private readonly logService: ILogService
) {
super();
@ -29,40 +27,26 @@ export class TextFileSaveParticipant extends Disposable {
return toDisposable(() => remove());
}
participate(model: ITextFileEditorModel, context: ITextFileSaveParticipantContext, token: CancellationToken): Promise<void> {
const cts = new CancellationTokenSource(token);
async participate(model: ITextFileEditorModel, context: ITextFileSaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> {
return this.progressService.withProgress({
title: localize('saveParticipants', "Saving '{0}'", model.name),
location: ProgressLocation.Notification,
cancellable: true,
delay: model.isDirty() ? 3000 : 5000
}, async progress => {
// undoStop before participation
model.textEditorModel?.pushStackElement();
// undoStop before participation
model.textEditorModel?.pushStackElement();
for (const saveParticipant of this.saveParticipants) {
if (cts.token.isCancellationRequested || !model.textEditorModel /* disposed */) {
break;
}
try {
const promise = saveParticipant.participate(model, context, progress, cts.token);
await raceCancellation(promise, cts.token);
} catch (err) {
this.logService.error(err);
}
for (const saveParticipant of this.saveParticipants) {
if (token.isCancellationRequested || !model.textEditorModel /* disposed */) {
break;
}
// undoStop after participation
model.textEditorModel?.pushStackElement();
}, () => {
// user cancel
cts.cancel();
}).finally(() => {
cts.dispose();
});
try {
const promise = saveParticipant.participate(model, context, progress, token);
await raceCancellation(promise, token);
} catch (err) {
this.logService.error(err);
}
}
// undoStop after participation
model.textEditorModel?.pushStackElement();
}
override dispose(): void {

View file

@ -385,7 +385,7 @@ export interface ITextFileEditorModelManager {
/**
* Runs the registered save participants on the provided model.
*/
runSaveParticipants(model: ITextFileEditorModel, context: ITextFileSaveParticipantContext, token: CancellationToken): Promise<void>;
runSaveParticipants(model: ITextFileEditorModel, context: ITextFileSaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void>;
/**
* Waits for the model to be ready to be disposed. There may be conditions

View file

@ -38,6 +38,7 @@ import { Schemas } from 'vs/base/common/network';
import { IDecorationData, IDecorationsProvider, IDecorationsService } from 'vs/workbench/services/decorations/common/decorations';
import { Codicon } from 'vs/base/common/codicons';
import { listErrorForeground } from 'vs/platform/theme/common/colorRegistry';
import { IProgressService } from 'vs/platform/progress/common/progress';
export interface IFileWorkingCopyManager<S extends IStoredFileWorkingCopyModel, U extends IUntitledFileWorkingCopyModel> extends IBaseFileWorkingCopyManager<S | U, IFileWorkingCopy<S | U>> {
@ -162,7 +163,8 @@ export class FileWorkingCopyManager<S extends IStoredFileWorkingCopyModel, U ext
@IPathService private readonly pathService: IPathService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IDialogService private readonly dialogService: IDialogService,
@IDecorationsService private readonly decorationsService: IDecorationsService
@IDecorationsService private readonly decorationsService: IDecorationsService,
@IProgressService progressService: IProgressService
) {
super();
@ -172,7 +174,7 @@ export class FileWorkingCopyManager<S extends IStoredFileWorkingCopyModel, U ext
this.storedWorkingCopyModelFactory,
fileService, lifecycleService, labelService, logService, workingCopyFileService,
workingCopyBackupService, uriIdentityService, filesConfigurationService, workingCopyService,
notificationService, workingCopyEditorService, editorService, elevatedFileService
notificationService, workingCopyEditorService, editorService, elevatedFileService, progressService
));
// Untitled file working copies manager

View file

@ -29,6 +29,7 @@ import { IElevatedFileService } from 'vs/workbench/services/files/common/elevate
import { IResourceWorkingCopy, ResourceWorkingCopy } from 'vs/workbench/services/workingCopy/common/resourceWorkingCopy';
import { IFileWorkingCopy, IFileWorkingCopyModel, IFileWorkingCopyModelFactory, SnapshotContext } from 'vs/workbench/services/workingCopy/common/fileWorkingCopy';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { IProgress, IProgressService, IProgressStep, ProgressLocation } from 'vs/platform/progress/common/progress';
/**
* Stored file specific working copy model factory.
@ -359,7 +360,8 @@ export class StoredFileWorkingCopy<M extends IStoredFileWorkingCopyModel> extend
@INotificationService private readonly notificationService: INotificationService,
@IWorkingCopyEditorService private readonly workingCopyEditorService: IWorkingCopyEditorService,
@IEditorService private readonly editorService: IEditorService,
@IElevatedFileService private readonly elevatedFileService: IElevatedFileService
@IElevatedFileService private readonly elevatedFileService: IElevatedFileService,
@IProgressService private readonly progressService: IProgressService
) {
super(resource, fileService);
@ -865,7 +867,7 @@ export class StoredFileWorkingCopy<M extends IStoredFileWorkingCopyModel> extend
options.reason = SaveReason.EXPLICIT;
}
let versionId = this.versionId;
const versionId = this.versionId;
this.trace(`doSave(${versionId}) - enter with versionId ${versionId}`);
// Return early if saved from within save participant to break recursion
@ -929,6 +931,22 @@ export class StoredFileWorkingCopy<M extends IStoredFileWorkingCopyModel> extend
const saveCancellation = new CancellationTokenSource();
return this.progressService.withProgress({
title: localize('saveParticipants', "Saving '{0}'", this.name),
location: ProgressLocation.Window,
cancellable: true,
delay: this.isDirty() ? 3000 : 5000,
type: 'loading'
}, progress => {
return this.doSaveSequential(versionId, options, progress, saveCancellation);
}, () => {
saveCancellation.cancel();
}).finally(() => {
saveCancellation.dispose();
});
}
private doSaveSequential(versionId: number, options: IStoredFileWorkingCopySaveAsOptions, progress: IProgress<IProgressStep>, saveCancellation: CancellationTokenSource): Promise<void> {
return this.saveSequentializer.run(versionId, (async () => {
// A save participant can still change the working copy now
@ -964,7 +982,7 @@ export class StoredFileWorkingCopy<M extends IStoredFileWorkingCopyModel> extend
if (!saveCancellation.token.isCancellationRequested) {
this.ignoreSaveFromSaveParticipants = true;
try {
await this.workingCopyFileService.runSaveParticipants(this, { reason: options.reason ?? SaveReason.EXPLICIT, savedFrom: options.from }, saveCancellation.token);
await this.workingCopyFileService.runSaveParticipants(this, { reason: options.reason ?? SaveReason.EXPLICIT, savedFrom: options.from }, progress, saveCancellation.token);
} finally {
this.ignoreSaveFromSaveParticipants = false;
}
@ -1004,6 +1022,7 @@ export class StoredFileWorkingCopy<M extends IStoredFileWorkingCopyModel> extend
// Save to Disk. We mark the save operation as currently running with
// the latest versionId because it might have changed from a save
// participant triggering
progress.report({ message: localize('saveTextFile', "Writing into file...") });
this.trace(`doSave(${versionId}) - before write()`);
const lastResolvedFileStat = assertIsDefined(this.lastResolvedFileStat);
const resolvedFileWorkingCopy = this;

View file

@ -30,6 +30,7 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo
import { isWeb } from 'vs/base/common/platform';
import { onUnexpectedError } from 'vs/base/common/errors';
import { SnapshotContext } from 'vs/workbench/services/workingCopy/common/fileWorkingCopy';
import { IProgressService } from 'vs/platform/progress/common/progress';
/**
* The only one that should be dealing with `IStoredFileWorkingCopy` and handle all
@ -186,7 +187,8 @@ export class StoredFileWorkingCopyManager<M extends IStoredFileWorkingCopyModel>
@INotificationService private readonly notificationService: INotificationService,
@IWorkingCopyEditorService private readonly workingCopyEditorService: IWorkingCopyEditorService,
@IEditorService private readonly editorService: IEditorService,
@IElevatedFileService private readonly elevatedFileService: IElevatedFileService
@IElevatedFileService private readonly elevatedFileService: IElevatedFileService,
@IProgressService private readonly progressService: IProgressService
) {
super(fileService, logService, workingCopyBackupService);
@ -532,7 +534,7 @@ export class StoredFileWorkingCopyManager<M extends IStoredFileWorkingCopyModel>
async options => { await this.resolve(resource, { ...options, reload: { async: false } }); },
this.fileService, this.logService, this.workingCopyFileService, this.filesConfigurationService,
this.workingCopyBackupService, this.workingCopyService, this.notificationService, this.workingCopyEditorService,
this.editorService, this.elevatedFileService
this.editorService, this.elevatedFileService, this.progressService
);
workingCopyResolve = workingCopy.resolve(resolveOptions);

View file

@ -3,11 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { raceCancellation } from 'vs/base/common/async';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ILogService } from 'vs/platform/log/common/log';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress';
import { IDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { insert } from 'vs/base/common/arrays';
import { IStoredFileWorkingCopySaveParticipant, IStoredFileWorkingCopySaveParticipantContext } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
@ -20,7 +19,6 @@ export class StoredFileWorkingCopySaveParticipant extends Disposable {
get length(): number { return this.saveParticipants.length; }
constructor(
@IProgressService private readonly progressService: IProgressService,
@ILogService private readonly logService: ILogService
) {
super();
@ -32,41 +30,26 @@ export class StoredFileWorkingCopySaveParticipant extends Disposable {
return toDisposable(() => remove());
}
participate(workingCopy: IStoredFileWorkingCopy<IStoredFileWorkingCopyModel>, context: IStoredFileWorkingCopySaveParticipantContext, token: CancellationToken): Promise<void> {
const cts = new CancellationTokenSource(token);
async participate(workingCopy: IStoredFileWorkingCopy<IStoredFileWorkingCopyModel>, context: IStoredFileWorkingCopySaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> {
return this.progressService.withProgress({
title: localize('saveParticipants', "Saving '{0}'", workingCopy.name),
location: ProgressLocation.Notification,
cancellable: true,
delay: workingCopy.isDirty() ? 3000 : 5000
}, async progress => {
// undoStop before participation
workingCopy.model?.pushStackElement();
// undoStop before participation
workingCopy.model?.pushStackElement();
for (const saveParticipant of this.saveParticipants) {
if (cts.token.isCancellationRequested || workingCopy.isDisposed()) {
break;
}
try {
const promise = saveParticipant.participate(workingCopy, context, progress, cts.token);
await raceCancellation(promise, cts.token);
} catch (err) {
this.logService.warn(err);
}
for (const saveParticipant of this.saveParticipants) {
if (token.isCancellationRequested || workingCopy.isDisposed()) {
break;
}
// undoStop after participation
workingCopy.model?.pushStackElement();
try {
const promise = saveParticipant.participate(workingCopy, context, progress, token);
await raceCancellation(promise, token);
} catch (err) {
this.logService.warn(err);
}
}
// Cleanup
cts.dispose();
}, () => {
// user cancel
cts.dispose(true);
});
// undoStop after participation
workingCopy.model?.pushStackElement();
}
override dispose(): void {

View file

@ -206,7 +206,7 @@ export interface IWorkingCopyFileService {
/**
* Runs all available save participants for stored file working copies.
*/
runSaveParticipants(workingCopy: IStoredFileWorkingCopy<IStoredFileWorkingCopyModel>, context: IStoredFileWorkingCopySaveParticipantContext, token: CancellationToken): Promise<void>;
runSaveParticipants(workingCopy: IStoredFileWorkingCopy<IStoredFileWorkingCopyModel>, context: IStoredFileWorkingCopySaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void>;
//#endregion
@ -507,8 +507,8 @@ export class WorkingCopyFileService extends Disposable implements IWorkingCopyFi
return this.saveParticipants.addSaveParticipant(participant);
}
runSaveParticipants(workingCopy: IStoredFileWorkingCopy<IStoredFileWorkingCopyModel>, context: IStoredFileWorkingCopySaveParticipantContext, token: CancellationToken): Promise<void> {
return this.saveParticipants.participate(workingCopy, context, token);
runSaveParticipants(workingCopy: IStoredFileWorkingCopy<IStoredFileWorkingCopyModel>, context: IStoredFileWorkingCopySaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> {
return this.saveParticipants.participate(workingCopy, context, progress, token);
}
//#endregion

View file

@ -40,7 +40,7 @@ suite('FileWorkingCopyManager', () => {
accessor.workingCopyFileService, accessor.workingCopyBackupService, accessor.uriIdentityService, accessor.fileDialogService,
accessor.filesConfigurationService, accessor.workingCopyService, accessor.notificationService,
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService, accessor.pathService,
accessor.environmentService, accessor.dialogService, accessor.decorationsService
accessor.environmentService, accessor.dialogService, accessor.decorationsService, accessor.progressService,
));
});

View file

@ -151,7 +151,7 @@ suite('StoredFileWorkingCopy (with custom save)', function () {
accessor = instantiationService.createInstance(TestServiceAccessor);
const resource = URI.file('test/resource');
workingCopy = disposables.add(new StoredFileWorkingCopy<TestStoredFileWorkingCopyModelWithCustomSave>('testStoredFileWorkingCopyType', resource, basename(resource), factory, options => workingCopy.resolve(options), accessor.fileService, accessor.logService, accessor.workingCopyFileService, accessor.filesConfigurationService, accessor.workingCopyBackupService, accessor.workingCopyService, accessor.notificationService, accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService));
workingCopy = disposables.add(new StoredFileWorkingCopy<TestStoredFileWorkingCopyModelWithCustomSave>('testStoredFileWorkingCopyType', resource, basename(resource), factory, options => workingCopy.resolve(options), accessor.fileService, accessor.logService, accessor.workingCopyFileService, accessor.filesConfigurationService, accessor.workingCopyBackupService, accessor.workingCopyService, accessor.notificationService, accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService, accessor.progressService));
});
teardown(() => {
@ -249,7 +249,7 @@ suite('StoredFileWorkingCopy', function () {
let workingCopy: StoredFileWorkingCopy<TestStoredFileWorkingCopyModel>;
function createWorkingCopy(uri: URI = resource) {
const workingCopy: StoredFileWorkingCopy<TestStoredFileWorkingCopyModel> = new StoredFileWorkingCopy<TestStoredFileWorkingCopyModel>('testStoredFileWorkingCopyType', uri, basename(uri), factory, options => workingCopy.resolve(options), accessor.fileService, accessor.logService, accessor.workingCopyFileService, accessor.filesConfigurationService, accessor.workingCopyBackupService, accessor.workingCopyService, accessor.notificationService, accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService);
const workingCopy: StoredFileWorkingCopy<TestStoredFileWorkingCopyModel> = new StoredFileWorkingCopy<TestStoredFileWorkingCopyModel>('testStoredFileWorkingCopyType', uri, basename(uri), factory, options => workingCopy.resolve(options), accessor.fileService, accessor.logService, accessor.workingCopyFileService, accessor.filesConfigurationService, accessor.workingCopyBackupService, accessor.workingCopyService, accessor.notificationService, accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService, accessor.progressService);
return workingCopy;
}

View file

@ -37,7 +37,8 @@ suite('StoredFileWorkingCopyManager', () => {
accessor.fileService, accessor.lifecycleService, accessor.labelService, accessor.logService,
accessor.workingCopyFileService, accessor.workingCopyBackupService, accessor.uriIdentityService,
accessor.filesConfigurationService, accessor.workingCopyService, accessor.notificationService,
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService,
accessor.progressService
));
});

View file

@ -39,7 +39,7 @@ suite('UntitledFileWorkingCopyManager', () => {
accessor.workingCopyFileService, accessor.workingCopyBackupService, accessor.uriIdentityService, accessor.fileDialogService,
accessor.filesConfigurationService, accessor.workingCopyService, accessor.notificationService,
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService, accessor.pathService,
accessor.environmentService, accessor.dialogService, accessor.decorationsService
accessor.environmentService, accessor.dialogService, accessor.decorationsService, accessor.progressService
));
});
@ -318,7 +318,7 @@ suite('UntitledFileWorkingCopyManager', () => {
accessor.workingCopyFileService, accessor.workingCopyBackupService, accessor.uriIdentityService, accessor.fileDialogService,
accessor.filesConfigurationService, accessor.workingCopyService, accessor.notificationService,
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService, accessor.pathService,
accessor.environmentService, accessor.dialogService, accessor.decorationsService
accessor.environmentService, accessor.dialogService, accessor.decorationsService, accessor.progressService
));
const untitled1OriginalType = disposables.add(await manager.untitled.resolve());
@ -340,7 +340,7 @@ suite('UntitledFileWorkingCopyManager', () => {
accessor.workingCopyFileService, accessor.workingCopyBackupService, accessor.uriIdentityService, accessor.fileDialogService,
accessor.filesConfigurationService, accessor.workingCopyService, accessor.notificationService,
accessor.workingCopyEditorService, accessor.editorService, accessor.elevatedFileService, accessor.pathService,
accessor.environmentService, accessor.dialogService, accessor.decorationsService
accessor.environmentService, accessor.dialogService, accessor.decorationsService, accessor.progressService
));
const result = disposables.add(await manager.untitled.resolve());

View file

@ -396,7 +396,8 @@ export class TestServiceAccessor {
@IInstantiationService public instantiationService: IInstantiationService,
@IElevatedFileService public elevatedFileService: IElevatedFileService,
@IWorkspaceTrustRequestService public workspaceTrustRequestService: TestWorkspaceTrustRequestService,
@IDecorationsService public decorationsService: IDecorationsService
@IDecorationsService public decorationsService: IDecorationsService,
@IProgressService public progressService: IProgressService,
) { }
}

View file

@ -30,6 +30,7 @@ import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { IAutoSaveConfiguration, IAutoSaveMode, IFilesConfigurationService } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
import { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService, IWorkspaceTrustRequestService, IWorkspaceTrustTransitionParticipant, IWorkspaceTrustUriInfo, WorkspaceTrustRequestOptions, WorkspaceTrustUriResponse } from 'vs/platform/workspace/common/workspaceTrust';
import { IMarker, IMarkerData, IMarkerService, IResourceMarker, MarkerStatistics } from 'vs/platform/markers/common/markers';
import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress';
export class TestLoggerService extends AbstractLoggerService {
constructor(logsHome?: URI) {
@ -253,7 +254,7 @@ export class TestWorkingCopyFileService implements IWorkingCopyFileService {
readonly hasSaveParticipants = false;
addSaveParticipant(participant: IStoredFileWorkingCopySaveParticipant): IDisposable { return Disposable.None; }
async runSaveParticipants(workingCopy: IWorkingCopy, context: IStoredFileWorkingCopySaveParticipantContext, token: CancellationToken): Promise<void> { }
async runSaveParticipants(workingCopy: IWorkingCopy, context: IStoredFileWorkingCopySaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> { }
async delete(operations: IDeleteOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<void> { }