提交 72c2f506 编写于 作者: B Benjamin Pasero

working copy - introduce first save/revert semantics (#84672)

上级 261ef3e7
...@@ -30,7 +30,8 @@ import { ILogService } from 'vs/platform/log/common/log'; ...@@ -30,7 +30,8 @@ import { ILogService } from 'vs/platform/log/common/log';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress'; import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { ISaveParticipant, SaveReason, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { ISaveParticipant, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../common/extHost.protocol'; import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../common/extHost.protocol';
export interface ICodeActionsOnSaveOptions { export interface ICodeActionsOnSaveOptions {
......
...@@ -45,7 +45,7 @@ import { ITerminalDimensions, IShellLaunchConfig } from 'vs/workbench/contrib/te ...@@ -45,7 +45,7 @@ import { ITerminalDimensions, IShellLaunchConfig } from 'vs/workbench/contrib/te
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions'; import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier'; import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import * as search from 'vs/workbench/services/search/common/search'; import * as search from 'vs/workbench/services/search/common/search';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator'; import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
export interface IEnvironment { export interface IEnvironment {
......
...@@ -11,7 +11,7 @@ import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IResou ...@@ -11,7 +11,7 @@ import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IResou
import { TextEdit } from 'vs/workbench/api/common/extHostTypes'; import { TextEdit } from 'vs/workbench/api/common/extHostTypes';
import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters'; import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments'; import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { LinkedList } from 'vs/base/common/linkedList'; import { LinkedList } from 'vs/base/common/linkedList';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
......
...@@ -13,7 +13,7 @@ import { EndOfLineSequence, TrackedRangeStickiness } from 'vs/editor/common/mode ...@@ -13,7 +13,7 @@ import { EndOfLineSequence, TrackedRangeStickiness } from 'vs/editor/common/mode
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { URI, UriComponents } from 'vs/base/common/uri'; import { URI, UriComponents } from 'vs/base/common/uri';
import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress'; import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { IPosition } from 'vs/editor/common/core/position'; import { IPosition } from 'vs/editor/common/core/position';
import * as editorRange from 'vs/editor/common/core/range'; import * as editorRange from 'vs/editor/common/core/range';
import { ISelection } from 'vs/editor/common/core/selection'; import { ISelection } from 'vs/editor/common/core/selection';
...@@ -31,7 +31,6 @@ import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log'; ...@@ -31,7 +31,6 @@ import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log';
import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays'; import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays';
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions'; import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
export interface PositionLike { export interface PositionLike {
line: number; line: number;
character: number; character: number;
......
...@@ -16,7 +16,8 @@ import { IStorageService } from 'vs/platform/storage/common/storage'; ...@@ -16,7 +16,8 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService'; import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ITextFileService, SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { isDiffEditor, isCodeEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser'; import { isDiffEditor, isCodeEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser';
......
...@@ -20,6 +20,7 @@ import { ActionRunner, IAction } from 'vs/base/common/actions'; ...@@ -20,6 +20,7 @@ import { ActionRunner, IAction } from 'vs/base/common/actions';
import { IFileService } from 'vs/platform/files/common/files'; import { IFileService } from 'vs/platform/files/common/files';
import { IPathData } from 'vs/platform/windows/common/windows'; import { IPathData } from 'vs/platform/windows/common/windows';
import { coalesce, firstOrDefault } from 'vs/base/common/arrays'; import { coalesce, firstOrDefault } from 'vs/base/common/arrays';
import { ISaveOptions, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
export const ActiveEditorContext = new RawContextKey<string | null>('activeEditor', null); export const ActiveEditorContext = new RawContextKey<string | null>('activeEditor', null);
export const ActiveEditorIsSaveableContext = new RawContextKey<boolean>('activeEditorIsSaveable', false); export const ActiveEditorIsSaveableContext = new RawContextKey<boolean>('activeEditorIsSaveable', false);
...@@ -261,25 +262,12 @@ export const enum Verbosity { ...@@ -261,25 +262,12 @@ export const enum Verbosity {
LONG LONG
} }
export interface IRevertOptions {
/**
* Forces to load the contents of the editor again even if the editor is not dirty.
*/
force?: boolean;
/**
* A soft revert will clear dirty state of an editor but will not attempt to load it.
*/
soft?: boolean;
}
export interface IEditorInput extends IDisposable { export interface IEditorInput extends IDisposable {
/** /**
* Triggered when this input is disposed. * Triggered when this input is disposed.
*/ */
onDispose: Event<void>; readonly onDispose: Event<void>;
/** /**
* Returns the associated resource of this input. * Returns the associated resource of this input.
...@@ -316,6 +304,11 @@ export interface IEditorInput extends IDisposable { ...@@ -316,6 +304,11 @@ export interface IEditorInput extends IDisposable {
*/ */
isDirty(): boolean; isDirty(): boolean;
/**
* Saves the editor if it is dirty.
*/
save(options?: ISaveOptions): Promise<boolean>;
/** /**
* Reverts this input. * Reverts this input.
*/ */
...@@ -418,7 +411,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput { ...@@ -418,7 +411,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
/** /**
* Saves the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation. * Saves the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation.
*/ */
save(): Promise<boolean> { save(options?: ISaveOptions): Promise<boolean> {
return Promise.resolve(true); return Promise.resolve(true);
} }
...@@ -553,12 +546,12 @@ export class SideBySideEditorInput extends EditorInput { ...@@ -553,12 +546,12 @@ export class SideBySideEditorInput extends EditorInput {
return this.master.isDirty(); return this.master.isDirty();
} }
save(): Promise<boolean> { save(options?: ISaveOptions): Promise<boolean> {
return this.master.save(); return this.master.save(options);
} }
revert(): Promise<boolean> { revert(options?: IRevertOptions): Promise<boolean> {
return this.master.revert(); return this.master.revert(options);
} }
getTelemetryDescriptor(): { [key: string]: unknown } { getTelemetryDescriptor(): { [key: string]: unknown } {
......
...@@ -15,6 +15,7 @@ import { Event, Emitter } from 'vs/base/common/event'; ...@@ -15,6 +15,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ILabelService } from 'vs/platform/label/common/label'; import { ILabelService } from 'vs/platform/label/common/label';
import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
import { ISaveOptions, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
/** /**
* An editor input to be used for untitled text buffers. * An editor input to be used for untitled text buffers.
...@@ -146,11 +147,11 @@ export class UntitledTextEditorInput extends EditorInput implements IEncodingSup ...@@ -146,11 +147,11 @@ export class UntitledTextEditorInput extends EditorInput implements IEncodingSup
return false; return false;
} }
save(): Promise<boolean> { save(options?: ISaveOptions): Promise<boolean> {
return this.textFileService.save(this.resource); return this.textFileService.save(this.resource, options);
} }
revert(): Promise<boolean> { revert(options?: IRevertOptions): Promise<boolean> {
if (this.cachedModel) { if (this.cachedModel) {
this.cachedModel.revert(); this.cachedModel.revert();
} }
......
...@@ -16,7 +16,8 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res ...@@ -16,7 +16,8 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
import { ITextBufferFactory } from 'vs/editor/common/model'; import { ITextBufferFactory } from 'vs/editor/common/model';
import { createTextBufferFactory } from 'vs/editor/common/model/textModel'; import { createTextBufferFactory } from 'vs/editor/common/model/textModel';
import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService'; import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
import { IWorkingCopyService, IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkingCopyService, IWorkingCopy, ISaveOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
export class UntitledTextEditorModel extends BaseTextEditorModel implements IEncodingSupport, IWorkingCopy { export class UntitledTextEditorModel extends BaseTextEditorModel implements IEncodingSupport, IWorkingCopy {
...@@ -48,7 +49,8 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IEnc ...@@ -48,7 +49,8 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IEnc
@IModelService modelService: IModelService, @IModelService modelService: IModelService,
@IBackupFileService private readonly backupFileService: IBackupFileService, @IBackupFileService private readonly backupFileService: IBackupFileService,
@ITextResourceConfigurationService private readonly configurationService: ITextResourceConfigurationService, @ITextResourceConfigurationService private readonly configurationService: ITextResourceConfigurationService,
@IWorkingCopyService private readonly workingCopyService: IWorkingCopyService @IWorkingCopyService private readonly workingCopyService: IWorkingCopyService,
@ITextFileService private readonly textFileService: ITextFileService
) { ) {
super(modelService, modeService); super(modelService, modeService);
...@@ -115,11 +117,17 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IEnc ...@@ -115,11 +117,17 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IEnc
this._onDidChangeDirty.fire(); this._onDidChangeDirty.fire();
} }
revert(): void { save(options?: ISaveOptions): Promise<boolean> {
return this.textFileService.save(this.resource, options);
}
async revert(): Promise<boolean> {
this.setDirty(false); this.setDirty(false);
// Handle content change event buffered // Handle content change event buffered
this.contentChangeEventScheduler.schedule(); this.contentChangeEventScheduler.schedule();
return true;
} }
backup(): Promise<void> { backup(): Promise<void> {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { IWorkingCopy, IWorkingCopyService, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkingCopy, IWorkingCopyService, WorkingCopyCapabilities, ISaveOptions, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
type Edit = string; type Edit = string;
...@@ -56,9 +56,19 @@ export class CustomEditorModel extends Disposable implements IWorkingCopy { ...@@ -56,9 +56,19 @@ export class CustomEditorModel extends Disposable implements IWorkingCopy {
this._onDidChangeDirty.fire(); this._onDidChangeDirty.fire();
} }
public save() { public async save(options?: ISaveOptions) {
this._savePoint = this._edits.length; this._savePoint = this._edits.length;
this.updateDirty(); this.updateDirty();
return true;
}
public async revert(options?: IRevertOptions) {
while (this._currentEditIndex > 0) {
this.undo();
}
return true;
} }
public undo() { public undo() {
......
...@@ -14,7 +14,8 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace ...@@ -14,7 +14,8 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { ExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, IExplorerService } from 'vs/workbench/contrib/files/common/files'; import { ExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, IExplorerService } from 'vs/workbench/contrib/files/common/files';
import { ExplorerViewlet } from 'vs/workbench/contrib/files/browser/explorerViewlet'; import { ExplorerViewlet } from 'vs/workbench/contrib/files/browser/explorerViewlet';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ISaveOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { toErrorMessage } from 'vs/base/common/errorMessage'; import { toErrorMessage } from 'vs/base/common/errorMessage';
import { IListService } from 'vs/platform/list/browser/listService'; import { IListService } from 'vs/platform/list/browser/listService';
import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { CommandsRegistry } from 'vs/platform/commands/common/commands';
......
...@@ -7,11 +7,12 @@ import { localize } from 'vs/nls'; ...@@ -7,11 +7,12 @@ import { localize } from 'vs/nls';
import { createMemoizer } from 'vs/base/common/decorators'; import { createMemoizer } from 'vs/base/common/decorators';
import { dirname } from 'vs/base/common/resources'; import { dirname } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { EncodingMode, EditorInput, IFileEditorInput, ITextEditorModel, Verbosity, IRevertOptions } from 'vs/workbench/common/editor'; import { EncodingMode, EditorInput, IFileEditorInput, ITextEditorModel, Verbosity } from 'vs/workbench/common/editor';
import { IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel'; import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files'; import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files';
import { ITextFileService, ModelState, TextFileModelChangeEvent, LoadReason, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, ModelState, TextFileModelChangeEvent, LoadReason, TextFileOperationError, TextFileOperationResult, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IReference } from 'vs/base/common/lifecycle'; import { IReference } from 'vs/base/common/lifecycle';
import { ITextModelService } from 'vs/editor/common/services/resolverService'; import { ITextModelService } from 'vs/editor/common/services/resolverService';
...@@ -243,8 +244,8 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput { ...@@ -243,8 +244,8 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
return model.isDirty(); return model.isDirty();
} }
save(): Promise<boolean> { save(options?: ITextFileSaveOptions): Promise<boolean> {
return this.textFileService.save(this.resource); return this.textFileService.save(this.resource, options);
} }
revert(options?: IRevertOptions): Promise<boolean> { revert(options?: IRevertOptions): Promise<boolean> {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions'; import { Action } from 'vs/base/common/actions';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IEditorInputFactory, EditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, EditorModel, IRevertOptions, EditorOptions } from 'vs/workbench/common/editor'; import { IEditorInputFactory, EditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, EditorModel, EditorOptions } from 'vs/workbench/common/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorModel } from 'vs/platform/editor/common/editor'; import { IEditorModel } from 'vs/platform/editor/common/editor';
import { Dimension, addDisposableListener, EventType } from 'vs/base/browser/dom'; import { Dimension, addDisposableListener, EventType } from 'vs/base/browser/dom';
...@@ -24,7 +24,7 @@ import { isEqual } from 'vs/base/common/resources'; ...@@ -24,7 +24,7 @@ import { isEqual } from 'vs/base/common/resources';
import { generateUuid } from 'vs/base/common/uuid'; import { generateUuid } from 'vs/base/common/uuid';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { editorBackground, editorForeground } from 'vs/platform/theme/common/colorRegistry'; import { editorBackground, editorForeground } from 'vs/platform/theme/common/colorRegistry';
import { IWorkingCopy, IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkingCopy, IWorkingCopyService, IRevertOptions, ISaveOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { env } from 'vs/base/common/process'; import { env } from 'vs/base/common/process';
const CUSTOM_SCHEME = 'testCustomEditor'; const CUSTOM_SCHEME = 'testCustomEditor';
...@@ -160,16 +160,16 @@ class TestCustomEditorInput extends EditorInput implements IWorkingCopy { ...@@ -160,16 +160,16 @@ class TestCustomEditorInput extends EditorInput implements IWorkingCopy {
return this.dirty; return this.dirty;
} }
save(): Promise<boolean> { async save(options?: ISaveOptions): Promise<boolean> {
this.setDirty(false); this.setDirty(false);
return Promise.resolve(true); return true;
} }
revert(options?: IRevertOptions): Promise<boolean> { async revert(options?: IRevertOptions): Promise<boolean> {
this.setDirty(false); this.setDirty(false);
return Promise.resolve(true); return true;
} }
async resolve(): Promise<IEditorModel | null> { async resolve(): Promise<IEditorModel | null> {
......
...@@ -32,7 +32,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; ...@@ -32,7 +32,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { createCancelablePromise, CancelablePromise } from 'vs/base/common/async'; import { createCancelablePromise, CancelablePromise } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { ICommandHandler } from 'vs/platform/commands/common/commands'; import { ICommandHandler } from 'vs/platform/commands/common/commands';
import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { toResource } from 'vs/workbench/common/editor'; import { toResource } from 'vs/workbench/common/editor';
import { normalizeDriveLetter } from 'vs/base/common/labels'; import { normalizeDriveLetter } from 'vs/base/common/labels';
...@@ -56,7 +56,7 @@ export namespace SaveLocalFileCommand { ...@@ -56,7 +56,7 @@ export namespace SaveLocalFileCommand {
const textFileService = accessor.get(ITextFileService); const textFileService = accessor.get(ITextFileService);
const editorService = accessor.get(IEditorService); const editorService = accessor.get(IEditorService);
let resource: URI | undefined = toResource(editorService.activeEditor); let resource: URI | undefined = toResource(editorService.activeEditor);
const options: ISaveOptions = { force: true, availableFileSystems: [Schemas.file] }; const options: ITextFileSaveOptions = { force: true, availableFileSystems: [Schemas.file] };
if (resource) { if (resource) {
return textFileService.saveAs(resource, undefined, options); return textFileService.saveAs(resource, undefined, options);
} }
......
...@@ -8,8 +8,8 @@ import { URI } from 'vs/base/common/uri'; ...@@ -8,8 +8,8 @@ import { URI } from 'vs/base/common/uri';
import { Emitter, AsyncEmitter } from 'vs/base/common/event'; import { Emitter, AsyncEmitter } from 'vs/base/common/event';
import * as platform from 'vs/base/common/platform'; import * as platform from 'vs/base/common/platform';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
import { IResult, ITextFileOperationResult, ITextFileService, ITextFileStreamContent, SaveReason, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ISaveOptions, ITextFileContent, IResourceEncodings, IReadTextFileOptions, IWriteTextFileOptions, toBufferOrReadable, TextFileOperationError, TextFileOperationResult, FileOperationWillRunEvent, FileOperationDidRunEvent } from 'vs/workbench/services/textfile/common/textfiles'; import { IResult, ITextFileOperationResult, ITextFileService, ITextFileStreamContent, ITextFileEditorModelManager, ITextFileEditorModel, ModelState, ITextFileContent, IResourceEncodings, IReadTextFileOptions, IWriteTextFileOptions, toBufferOrReadable, TextFileOperationError, TextFileOperationResult, FileOperationWillRunEvent, FileOperationDidRunEvent, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { IRevertOptions } from 'vs/workbench/common/editor'; import { SaveReason, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { ILifecycleService, ShutdownReason, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { ILifecycleService, ShutdownReason, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IFileService, FileOperationError, FileOperationResult, HotExitConfiguration, IFileStatWithMetadata, ICreateFileOptions, FileOperation } from 'vs/platform/files/common/files'; import { IFileService, FileOperationError, FileOperationResult, HotExitConfiguration, IFileStatWithMetadata, ICreateFileOptions, FileOperation } from 'vs/platform/files/common/files';
...@@ -477,7 +477,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex ...@@ -477,7 +477,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
//#region save/revert //#region save/revert
async save(resource: URI, options?: ISaveOptions): Promise<boolean> { async save(resource: URI, options?: ITextFileSaveOptions): Promise<boolean> {
// Run a forced save if we detect the file is not dirty so that save participants can still run // Run a forced save if we detect the file is not dirty so that save participants can still run
if (options?.force && this.fileService.canHandleResource(resource) && !this.isDirty(resource)) { if (options?.force && this.fileService.canHandleResource(resource) && !this.isDirty(resource)) {
...@@ -496,9 +496,9 @@ export abstract class AbstractTextFileService extends Disposable implements ITex ...@@ -496,9 +496,9 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return result.results.length === 1 && !!result.results[0].success; return result.results.length === 1 && !!result.results[0].success;
} }
saveAll(includeUntitled?: boolean, options?: ISaveOptions): Promise<ITextFileOperationResult>; saveAll(includeUntitled?: boolean, options?: ITextFileSaveOptions): Promise<ITextFileOperationResult>;
saveAll(resources: URI[], options?: ISaveOptions): Promise<ITextFileOperationResult>; saveAll(resources: URI[], options?: ITextFileSaveOptions): Promise<ITextFileOperationResult>;
saveAll(arg1?: boolean | URI[], options?: ISaveOptions): Promise<ITextFileOperationResult> { saveAll(arg1?: boolean | URI[], options?: ITextFileSaveOptions): Promise<ITextFileOperationResult> {
// get all dirty // get all dirty
let toSave: URI[] = []; let toSave: URI[] = [];
...@@ -522,7 +522,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex ...@@ -522,7 +522,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return this.doSaveAll(filesToSave, untitledToSave, options); return this.doSaveAll(filesToSave, untitledToSave, options);
} }
private async doSaveAll(fileResources: URI[], untitledResources: URI[], options?: ISaveOptions): Promise<ITextFileOperationResult> { private async doSaveAll(fileResources: URI[], untitledResources: URI[], options?: ITextFileSaveOptions): Promise<ITextFileOperationResult> {
// Handle files first that can just be saved // Handle files first that can just be saved
const result = await this.doSaveAllFiles(fileResources, options); const result = await this.doSaveAllFiles(fileResources, options);
...@@ -627,7 +627,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex ...@@ -627,7 +627,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return options; return options;
} }
private async doSaveAllFiles(resources?: URI[], options: ISaveOptions = Object.create(null)): Promise<ITextFileOperationResult> { private async doSaveAllFiles(resources?: URI[], options: ITextFileSaveOptions = Object.create(null)): Promise<ITextFileOperationResult> {
const dirtyFileModels = this.getDirtyFileModels(Array.isArray(resources) ? resources : undefined /* Save All */) const dirtyFileModels = this.getDirtyFileModels(Array.isArray(resources) ? resources : undefined /* Save All */)
.filter(model => { .filter(model => {
if ((model.hasState(ModelState.CONFLICT) || model.hasState(ModelState.ERROR)) && (options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE)) { if ((model.hasState(ModelState.CONFLICT) || model.hasState(ModelState.ERROR)) && (options.reason === SaveReason.AUTO || options.reason === SaveReason.FOCUS_CHANGE || options.reason === SaveReason.WINDOW_CHANGE)) {
...@@ -675,7 +675,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex ...@@ -675,7 +675,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return this.getFileModels(resources).filter(model => model.isDirty()); return this.getFileModels(resources).filter(model => model.isDirty());
} }
async saveAs(resource: URI, targetResource?: URI, options?: ISaveOptions): Promise<URI | undefined> { async saveAs(resource: URI, targetResource?: URI, options?: ITextFileSaveOptions): Promise<URI | undefined> {
// Get to target resource // Get to target resource
if (!targetResource) { if (!targetResource) {
...@@ -702,7 +702,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex ...@@ -702,7 +702,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return this.doSaveAs(resource, targetResource, options); return this.doSaveAs(resource, targetResource, options);
} }
private async doSaveAs(resource: URI, target: URI, options?: ISaveOptions): Promise<URI> { private async doSaveAs(resource: URI, target: URI, options?: ITextFileSaveOptions): Promise<URI> {
// Retrieve text model from provided resource if any // Retrieve text model from provided resource if any
let model: ITextFileEditorModel | UntitledTextEditorModel | undefined; let model: ITextFileEditorModel | UntitledTextEditorModel | undefined;
...@@ -736,7 +736,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex ...@@ -736,7 +736,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
return target; return target;
} }
private async doSaveTextFileAs(sourceModel: ITextFileEditorModel | UntitledTextEditorModel, resource: URI, target: URI, options?: ISaveOptions): Promise<boolean> { private async doSaveTextFileAs(sourceModel: ITextFileEditorModel | UntitledTextEditorModel, resource: URI, target: URI, options?: ITextFileSaveOptions): Promise<boolean> {
// Prefer an existing model if it is already loaded for the given target resource // Prefer an existing model if it is already loaded for the given target resource
let targetExists: boolean = false; let targetExists: boolean = false;
...@@ -866,7 +866,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex ...@@ -866,7 +866,7 @@ export abstract class AbstractTextFileService extends Disposable implements ITex
await Promise.all(fileModels.map(async model => { await Promise.all(fileModels.map(async model => {
try { try {
await model.revert(options?.soft); await model.revert(options);
if (!model.isDirty()) { if (!model.isDirty()) {
const result = mapResourceToResult.get(model.resource); const result = mapResourceToResult.get(model.resource);
......
...@@ -11,7 +11,7 @@ import { URI } from 'vs/base/common/uri'; ...@@ -11,7 +11,7 @@ import { URI } from 'vs/base/common/uri';
import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types'; import { isUndefinedOrNull, assertIsDefined } from 'vs/base/common/types';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ITextFileService, ModelState, ITextFileEditorModel, ISaveOptions, ISaveErrorHandler, ISaveParticipant, StateChange, SaveReason, ITextFileStreamContent, ILoadOptions, LoadReason, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, ModelState, ITextFileEditorModel, ISaveErrorHandler, ISaveParticipant, StateChange, ITextFileStreamContent, ILoadOptions, LoadReason, IResolvedTextFileEditorModel, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { EncodingMode } from 'vs/workbench/common/editor'; import { EncodingMode } from 'vs/workbench/common/editor';
import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel'; import { BaseTextEditorModel } from 'vs/workbench/common/editor/textEditorModel';
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup'; import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
...@@ -29,7 +29,7 @@ import { ILogService } from 'vs/platform/log/common/log'; ...@@ -29,7 +29,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { isEqual, isEqualOrParent, extname, basename, joinPath } from 'vs/base/common/resources'; import { isEqual, isEqualOrParent, extname, basename, joinPath } from 'vs/base/common/resources';
import { onUnexpectedError } from 'vs/base/common/errors'; import { onUnexpectedError } from 'vs/base/common/errors';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { IWorkingCopyService, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkingCopyService, WorkingCopyCapabilities, SaveReason, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { IFilesConfigurationService, IAutoSaveConfiguration } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; import { IFilesConfigurationService, IAutoSaveConfiguration } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
export interface IBackupMetaData { export interface IBackupMetaData {
...@@ -252,9 +252,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -252,9 +252,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
return this.backupFileService.hasBackupSync(this.resource, this.versionId); return this.backupFileService.hasBackupSync(this.resource, this.versionId);
} }
async revert(soft?: boolean): Promise<void> { async revert(options?: IRevertOptions): Promise<boolean> {
if (!this.isResolved()) { if (!this.isResolved()) {
return; return false;
} }
// Cancel any running auto-save // Cancel any running auto-save
...@@ -265,7 +265,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -265,7 +265,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
const undo = this.setDirty(false); const undo = this.setDirty(false);
// Force read from disk unless reverting soft // Force read from disk unless reverting soft
if (!soft) { const softUndo = options?.soft;
if (!softUndo) {
try { try {
await this.load({ forceReadFromDisk: true }); await this.load({ forceReadFromDisk: true });
} catch (error) { } catch (error) {
...@@ -284,6 +285,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -284,6 +285,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
if (wasDirty) { if (wasDirty) {
this._onDidChangeDirty.fire(); this._onDidChangeDirty.fire();
} }
return true;
} }
async load(options?: ILoadOptions): Promise<ITextFileEditorModel> { async load(options?: ILoadOptions): Promise<ITextFileEditorModel> {
...@@ -612,9 +615,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -612,9 +615,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
this.autoSaveDisposable.value = toDisposable(() => clearTimeout(handle)); this.autoSaveDisposable.value = toDisposable(() => clearTimeout(handle));
} }
async save(options: ISaveOptions = Object.create(null)): Promise<void> { async save(options: ITextFileSaveOptions = Object.create(null)): Promise<boolean> {
if (!this.isResolved()) { if (!this.isResolved()) {
return; return false;
} }
this.logService.trace('save() - enter', this.resource); this.logService.trace('save() - enter', this.resource);
...@@ -622,10 +625,12 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil ...@@ -622,10 +625,12 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Cancel any currently running auto saves to make this the one that succeeds // Cancel any currently running auto saves to make this the one that succeeds
this.autoSaveDisposable.clear(); this.autoSaveDisposable.clear();
return this.doSave(this.versionId, options); await this.doSave(this.versionId, options);
return true;
} }
private doSave(versionId: number, options: ISaveOptions): Promise<void> { private doSave(versionId: number, options: ITextFileSaveOptions): Promise<void> {
if (isUndefinedOrNull(options.reason)) { if (isUndefinedOrNull(options.reason)) {
options.reason = SaveReason.EXPLICIT; options.reason = SaveReason.EXPLICIT;
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { Event, IWaitUntil } from 'vs/base/common/event'; import { Event, IWaitUntil } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle'; import { IDisposable } from 'vs/base/common/lifecycle';
import { IEncodingSupport, IRevertOptions, IModeSupport } from 'vs/workbench/common/editor'; import { IEncodingSupport, IModeSupport } from 'vs/workbench/common/editor';
import { IBaseStatWithMetadata, IFileStatWithMetadata, IReadFileOptions, IWriteFileOptions, FileOperationError, FileOperationResult, FileOperation } from 'vs/platform/files/common/files'; import { IBaseStatWithMetadata, IFileStatWithMetadata, IReadFileOptions, IWriteFileOptions, FileOperationError, FileOperationResult, FileOperation } from 'vs/platform/files/common/files';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ITextEditorModel } from 'vs/editor/common/services/resolverService'; import { ITextEditorModel } from 'vs/editor/common/services/resolverService';
...@@ -14,7 +14,7 @@ import { ITextBufferFactory, ITextModel, ITextSnapshot } from 'vs/editor/common/ ...@@ -14,7 +14,7 @@ import { ITextBufferFactory, ITextModel, ITextSnapshot } from 'vs/editor/common/
import { VSBuffer, VSBufferReadable } from 'vs/base/common/buffer'; import { VSBuffer, VSBufferReadable } from 'vs/base/common/buffer';
import { isUndefinedOrNull } from 'vs/base/common/types'; import { isUndefinedOrNull } from 'vs/base/common/types';
import { isNative } from 'vs/base/common/platform'; import { isNative } from 'vs/base/common/platform';
import { IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkingCopy, ISaveOptions, SaveReason, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
export const ITextFileService = createDecorator<ITextFileService>('textFileService'); export const ITextFileService = createDecorator<ITextFileService>('textFileService');
...@@ -323,13 +323,6 @@ export interface IResult { ...@@ -323,13 +323,6 @@ export interface IResult {
success?: boolean; success?: boolean;
} }
export const enum SaveReason {
EXPLICIT = 1,
AUTO = 2,
FOCUS_CHANGE = 3,
WINDOW_CHANGE = 4
}
export const enum LoadReason { export const enum LoadReason {
EDITOR = 1, EDITOR = 1,
REFERENCE = 2, REFERENCE = 2,
...@@ -421,12 +414,9 @@ export interface ITextFileEditorModelManager { ...@@ -421,12 +414,9 @@ export interface ITextFileEditorModelManager {
disposeModel(model: ITextFileEditorModel): void; disposeModel(model: ITextFileEditorModel): void;
} }
export interface ISaveOptions { export interface ITextFileSaveOptions extends ISaveOptions {
force?: boolean;
reason?: SaveReason;
overwriteReadonly?: boolean; overwriteReadonly?: boolean;
overwriteEncoding?: boolean; overwriteEncoding?: boolean;
skipSaveParticipants?: boolean;
writeElevated?: boolean; writeElevated?: boolean;
availableFileSystems?: readonly string[]; availableFileSystems?: readonly string[];
} }
...@@ -458,11 +448,11 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport ...@@ -458,11 +448,11 @@ export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport
updatePreferredEncoding(encoding: string | undefined): void; updatePreferredEncoding(encoding: string | undefined): void;
save(options?: ISaveOptions): Promise<void>; save(options?: ITextFileSaveOptions): Promise<boolean>;
load(options?: ILoadOptions): Promise<ITextFileEditorModel>; load(options?: ILoadOptions): Promise<ITextFileEditorModel>;
revert(soft?: boolean): Promise<void>; revert(options?: IRevertOptions): Promise<boolean>;
backup(target?: URI): Promise<void>; backup(target?: URI): Promise<void>;
......
...@@ -263,7 +263,7 @@ suite('Files - TextFileEditorModel', () => { ...@@ -263,7 +263,7 @@ suite('Files - TextFileEditorModel', () => {
assert.equal(accessor.workingCopyService.dirtyCount, 1); assert.equal(accessor.workingCopyService.dirtyCount, 1);
assert.equal(accessor.workingCopyService.isDirty(model.resource), true); assert.equal(accessor.workingCopyService.isDirty(model.resource), true);
await model.revert(true /* soft revert */); await model.revert({ soft: true });
assert.ok(!model.isDirty()); assert.ok(!model.isDirty());
assert.equal(model.textEditorModel!.getValue(), 'foo'); assert.equal(model.textEditorModel!.getValue(), 'foo');
assert.equal(eventCounter, 1); assert.equal(eventCounter, 1);
...@@ -300,7 +300,7 @@ suite('Files - TextFileEditorModel', () => { ...@@ -300,7 +300,7 @@ suite('Files - TextFileEditorModel', () => {
model.textEditorModel!.setValue('foo'); model.textEditorModel!.setValue('foo');
assert.ok(model.isDirty()); assert.ok(model.isDirty());
await model.revert(true /* soft revert */); await model.revert({ soft: true });
assert.ok(!model.isDirty()); assert.ok(!model.isDirty());
model.onDidStateChange(e => { model.onDidStateChange(e => {
......
...@@ -286,7 +286,7 @@ suite('Files - TextFileEditorModelManager', () => { ...@@ -286,7 +286,7 @@ suite('Files - TextFileEditorModelManager', () => {
model.textEditorModel!.setValue('make dirty'); model.textEditorModel!.setValue('make dirty');
manager.disposeModel((model as TextFileEditorModel)); manager.disposeModel((model as TextFileEditorModel));
assert.ok(!model.isDisposed()); assert.ok(!model.isDisposed());
model.revert(true); model.revert({ soft: true });
manager.disposeModel((model as TextFileEditorModel)); manager.disposeModel((model as TextFileEditorModel));
assert.ok(model.isDisposed()); assert.ok(model.isDisposed());
manager.dispose(); manager.dispose();
......
...@@ -19,6 +19,63 @@ export const enum WorkingCopyCapabilities { ...@@ -19,6 +19,63 @@ export const enum WorkingCopyCapabilities {
AutoSave = 1 << 1 AutoSave = 1 << 1
} }
export const enum SaveReason {
/**
* Explicit user gesture.
*/
EXPLICIT = 1,
/**
* Auto save after a timeout.
*/
AUTO = 2,
/**
* Auto save after editor focus change.
*/
FOCUS_CHANGE = 3,
/**
* Auto save after window change.
*/
WINDOW_CHANGE = 4
}
export interface ISaveOptions {
/**
* An indicator how the save operation was triggered.
*/
reason?: SaveReason;
/**
* Forces to load the contents of the working copy
* again even if the working copy is not dirty.
*/
force?: boolean;
/**
* Instructs the save operation to skip any save participants.
*/
skipSaveParticipants?: boolean;
}
export interface IRevertOptions {
/**
* Forces to load the contents of the working copy
* again even if the working copy is not dirty.
*/
force?: boolean;
/**
* A soft revert will clear dirty state of a working copy
* but will not attempt to load it from its persisted state.
*/
soft?: boolean;
}
export interface IWorkingCopy { export interface IWorkingCopy {
//#region Dirty Tracking //#region Dirty Tracking
...@@ -29,6 +86,16 @@ export interface IWorkingCopy { ...@@ -29,6 +86,16 @@ export interface IWorkingCopy {
//#endregion //#endregion
//#region Save/Revert
save(options?: ISaveOptions): Promise<boolean>;
revert(options?: IRevertOptions): Promise<boolean>;
//#endregion
readonly resource: URI; readonly resource: URI;
readonly capabilities: WorkingCopyCapabilities; readonly capabilities: WorkingCopyCapabilities;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as assert from 'assert'; import * as assert from 'assert';
import { IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IWorkingCopy, ISaveOptions, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { Emitter } from 'vs/base/common/event'; import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
...@@ -41,6 +41,9 @@ suite('WorkingCopyService', () => { ...@@ -41,6 +41,9 @@ suite('WorkingCopyService', () => {
return this.dirty; return this.dirty;
} }
async save(options?: ISaveOptions): Promise<boolean> { return true; }
async revert(options?: IRevertOptions): Promise<boolean> { return true; }
dispose(): void { dispose(): void {
this._onDispose.fire(); this._onDispose.fire();
......
...@@ -10,7 +10,7 @@ import { TextDocumentSaveReason, TextEdit, Position, EndOfLine } from 'vs/workbe ...@@ -10,7 +10,7 @@ import { TextDocumentSaveReason, TextEdit, Position, EndOfLine } from 'vs/workbe
import { MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol'; import { MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/common/extHostDocumentSaveParticipant'; import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/common/extHostDocumentSaveParticipant';
import { SingleProxyRPCProtocol } from './testRPCProtocol'; import { SingleProxyRPCProtocol } from './testRPCProtocol';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { mock } from 'vs/workbench/test/electron-browser/api/mock'; import { mock } from 'vs/workbench/test/electron-browser/api/mock';
import { NullLogService } from 'vs/platform/log/common/log'; import { NullLogService } from 'vs/platform/log/common/log';
......
...@@ -13,7 +13,8 @@ import { IModelService } from 'vs/editor/common/services/modelService'; ...@@ -13,7 +13,8 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { Range } from 'vs/editor/common/core/range'; import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection'; import { Selection } from 'vs/editor/common/core/selection';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel'; import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { ITextFileService, SaveReason, IResolvedTextFileEditorModel, snapshotToString } from 'vs/workbench/services/textfile/common/textfiles'; import { ITextFileService, IResolvedTextFileEditorModel, snapshotToString } from 'vs/workbench/services/textfile/common/textfiles';
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager'; import { TextFileEditorModelManager } from 'vs/workbench/services/textfile/common/textFileEditorModelManager';
class ServiceAccessor { class ServiceAccessor {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册