Skip to content

Commit 72c2f50

Browse files
committed
working copy - introduce first save/revert semantics (#84672)
1 parent 261ef3e commit 72c2f50

22 files changed

+169
-88
lines changed

src/vs/workbench/api/browser/mainThreadSaveParticipant.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import { ILogService } from 'vs/platform/log/common/log';
3030
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
3131
import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers';
3232
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
33-
import { ISaveParticipant, SaveReason, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
33+
import { ISaveParticipant, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
34+
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
3435
import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../common/extHost.protocol';
3536

3637
export interface ICodeActionsOnSaveOptions {

src/vs/workbench/api/common/extHost.protocol.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import { ITerminalDimensions, IShellLaunchConfig } from 'vs/workbench/contrib/te
4545
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
4646
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
4747
import * as search from 'vs/workbench/services/search/common/search';
48-
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
48+
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
4949
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
5050

5151
export interface IEnvironment {

src/vs/workbench/api/common/extHostDocumentSaveParticipant.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IResou
1111
import { TextEdit } from 'vs/workbench/api/common/extHostTypes';
1212
import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters';
1313
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
14-
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
14+
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
1515
import * as vscode from 'vscode';
1616
import { LinkedList } from 'vs/base/common/linkedList';
1717
import { ILogService } from 'vs/platform/log/common/log';

src/vs/workbench/api/common/extHostTypeConverters.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { EndOfLineSequence, TrackedRangeStickiness } from 'vs/editor/common/mode
1313
import * as vscode from 'vscode';
1414
import { URI, UriComponents } from 'vs/base/common/uri';
1515
import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress';
16-
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
16+
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
1717
import { IPosition } from 'vs/editor/common/core/position';
1818
import * as editorRange from 'vs/editor/common/core/range';
1919
import { ISelection } from 'vs/editor/common/core/selection';
@@ -31,7 +31,6 @@ import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log';
3131
import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays';
3232
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
3333

34-
3534
export interface PositionLike {
3635
line: number;
3736
character: number;

src/vs/workbench/browser/parts/editor/textEditor.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
1616
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1717
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
1818
import { IThemeService } from 'vs/platform/theme/common/themeService';
19-
import { ITextFileService, SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
19+
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
20+
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
2021
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
2122
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
2223
import { isDiffEditor, isCodeEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser';

src/vs/workbench/common/editor.ts

+12-19
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { ActionRunner, IAction } from 'vs/base/common/actions';
2020
import { IFileService } from 'vs/platform/files/common/files';
2121
import { IPathData } from 'vs/platform/windows/common/windows';
2222
import { coalesce, firstOrDefault } from 'vs/base/common/arrays';
23+
import { ISaveOptions, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
2324

2425
export const ActiveEditorContext = new RawContextKey<string | null>('activeEditor', null);
2526
export const ActiveEditorIsSaveableContext = new RawContextKey<boolean>('activeEditorIsSaveable', false);
@@ -261,25 +262,12 @@ export const enum Verbosity {
261262
LONG
262263
}
263264

264-
export interface IRevertOptions {
265-
266-
/**
267-
* Forces to load the contents of the editor again even if the editor is not dirty.
268-
*/
269-
force?: boolean;
270-
271-
/**
272-
* A soft revert will clear dirty state of an editor but will not attempt to load it.
273-
*/
274-
soft?: boolean;
275-
}
276-
277265
export interface IEditorInput extends IDisposable {
278266

279267
/**
280268
* Triggered when this input is disposed.
281269
*/
282-
onDispose: Event<void>;
270+
readonly onDispose: Event<void>;
283271

284272
/**
285273
* Returns the associated resource of this input.
@@ -316,6 +304,11 @@ export interface IEditorInput extends IDisposable {
316304
*/
317305
isDirty(): boolean;
318306

307+
/**
308+
* Saves the editor if it is dirty.
309+
*/
310+
save(options?: ISaveOptions): Promise<boolean>;
311+
319312
/**
320313
* Reverts this input.
321314
*/
@@ -418,7 +411,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
418411
/**
419412
* Saves the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation.
420413
*/
421-
save(): Promise<boolean> {
414+
save(options?: ISaveOptions): Promise<boolean> {
422415
return Promise.resolve(true);
423416
}
424417

@@ -553,12 +546,12 @@ export class SideBySideEditorInput extends EditorInput {
553546
return this.master.isDirty();
554547
}
555548

556-
save(): Promise<boolean> {
557-
return this.master.save();
549+
save(options?: ISaveOptions): Promise<boolean> {
550+
return this.master.save(options);
558551
}
559552

560-
revert(): Promise<boolean> {
561-
return this.master.revert();
553+
revert(options?: IRevertOptions): Promise<boolean> {
554+
return this.master.revert(options);
562555
}
563556

564557
getTelemetryDescriptor(): { [key: string]: unknown } {

src/vs/workbench/common/editor/untitledTextEditorInput.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { Event, Emitter } from 'vs/base/common/event';
1515
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
1616
import { ILabelService } from 'vs/platform/label/common/label';
1717
import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
18+
import { ISaveOptions, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
1819

1920
/**
2021
* An editor input to be used for untitled text buffers.
@@ -146,11 +147,11 @@ export class UntitledTextEditorInput extends EditorInput implements IEncodingSup
146147
return false;
147148
}
148149

149-
save(): Promise<boolean> {
150-
return this.textFileService.save(this.resource);
150+
save(options?: ISaveOptions): Promise<boolean> {
151+
return this.textFileService.save(this.resource, options);
151152
}
152153

153-
revert(): Promise<boolean> {
154+
revert(options?: IRevertOptions): Promise<boolean> {
154155
if (this.cachedModel) {
155156
this.cachedModel.revert();
156157
}

src/vs/workbench/common/editor/untitledTextEditorModel.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ import { ITextResourceConfigurationService } from 'vs/editor/common/services/res
1616
import { ITextBufferFactory } from 'vs/editor/common/model';
1717
import { createTextBufferFactory } from 'vs/editor/common/model/textModel';
1818
import { IResolvedTextEditorModel } from 'vs/editor/common/services/resolverService';
19-
import { IWorkingCopyService, IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService';
19+
import { IWorkingCopyService, IWorkingCopy, ISaveOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
20+
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
2021

2122
export class UntitledTextEditorModel extends BaseTextEditorModel implements IEncodingSupport, IWorkingCopy {
2223

@@ -48,7 +49,8 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IEnc
4849
@IModelService modelService: IModelService,
4950
@IBackupFileService private readonly backupFileService: IBackupFileService,
5051
@ITextResourceConfigurationService private readonly configurationService: ITextResourceConfigurationService,
51-
@IWorkingCopyService private readonly workingCopyService: IWorkingCopyService
52+
@IWorkingCopyService private readonly workingCopyService: IWorkingCopyService,
53+
@ITextFileService private readonly textFileService: ITextFileService
5254
) {
5355
super(modelService, modeService);
5456

@@ -115,11 +117,17 @@ export class UntitledTextEditorModel extends BaseTextEditorModel implements IEnc
115117
this._onDidChangeDirty.fire();
116118
}
117119

118-
revert(): void {
120+
save(options?: ISaveOptions): Promise<boolean> {
121+
return this.textFileService.save(this.resource, options);
122+
}
123+
124+
async revert(): Promise<boolean> {
119125
this.setDirty(false);
120126

121127
// Handle content change event buffered
122128
this.contentChangeEventScheduler.schedule();
129+
130+
return true;
123131
}
124132

125133
backup(): Promise<void> {

src/vs/workbench/contrib/customEditor/browser/customEditorModel.ts

+12-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { Emitter, Event } from 'vs/base/common/event';
77
import { Disposable } from 'vs/base/common/lifecycle';
88
import { URI } from 'vs/base/common/uri';
9-
import { IWorkingCopy, IWorkingCopyService, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService';
9+
import { IWorkingCopy, IWorkingCopyService, WorkingCopyCapabilities, ISaveOptions, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
1010

1111
type Edit = string;
1212

@@ -56,9 +56,19 @@ export class CustomEditorModel extends Disposable implements IWorkingCopy {
5656
this._onDidChangeDirty.fire();
5757
}
5858

59-
public save() {
59+
public async save(options?: ISaveOptions) {
6060
this._savePoint = this._edits.length;
6161
this.updateDirty();
62+
63+
return true;
64+
}
65+
66+
public async revert(options?: IRevertOptions) {
67+
while (this._currentEditIndex > 0) {
68+
this.undo();
69+
}
70+
71+
return true;
6272
}
6373

6474
public undo() {

src/vs/workbench/contrib/files/browser/fileCommands.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
1414
import { ExplorerFocusCondition, TextFileContentProvider, VIEWLET_ID, IExplorerService } from 'vs/workbench/contrib/files/common/files';
1515
import { ExplorerViewlet } from 'vs/workbench/contrib/files/browser/explorerViewlet';
1616
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
17-
import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
17+
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
18+
import { ISaveOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
1819
import { toErrorMessage } from 'vs/base/common/errorMessage';
1920
import { IListService } from 'vs/platform/list/browser/listService';
2021
import { CommandsRegistry } from 'vs/platform/commands/common/commands';

src/vs/workbench/contrib/files/common/editors/fileEditorInput.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import { localize } from 'vs/nls';
77
import { createMemoizer } from 'vs/base/common/decorators';
88
import { dirname } from 'vs/base/common/resources';
99
import { URI } from 'vs/base/common/uri';
10-
import { EncodingMode, EditorInput, IFileEditorInput, ITextEditorModel, Verbosity, IRevertOptions } from 'vs/workbench/common/editor';
10+
import { EncodingMode, EditorInput, IFileEditorInput, ITextEditorModel, Verbosity } from 'vs/workbench/common/editor';
11+
import { IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
1112
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
1213
import { BinaryEditorModel } from 'vs/workbench/common/editor/binaryEditorModel';
1314
import { FileOperationError, FileOperationResult, IFileService } from 'vs/platform/files/common/files';
14-
import { ITextFileService, ModelState, TextFileModelChangeEvent, LoadReason, TextFileOperationError, TextFileOperationResult } from 'vs/workbench/services/textfile/common/textfiles';
15+
import { ITextFileService, ModelState, TextFileModelChangeEvent, LoadReason, TextFileOperationError, TextFileOperationResult, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
1516
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1617
import { IReference } from 'vs/base/common/lifecycle';
1718
import { ITextModelService } from 'vs/editor/common/services/resolverService';
@@ -243,8 +244,8 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
243244
return model.isDirty();
244245
}
245246

246-
save(): Promise<boolean> {
247-
return this.textFileService.save(this.resource);
247+
save(options?: ITextFileSaveOptions): Promise<boolean> {
248+
return this.textFileService.save(this.resource, options);
248249
}
249250

250251
revert(options?: IRevertOptions): Promise<boolean> {

src/vs/workbench/contrib/testCustomEditors/browser/testCustomEditors.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import * as nls from 'vs/nls';
77
import { Action } from 'vs/base/common/actions';
88
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
9-
import { IEditorInputFactory, EditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, EditorModel, IRevertOptions, EditorOptions } from 'vs/workbench/common/editor';
9+
import { IEditorInputFactory, EditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, EditorModel, EditorOptions } from 'vs/workbench/common/editor';
1010
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
1111
import { IEditorModel } from 'vs/platform/editor/common/editor';
1212
import { Dimension, addDisposableListener, EventType } from 'vs/base/browser/dom';
@@ -24,7 +24,7 @@ import { isEqual } from 'vs/base/common/resources';
2424
import { generateUuid } from 'vs/base/common/uuid';
2525
import { CancellationToken } from 'vs/base/common/cancellation';
2626
import { editorBackground, editorForeground } from 'vs/platform/theme/common/colorRegistry';
27-
import { IWorkingCopy, IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
27+
import { IWorkingCopy, IWorkingCopyService, IRevertOptions, ISaveOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
2828
import { env } from 'vs/base/common/process';
2929

3030
const CUSTOM_SCHEME = 'testCustomEditor';
@@ -160,16 +160,16 @@ class TestCustomEditorInput extends EditorInput implements IWorkingCopy {
160160
return this.dirty;
161161
}
162162

163-
save(): Promise<boolean> {
163+
async save(options?: ISaveOptions): Promise<boolean> {
164164
this.setDirty(false);
165165

166-
return Promise.resolve(true);
166+
return true;
167167
}
168168

169-
revert(options?: IRevertOptions): Promise<boolean> {
169+
async revert(options?: IRevertOptions): Promise<boolean> {
170170
this.setDirty(false);
171171

172-
return Promise.resolve(true);
172+
return true;
173173
}
174174

175175
async resolve(): Promise<IEditorModel | null> {

src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
3232
import { createCancelablePromise, CancelablePromise } from 'vs/base/common/async';
3333
import { CancellationToken } from 'vs/base/common/cancellation';
3434
import { ICommandHandler } from 'vs/platform/commands/common/commands';
35-
import { ITextFileService, ISaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
35+
import { ITextFileService, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles';
3636
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
3737
import { toResource } from 'vs/workbench/common/editor';
3838
import { normalizeDriveLetter } from 'vs/base/common/labels';
@@ -56,7 +56,7 @@ export namespace SaveLocalFileCommand {
5656
const textFileService = accessor.get(ITextFileService);
5757
const editorService = accessor.get(IEditorService);
5858
let resource: URI | undefined = toResource(editorService.activeEditor);
59-
const options: ISaveOptions = { force: true, availableFileSystems: [Schemas.file] };
59+
const options: ITextFileSaveOptions = { force: true, availableFileSystems: [Schemas.file] };
6060
if (resource) {
6161
return textFileService.saveAs(resource, undefined, options);
6262
}

0 commit comments

Comments
 (0)