diff --git a/src/vs/workbench/api/browser/mainThreadEditorTabs.ts b/src/vs/workbench/api/browser/mainThreadEditorTabs.ts index 1c2b5341cf3..4bf970b19bf 100644 --- a/src/vs/workbench/api/browser/mainThreadEditorTabs.ts +++ b/src/vs/workbench/api/browser/mainThreadEditorTabs.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { DisposableStore } from 'vs/base/common/lifecycle'; -import { ExtHostContext, IExtHostEditorTabsShape, MainContext, IEditorTabDto, IEditorTabGroupDto, TabKind, MainThreadEditorTabsShape } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostContext, IExtHostEditorTabsShape, MainContext, IEditorTabDto, IEditorTabGroupDto, TabKind, MainThreadEditorTabsShape, AnyInputDto, TabInputKind } from 'vs/workbench/api/common/extHost.protocol'; import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers'; import { EditorResourceAccessor, SideBySideEditor, GroupModelChangeKind } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; @@ -13,6 +13,9 @@ import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEdit import { columnToEditorGroup, EditorGroupColumn, editorGroupToColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; import { GroupDirection, IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IEditorsChangeEvent, IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { AbstractTextResourceEditorInput } from 'vs/workbench/common/editor/textResourceEditorInput'; +import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; +import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput'; interface TabInfo { @@ -64,8 +67,9 @@ export class MainThreadEditorTabs implements MainThreadEditorTabsShape { id: this._generateTabId(editor, group.id), viewColumn: editorGroupToColumn(this._editorGroupsService, group), label: editor.getName(), - resource: editor instanceof SideBySideEditorInput ? EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }) : EditorResourceAccessor.getCanonicalUri(editor), editorId, + input: this._editorInputToDto(editor), + resource: editor instanceof SideBySideEditorInput ? EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.PRIMARY }) : EditorResourceAccessor.getCanonicalUri(editor), kind: tabKind, additionalResourcesAndViewTypes: [], isPinned: group.isSticky(editorIndex), @@ -79,6 +83,52 @@ export class MainThreadEditorTabs implements MainThreadEditorTabsShape { return tab; } + private _editorInputToDto(editor: EditorInput): AnyInputDto { + + if (editor instanceof AbstractTextResourceEditorInput) { + return { + kind: TabInputKind.TextInput, + uri: editor.resource + }; + } + + if (editor instanceof NotebookEditorInput) { + return { + kind: TabInputKind.NotebookInput, + notebookType: editor.viewType, + uri: editor.resource + }; + } + + if (editor instanceof CustomEditorInput) { + return { + kind: TabInputKind.CustomEditorInput, + viewType: editor.viewType, + uri: editor.resource, + }; + } + + if (editor instanceof DiffEditorInput) { + if (editor.modified instanceof AbstractTextResourceEditorInput && editor.original instanceof AbstractTextResourceEditorInput) { + return { + kind: TabInputKind.TextDiffInput, + modified: editor.modified.resource, + original: editor.original.resource + }; + } + if (editor.modified instanceof NotebookEditorInput && editor.original instanceof NotebookEditorInput) { + return { + kind: TabInputKind.NotebookDiffInput, + notebookType: editor.original.viewType, + modified: editor.modified.resource, + original: editor.original.resource + }; + } + } + + return { kind: TabInputKind.UnknownInput }; + } + /** * Generates a unique id for a tab * @param editor The editor input diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index b73eee6eeb4..994bdb200fe 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1325,6 +1325,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I WorkspaceTrustState: extHostTypes.WorkspaceTrustState, LanguageStatusSeverity: extHostTypes.LanguageStatusSeverity, QuickPickItemKind: extHostTypes.QuickPickItemKind, + TextTabInput: extHostTypes.TextTabInput, + TextDiffTabInput: extHostTypes.TextDiffTabInput, }; }; } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 93713243bbb..2146249c816 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -609,6 +609,51 @@ export interface ExtHostEditorInsetsShape { //#region --- tabs model +export const enum TabInputKind { + UnknownInput, + TextInput, + TextDiffInput, + NotebookInput, + NotebookDiffInput, + CustomEditorInput +} + +export interface UnknownInputDto { + kind: TabInputKind.UnknownInput; +} + +export interface TextInputDto { + kind: TabInputKind.TextInput; + uri: UriComponents; +} + +export interface TextDiffInputDto { + kind: TabInputKind.TextDiffInput; + original: UriComponents; + modified: UriComponents; +} + +export interface NotebookInputDto { + kind: TabInputKind.NotebookInput; + notebookType: string; + uri: UriComponents; +} + +export interface NotebookDiffInputDto { + kind: TabInputKind.NotebookDiffInput; + notebookType: string; + original: UriComponents; + modified: UriComponents; +} + +export interface CustomInputDto { + kind: TabInputKind.CustomEditorInput; + viewType: string; + uri: UriComponents; +} + +export type AnyInputDto = UnknownInputDto | TextInputDto | TextDiffInputDto | NotebookInputDto | NotebookDiffInputDto | CustomInputDto; + export interface MainThreadEditorTabsShape extends IDisposable { // manage tabs: move, close, rearrange etc $moveTab(tabId: string, index: number, viewColumn: EditorGroupColumn): void; @@ -634,6 +679,7 @@ export interface IEditorTabDto { id: string; viewColumn: EditorGroupColumn; label: string; + input: AnyInputDto; resource?: UriComponents; editorId?: string; isActive: boolean; diff --git a/src/vs/workbench/api/common/extHostEditorTabs.ts b/src/vs/workbench/api/common/extHostEditorTabs.ts index ad3ab387f5d..045cdc90a97 100644 --- a/src/vs/workbench/api/common/extHostEditorTabs.ts +++ b/src/vs/workbench/api/common/extHostEditorTabs.ts @@ -5,11 +5,11 @@ import type * as vscode from 'vscode'; import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters'; -import { IEditorTabDto, IEditorTabGroupDto, IExtHostEditorTabsShape, MainContext, MainThreadEditorTabsShape } from 'vs/workbench/api/common/extHost.protocol'; +import { IEditorTabDto, IEditorTabGroupDto, IExtHostEditorTabsShape, MainContext, MainThreadEditorTabsShape, TabInputKind } from 'vs/workbench/api/common/extHost.protocol'; import { URI } from 'vs/base/common/uri'; import { Emitter } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { ViewColumn } from 'vs/workbench/api/common/extHostTypes'; +import { TextDiffTabInput, TextTabInput, ViewColumn } from 'vs/workbench/api/common/extHostTypes'; import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; export interface IExtHostEditorTabs extends IExtHostEditorTabsShape { @@ -19,17 +19,19 @@ export interface IExtHostEditorTabs extends IExtHostEditorTabsShape { export const IExtHostEditorTabs = createDecorator('IExtHostEditorTabs'); +type AnyTab = TextTabInput | TextDiffTabInput; class ExtHostEditorTab { private _apiObject: vscode.Tab | undefined; - private _dto: IEditorTabDto; - private _proxy: MainThreadEditorTabsShape; - private _activeTabIdGetter: () => string; + private _dto!: IEditorTabDto; + private _input: AnyTab | undefined; + private readonly _proxy: MainThreadEditorTabsShape; + private readonly _activeTabIdGetter: () => string; constructor(dto: IEditorTabDto, proxy: MainThreadEditorTabsShape, activeTabIdGetter: () => string) { - this._dto = dto; this._proxy = proxy; this._activeTabIdGetter = activeTabIdGetter; + this.acceptDtoUpdate(dto); } get apiObject(): vscode.Tab { @@ -44,6 +46,9 @@ class ExtHostEditorTab { get label() { return that._dto.label; }, + get input() { + return that._input; + }, get resource() { return URI.revive(that._dto.resource); }, @@ -80,8 +85,19 @@ class ExtHostEditorTab { acceptDtoUpdate(dto: IEditorTabDto) { this._dto = dto; + this._input = this._initInput(); } + private _initInput() { + switch (this._dto.input.kind) { + case TabInputKind.TextInput: + return new TextTabInput(URI.revive(this._dto.input.uri)); + case TabInputKind.TextDiffInput: + return new TextDiffTabInput(URI.revive(this._dto.input.original), URI.revive(this._dto.input.modified)); + // TODO@lramos15 support all the cases + } + return undefined; + } } class ExtHostEditorTabGroup { diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index d733424fce1..ca0f738e973 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -3595,3 +3595,13 @@ export class TypeHierarchyItem { this.selectionRange = selectionRange; } } + +// --- + +export class TextTabInput { + constructor(readonly uri: URI) { } +} + +export class TextDiffTabInput { + constructor(readonly original: URI, readonly modified: URI) { } +} diff --git a/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts b/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts index d7b0e5bb14e..b89d20dbd71 100644 --- a/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts +++ b/src/vs/workbench/api/test/browser/extHostEditorTabs.test.ts @@ -7,12 +7,28 @@ import type * as vscode from 'vscode'; import assert = require('assert'); import { URI } from 'vs/base/common/uri'; import { mock } from 'vs/base/test/common/mock'; -import { IEditorTabDto, MainThreadEditorTabsShape, TabKind } from 'vs/workbench/api/common/extHost.protocol'; +import { IEditorTabDto, MainThreadEditorTabsShape, TabInputKind, TabKind } from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostEditorTabs } from 'vs/workbench/api/common/extHostEditorTabs'; import { SingleProxyRPCProtocol } from 'vs/workbench/api/test/common/testRPCProtocol'; suite('ExtHostEditorTabs', function () { + const defaultTabDto: IEditorTabDto = { + id: 'uniquestring', + input: { kind: TabInputKind.UnknownInput }, + resource: URI.parse('file://abc/def.txt'), + isActive: true, + isDirty: true, + isPinned: true, + label: 'label1', + viewColumn: 0, + additionalResourcesAndViewTypes: [], + kind: TabKind.Singular + }; + + function createTabDto(dto?: Partial): IEditorTabDto { + return { ...defaultTabDto, ...dto }; + } test('empty', function () { @@ -34,7 +50,7 @@ suite('ExtHostEditorTabs', function () { }) ); - const tab: IEditorTabDto = { + const tab: IEditorTabDto = createTabDto({ id: 'uniquestring', isActive: true, isDirty: true, @@ -43,7 +59,7 @@ suite('ExtHostEditorTabs', function () { viewColumn: 0, additionalResourcesAndViewTypes: [], kind: TabKind.Singular - }; + }); extHostEditorTabs.$acceptEditorTabModel([{ isActive: true, @@ -122,7 +138,7 @@ suite('ExtHostEditorTabs', function () { // override/implement $moveTab or $closeTab }) ); - const tab: IEditorTabDto = { + const tab = createTabDto({ id: 'uniquestring', isActive: true, isDirty: true, @@ -133,7 +149,7 @@ suite('ExtHostEditorTabs', function () { viewColumn: 0, additionalResourcesAndViewTypes: [], kind: TabKind.Singular - }; + }); extHostEditorTabs.$acceptEditorTabModel([{ isActive: true, @@ -218,18 +234,7 @@ suite('ExtHostEditorTabs', function () { // override/implement $moveTab or $closeTab }) ); - const tabDto: IEditorTabDto = { - id: 'uniquestring', - isActive: true, - isDirty: true, - isPinned: true, - label: 'label1', - resource: URI.parse('file://abc/def.txt'), - editorId: 'default', - viewColumn: 0, - additionalResourcesAndViewTypes: [], - kind: TabKind.Singular - }; + const tabDto = createTabDto(); // single dirty tab @@ -268,7 +273,7 @@ suite('ExtHostEditorTabs', function () { // override/implement $moveTab or $closeTab }) ); - const tabDtoAAA: IEditorTabDto = { + const tabDtoAAA = createTabDto({ id: 'AAA', isActive: true, isDirty: true, @@ -279,9 +284,9 @@ suite('ExtHostEditorTabs', function () { viewColumn: 0, additionalResourcesAndViewTypes: [], kind: TabKind.Singular - }; + }); - const tabDtoBBB: IEditorTabDto = { + const tabDtoBBB = createTabDto({ id: 'BBB', isActive: false, isDirty: true, @@ -292,7 +297,7 @@ suite('ExtHostEditorTabs', function () { viewColumn: 0, additionalResourcesAndViewTypes: [], kind: TabKind.Singular - }; + }); // single dirty tab @@ -354,7 +359,7 @@ suite('ExtHostEditorTabs', function () { } }) ); - const tab: IEditorTabDto = { + const tab: IEditorTabDto = createTabDto({ id: 'uniquestring', isActive: true, isDirty: true, @@ -365,7 +370,7 @@ suite('ExtHostEditorTabs', function () { viewColumn: 0, additionalResourcesAndViewTypes: [], kind: TabKind.Singular - }; + }); extHostEditorTabs.$acceptEditorTabModel([{ isActive: true, diff --git a/src/vscode-dts/vscode.proposed.tabs.d.ts b/src/vscode-dts/vscode.proposed.tabs.d.ts index a57bd20d2ef..bdd5bbd1fd3 100644 --- a/src/vscode-dts/vscode.proposed.tabs.d.ts +++ b/src/vscode-dts/vscode.proposed.tabs.d.ts @@ -7,12 +7,26 @@ declare module 'vscode' { // https://github.com/Microsoft/vscode/issues/15178 + // TODO@API remove export enum TabKind { Singular = 0, Diff = 1, SidebySide = 2 } + // TODO@API names + export class TextTabInput { + readonly uri: Uri; + constructor(uri: Uri); + } + + // TODO@API names + export class TextDiffTabInput { + readonly original: Uri; + readonly modified: Uri; + constructor(original: Uri, modified: Uri); + } + /** * Represents a tab within the window */ @@ -28,10 +42,15 @@ declare module 'vscode' { // TODO@API point to TabGroup instead? readonly viewColumn: ViewColumn; + + // TODO@API NAME: optional + readonly input: TextTabInput | TextDiffTabInput | unknown; + /** * The resource represented by the tab if available. * Note: Not all tabs have a resource associated with them. */ + // TODO@API remove readonly resource: Uri | undefined; /** @@ -39,6 +58,7 @@ declare module 'vscode' { * This is equivalent to `viewType` for custom editors and `notebookType` for notebooks. * The built-in text editor has an id of 'default' for all configurations. */ + // TODO@API remove readonly viewType: string | undefined; /** @@ -46,6 +66,7 @@ declare module 'vscode' { * {@link Tab.resource resource} and {@link Tab.viewType viewType} will * always be at index 0. */ + // TODO@API remove readonly additionalResourcesAndViewTypes: readonly { readonly resource: Uri | undefined; readonly viewType: string | undefined; @@ -70,6 +91,7 @@ declare module 'vscode' { /** * Indicates the type of tab it is. */ + // TODO@API remove readonly kind: TabKind; /**