diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index 24e6f4bc58c..89a1dfb1fe3 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -6,7 +6,7 @@ import * as nls from 'vs/nls'; import { Action } from 'vs/base/common/actions'; import { mixin } from 'vs/base/common/objects'; -import { IEditorInput, EditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection } from 'vs/workbench/common/editor'; +import { IEditorInput, EditorInput, IEditorIdentifier, IEditorCommandsContext, CloseDirection, SaveReason } from 'vs/workbench/common/editor'; import { QuickOpenEntryGroup } from 'vs/base/parts/quickopen/browser/quickOpenModel'; import { EditorQuickOpenEntry, EditorQuickOpenEntryGroup, IEditorQuickOpenEntry, QuickOpenAction } from 'vs/workbench/browser/quickopen'; import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen'; @@ -649,7 +649,7 @@ export abstract class BaseCloseAllAction extends Action { await this.editorService.revertAll({ soft: true }); saveOrRevert = true; } else { - saveOrRevert = await this.editorService.saveAll({ includeUntitled: true }); + saveOrRevert = await this.editorService.saveAll({ reason: SaveReason.EXPLICIT, includeUntitled: true }); } if (saveOrRevert) { diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index dc5ce544297..0b0fcb36fc7 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -6,7 +6,7 @@ import 'vs/css!./media/editorgroupview'; import { EditorGroup, IEditorOpenOptions, EditorCloseEvent, ISerializedEditorGroup, isSerializedEditorGroup } from 'vs/workbench/common/editor/editorGroup'; -import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor, EditorGroupEditorsCountContext, toResource, SideBySideEditor } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, EditorGroupActiveEditorDirtyContext, IEditor, EditorGroupEditorsCountContext, toResource, SideBySideEditor, SaveReason } from 'vs/workbench/common/editor'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { addClass, addClasses, Dimension, trackFocus, toggleClass, removeClass, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom'; @@ -1310,7 +1310,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Otherwise, handle accordingly switch (res) { case ConfirmResult.SAVE: - const result = await editor.save(this._group.id); + const result = await editor.save(this._group.id, { reason: SaveReason.EXPLICIT }); return !result; case ConfirmResult.DONT_SAVE: diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index f85d5c0cfde..36e0da44c73 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -437,38 +437,20 @@ export abstract class EditorInput extends Disposable implements IEditorInput { private disposed: boolean = false; - /** - * Returns the unique type identifier of this input. - */ abstract getTypeId(): string; - /** - * Returns the associated resource of this input if any. - */ getResource(): URI | undefined { return undefined; } - /** - * Returns the name of this input that can be shown to the user. Examples include showing the name of the input - * above the editor area when the input is shown. - */ getName(): string { return `Editor ${this.getTypeId()}`; } - /** - * Returns the description of this input that can be shown to the user. Examples include showing the description of - * the input above the editor area to the side of the name of the input. - */ getDescription(verbosity?: Verbosity): string | undefined { return undefined; } - /** - * Returns the title of this input that can be shown to the user. Examples include showing the title of - * the input above the editor area as hover over the input label. - */ getTitle(verbosity?: Verbosity): string { return this.getName(); } @@ -482,10 +464,10 @@ export abstract class EditorInput extends Disposable implements IEditorInput { } /** - * Returns a descriptor suitable for telemetry events. - * - * Subclasses should extend if they can contribute. - */ + * Returns a descriptor suitable for telemetry events. + * + * Subclasses should extend if they can contribute. + */ getTelemetryDescriptor(): { [key: string]: unknown } { /* __GDPR__FRAGMENT__ "EditorTelemetryDescriptor" : { @@ -501,46 +483,26 @@ export abstract class EditorInput extends Disposable implements IEditorInput { */ abstract resolve(): Promise; - /** - * Returns if this input is readonly or not. - */ isReadonly(): boolean { - // Subclasses need to explicitly opt-in to being editable. - return !this.isDirty(); - } - - /** - * Returns if the input is an untitled editor or not. - */ - isUntitled(): boolean { - // Subclasses need to explicitly opt-in to being untitled. return false; } - /** - * An editor that is dirty will be asked to be saved once it closes. - */ + isUntitled(): boolean { + return false; + } + isDirty(): boolean { return false; } - /** - * Saves the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation. - */ save(groupId: GroupIdentifier, options?: ISaveOptions): Promise { return Promise.resolve(true); } - /** - * Saves the editor to a different location. - */ saveAs(groupId: GroupIdentifier, options?: ISaveOptions): Promise { return Promise.resolve(true); } - /** - * Reverts the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation. - */ revert(options?: IRevertOptions): Promise { return Promise.resolve(true); } @@ -552,24 +514,14 @@ export abstract class EditorInput extends Disposable implements IEditorInput { return true; } - /** - * Returns true if this input is identical to the otherInput. - */ matches(otherInput: unknown): boolean { return this === otherInput; } - /** - * Returns whether this input was disposed or not. - */ isDisposed(): boolean { return this.disposed; } - /** - * Called when an editor input is no longer needed. Allows to free up any resources taken by - * resolving the editor input. - */ dispose(): void { this.disposed = true; this._onDispose.fire(); diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index a3c9bae7a01..7b5b47e820b 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -5,7 +5,7 @@ import * as nls from 'vs/nls'; import { URI } from 'vs/base/common/uri'; -import { toResource, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier } from 'vs/workbench/common/editor'; +import { toResource, IEditorCommandsContext, SideBySideEditor, IEditorIdentifier, SaveReason } from 'vs/workbench/common/editor'; import { IWindowOpenable, IOpenWindowOptions, isWorkspaceToOpen, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -36,6 +36,7 @@ import { basename, joinPath, isEqual } from 'vs/base/common/resources'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { UNTITLED_WORKSPACE_NAME } from 'vs/platform/workspaces/common/workspaces'; +import { coalesce } from 'vs/base/common/arrays'; // Commands @@ -318,7 +319,7 @@ function saveSelectedEditors(accessor: ServicesAccessor, options?: ISaveEditorsO return doSaveEditors(accessor, saveableEditors, options); } -function saveEditorsOfGroups(accessor: ServicesAccessor, groups = accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), options?: ISaveEditorsOptions): Promise { +function saveEditorsOfGroups(accessor: ServicesAccessor, groups: ReadonlyArray, options?: ISaveEditorsOptions): Promise { const saveableEditors: IEditorIdentifier[] = []; for (const group of groups) { for (const editor of group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) { @@ -348,7 +349,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ primary: KeyMod.CtrlCmd | KeyCode.KEY_S, id: SAVE_FILE_COMMAND_ID, handler: accessor => { - return saveSelectedEditors(accessor, { force: true }); + return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true }); } }); @@ -359,7 +360,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ win: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S) }, id: SAVE_FILE_WITHOUT_FORMATTING_COMMAND_ID, handler: accessor => { - return saveSelectedEditors(accessor, { force: true, skipSaveParticipants: true }); + return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, force: true, skipSaveParticipants: true }); } }); @@ -369,14 +370,14 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ when: undefined, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S, handler: accessor => { - return saveSelectedEditors(accessor, { saveAs: true }); + return saveSelectedEditors(accessor, { reason: SaveReason.EXPLICIT, saveAs: true }); } }); CommandsRegistry.registerCommand({ id: SAVE_ALL_COMMAND_ID, handler: (accessor) => { - return saveEditorsOfGroups(accessor); + return saveEditorsOfGroups(accessor, accessor.get(IEditorGroupsService).getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE), { reason: SaveReason.EXPLICIT }); } }); @@ -387,23 +388,14 @@ CommandsRegistry.registerCommand({ const contexts = getMultiSelectedEditorContexts(editorContext, accessor.get(IListService), accessor.get(IEditorGroupsService)); - let groups: IEditorGroup[] | undefined = undefined; + let groups: ReadonlyArray | undefined = undefined; if (!contexts.length) { - groups = [...editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE)]; + groups = editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); } else { - contexts.forEach(context => { - const editorGroup = editorGroupService.getGroup(context.groupId); - if (editorGroup) { - if (!groups) { - groups = []; - } - - groups.push(editorGroup); - } - }); + groups = coalesce(contexts.map(context => editorGroupService.getGroup(context.groupId))); } - return saveEditorsOfGroups(accessor, groups); + return saveEditorsOfGroups(accessor, groups, { reason: SaveReason.EXPLICIT }); } }); @@ -412,7 +404,7 @@ CommandsRegistry.registerCommand({ handler: accessor => { const editorService = accessor.get(IEditorService); - return editorService.saveAll({ includeUntitled: false }); + return editorService.saveAll({ includeUntitled: false, reason: SaveReason.EXPLICIT }); } }); diff --git a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts index 5e123f78eaa..24482931109 100644 --- a/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/simpleFileDialog.ts @@ -34,6 +34,7 @@ import { CancellationToken } from 'vs/base/common/cancellation'; import { ICommandHandler } from 'vs/platform/commands/common/commands'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { normalizeDriveLetter } from 'vs/base/common/labels'; +import { SaveReason } from 'vs/workbench/common/editor'; export namespace OpenLocalFileCommand { export const ID = 'workbench.action.files.openLocalFile'; @@ -54,7 +55,7 @@ export namespace SaveLocalFileCommand { const editorService = accessor.get(IEditorService); const activeControl = editorService.activeControl; if (activeControl) { - return editorService.save({ groupId: activeControl.group.id, editor: activeControl.input }, { saveAs: true, availableFileSystems: [Schemas.file] }); + return editorService.save({ groupId: activeControl.group.id, editor: activeControl.input }, { saveAs: true, availableFileSystems: [Schemas.file], reason: SaveReason.EXPLICIT }); } return Promise.resolve(undefined);