UNPKG

@codingame/monaco-vscode-extensions-service-override

Version:

VSCode public API plugged on the monaco editor - extensions service-override

528 lines (525 loc) 22.8 kB
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js'; import { Event } from 'vscode/vscode/vs/base/common/event'; import { DisposableStore, DisposableMap } from 'vscode/vscode/vs/base/common/lifecycle'; import { isEqual } from 'vscode/vscode/vs/base/common/resources'; import { URI } from 'vscode/vscode/vs/base/common/uri'; import { IConfigurationService } from 'vscode/vscode/vs/platform/configuration/common/configuration.service'; import { ILogService } from 'vscode/vscode/vs/platform/log/common/log.service'; import { ExtHostContext, TabInputKind, TabModelOperationKind, MainContext } from 'vscode/vscode/vs/workbench/api/common/extHost.protocol'; import { EditorResourceAccessor, SideBySideEditor, GroupModelChangeKind } from 'vscode/vscode/vs/workbench/common/editor'; import { DiffEditorInput } from 'vscode/vscode/vs/workbench/common/editor/diffEditorInput'; import { isGroupEditorMoveEvent } from 'vscode/vscode/vs/workbench/common/editor/editorGroupModel'; import { SideBySideEditorInput } from 'vscode/vscode/vs/workbench/common/editor/sideBySideEditorInput'; import { AbstractTextResourceEditorInput } from 'vscode/vscode/vs/workbench/common/editor/textResourceEditorInput'; import { ChatEditorInput } from 'vscode/vscode/vs/workbench/contrib/chat/browser/chatEditorInput'; import { CustomEditorInput } from 'vscode/vscode/vs/workbench/contrib/customEditor/browser/customEditorInput'; import { InteractiveEditorInput } from 'vscode/vscode/vs/workbench/contrib/interactive/browser/interactiveEditorInput'; import { MergeEditorInput } from 'vscode/vscode/vs/workbench/contrib/mergeEditor/browser/mergeEditorInput'; import { MultiDiffEditorInput } from 'vscode/vscode/vs/workbench/contrib/multiDiffEditor/browser/multiDiffEditorInput'; import { NotebookEditorInput } from 'vscode/vscode/vs/workbench/contrib/notebook/common/notebookEditorInput'; import { TerminalEditorInput } from 'vscode/vscode/vs/workbench/contrib/terminal/browser/terminalEditorInput'; import { WebviewInput } from 'vscode/vscode/vs/workbench/contrib/webviewPanel/browser/webviewEditorInput'; import { editorGroupToColumn, columnToEditorGroup } from 'vscode/vscode/vs/workbench/services/editor/common/editorGroupColumn'; import { GroupDirection, preferredSideBySideGroupDirection } from 'vscode/vscode/vs/workbench/services/editor/common/editorGroupsService'; import { IEditorGroupsService } from 'vscode/vscode/vs/workbench/services/editor/common/editorGroupsService.service'; import { SIDE_GROUP } from 'vscode/vscode/vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService.service'; import { extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js'; let MainThreadEditorTabs = class MainThreadEditorTabs { constructor(extHostContext, _editorGroupsService, _configurationService, _logService, editorService) { this._editorGroupsService = _editorGroupsService; this._configurationService = _configurationService; this._logService = _logService; this._dispoables = ( new DisposableStore()); this._tabGroupModel = []; this._groupLookup = ( new Map()); this._tabInfoLookup = ( new Map()); this._multiDiffEditorInputListeners = ( new DisposableMap()); this._proxy = ( extHostContext.getProxy(ExtHostContext.ExtHostEditorTabs)); this._dispoables.add(editorService.onDidEditorsChange((event) => { try { this._updateTabsModel(event); } catch { this._logService.error('Failed to update model, rebuilding'); this._createTabsModel(); } })); this._dispoables.add(this._multiDiffEditorInputListeners); this._dispoables.add(this._editorGroupsService.onDidAddGroup(() => this._createTabsModel())); this._dispoables.add(this._editorGroupsService.onDidRemoveGroup(() => this._createTabsModel())); this._editorGroupsService.whenReady.then(() => this._createTabsModel()); } dispose() { this._groupLookup.clear(); this._tabInfoLookup.clear(); this._dispoables.dispose(); } _buildTabObject(group, editor, editorIndex) { const editorId = editor.editorId; const tab = { id: this._generateTabId(editor, group.id), label: editor.getName(), editorId, input: this._editorInputToDto(editor), isPinned: group.isSticky(editorIndex), isPreview: !group.isPinned(editorIndex), isActive: group.isActive(editor), isDirty: editor.isDirty() }; return tab; } _editorInputToDto(editor) { if (editor instanceof MergeEditorInput) { return { kind: TabInputKind.TextMergeInput, base: editor.base, input1: editor.input1.uri, input2: editor.input2.uri, result: editor.resource }; } if (editor instanceof AbstractTextResourceEditorInput) { return { kind: TabInputKind.TextInput, uri: editor.resource }; } if (editor instanceof SideBySideEditorInput && !(editor instanceof DiffEditorInput)) { const primaryResource = editor.primary.resource; const secondaryResource = editor.secondary.resource; if (editor.primary instanceof AbstractTextResourceEditorInput && editor.secondary instanceof AbstractTextResourceEditorInput && isEqual(primaryResource, secondaryResource) && primaryResource && secondaryResource) { return { kind: TabInputKind.TextInput, uri: primaryResource }; } return { kind: TabInputKind.UnknownInput }; } 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 WebviewInput) { return { kind: TabInputKind.WebviewEditorInput, viewType: editor.viewType }; } if (editor instanceof TerminalEditorInput) { return { kind: TabInputKind.TerminalEditorInput }; } 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 }; } } if (editor instanceof InteractiveEditorInput) { return { kind: TabInputKind.InteractiveEditorInput, uri: editor.resource, inputBoxUri: editor.inputResource }; } if (editor instanceof ChatEditorInput) { return { kind: TabInputKind.ChatEditorInput, }; } if (editor instanceof MultiDiffEditorInput) { const diffEditors = []; for (const resource of (editor?.resources.get() ?? [])) { if (resource.originalUri && resource.modifiedUri) { diffEditors.push({ kind: TabInputKind.TextDiffInput, original: resource.originalUri, modified: resource.modifiedUri }); } } return { kind: TabInputKind.MultiDiffEditorInput, diffEditors }; } return { kind: TabInputKind.UnknownInput }; } _generateTabId(editor, groupId) { let resourceString; const resource = EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.BOTH }); if (resource instanceof URI) { resourceString = ( resource.toString()); } else { resourceString = `${resource?.primary?.toString()}-${resource?.secondary?.toString()}`; } return `${groupId}~${editor.editorId}-${editor.typeId}-${resourceString} `; } _onDidGroupActivate() { const activeGroupId = this._editorGroupsService.activeGroup.id; const activeGroup = this._groupLookup.get(activeGroupId); if (activeGroup) { activeGroup.isActive = true; this._proxy.$acceptTabGroupUpdate(activeGroup); } } _onDidTabLabelChange(groupId, editorInput, editorIndex) { const tabId = this._generateTabId(editorInput, groupId); const tabInfo = this._tabInfoLookup.get(tabId); if (tabInfo) { tabInfo.tab.label = editorInput.getName(); this._proxy.$acceptTabOperation({ groupId, index: editorIndex, tabDto: tabInfo.tab, kind: TabModelOperationKind.TAB_UPDATE }); } else { this._logService.error('Invalid model for label change, rebuilding'); this._createTabsModel(); } } _onDidTabOpen(groupId, editorInput, editorIndex) { const group = this._editorGroupsService.getGroup(groupId); const groupInModel = this._groupLookup.get(groupId) !== undefined; if (!group || !groupInModel) { this._createTabsModel(); return; } const tabs = this._groupLookup.get(groupId)?.tabs; if (!tabs) { return; } const tabObject = this._buildTabObject(group, editorInput, editorIndex); tabs.splice(editorIndex, 0, tabObject); const tabId = this._generateTabId(editorInput, groupId); this._tabInfoLookup.set(tabId, { group, editorInput, tab: tabObject }); if (editorInput instanceof MultiDiffEditorInput) { this._multiDiffEditorInputListeners.set(editorInput, Event.fromObservableLight(editorInput.resources)(() => { const tabInfo = this._tabInfoLookup.get(tabId); if (!tabInfo) { return; } tabInfo.tab = this._buildTabObject(group, editorInput, editorIndex); this._proxy.$acceptTabOperation({ groupId, index: editorIndex, tabDto: tabInfo.tab, kind: TabModelOperationKind.TAB_UPDATE }); })); } this._proxy.$acceptTabOperation({ groupId, index: editorIndex, tabDto: tabObject, kind: TabModelOperationKind.TAB_OPEN }); } _onDidTabClose(groupId, editorIndex) { const group = this._editorGroupsService.getGroup(groupId); const tabs = this._groupLookup.get(groupId)?.tabs; if (!group || !tabs) { this._createTabsModel(); return; } const removedTab = tabs.splice(editorIndex, 1); if (removedTab.length === 0) { return; } this._tabInfoLookup.delete(removedTab[0]?.id ?? ''); if (removedTab[0]?.input instanceof MultiDiffEditorInput) { this._multiDiffEditorInputListeners.deleteAndDispose(removedTab[0]?.input); } this._proxy.$acceptTabOperation({ groupId, index: editorIndex, tabDto: removedTab[0], kind: TabModelOperationKind.TAB_CLOSE }); } _onDidTabActiveChange(groupId, editorIndex) { const tabs = this._groupLookup.get(groupId)?.tabs; if (!tabs) { return; } const activeTab = tabs[editorIndex]; activeTab.isActive = true; this._proxy.$acceptTabOperation({ groupId, index: editorIndex, tabDto: activeTab, kind: TabModelOperationKind.TAB_UPDATE }); } _onDidTabDirty(groupId, editorIndex, editor) { const tabId = this._generateTabId(editor, groupId); const tabInfo = this._tabInfoLookup.get(tabId); if (!tabInfo) { this._logService.error('Invalid model for dirty change, rebuilding'); this._createTabsModel(); return; } tabInfo.tab.isDirty = editor.isDirty(); this._proxy.$acceptTabOperation({ groupId, index: editorIndex, tabDto: tabInfo.tab, kind: TabModelOperationKind.TAB_UPDATE }); } _onDidTabPinChange(groupId, editorIndex, editor) { const tabId = this._generateTabId(editor, groupId); const tabInfo = this._tabInfoLookup.get(tabId); const group = tabInfo?.group; const tab = tabInfo?.tab; if (!group || !tab) { this._logService.error('Invalid model for sticky change, rebuilding'); this._createTabsModel(); return; } tab.isPinned = group.isSticky(editorIndex); this._proxy.$acceptTabOperation({ groupId, index: editorIndex, tabDto: tab, kind: TabModelOperationKind.TAB_UPDATE }); } _onDidTabPreviewChange(groupId, editorIndex, editor) { const tabId = this._generateTabId(editor, groupId); const tabInfo = this._tabInfoLookup.get(tabId); const group = tabInfo?.group; const tab = tabInfo?.tab; if (!group || !tab) { this._logService.error('Invalid model for sticky change, rebuilding'); this._createTabsModel(); return; } tab.isPreview = !group.isPinned(editorIndex); this._proxy.$acceptTabOperation({ kind: TabModelOperationKind.TAB_UPDATE, groupId, tabDto: tab, index: editorIndex }); } _onDidTabMove(groupId, editorIndex, oldEditorIndex, editor) { const tabs = this._groupLookup.get(groupId)?.tabs; if (!tabs) { this._logService.error('Invalid model for move change, rebuilding'); this._createTabsModel(); return; } const removedTab = tabs.splice(oldEditorIndex, 1); if (removedTab.length === 0) { return; } tabs.splice(editorIndex, 0, removedTab[0]); this._proxy.$acceptTabOperation({ kind: TabModelOperationKind.TAB_MOVE, groupId, tabDto: removedTab[0], index: editorIndex, oldIndex: oldEditorIndex }); } _createTabsModel() { if (this._editorGroupsService.groups.length === 0) { return; } this._tabGroupModel = []; this._groupLookup.clear(); this._tabInfoLookup.clear(); let tabs = []; for (const group of this._editorGroupsService.groups) { const currentTabGroupModel = { groupId: group.id, isActive: group.id === this._editorGroupsService.activeGroup.id, viewColumn: editorGroupToColumn(this._editorGroupsService, group), tabs: [] }; group.editors.forEach((editor, editorIndex) => { const tab = this._buildTabObject(group, editor, editorIndex); tabs.push(tab); this._tabInfoLookup.set(this._generateTabId(editor, group.id), { group, tab, editorInput: editor }); }); currentTabGroupModel.tabs = tabs; this._tabGroupModel.push(currentTabGroupModel); this._groupLookup.set(group.id, currentTabGroupModel); tabs = []; } this._proxy.$acceptEditorTabModel(this._tabGroupModel); } _updateTabsModel(changeEvent) { const event = changeEvent.event; const groupId = changeEvent.groupId; switch (event.kind) { case GroupModelChangeKind.GROUP_ACTIVE: if (groupId === this._editorGroupsService.activeGroup.id) { this._onDidGroupActivate(); break; } else { return; } case GroupModelChangeKind.EDITOR_LABEL: if (event.editor !== undefined && event.editorIndex !== undefined) { this._onDidTabLabelChange(groupId, event.editor, event.editorIndex); break; } case GroupModelChangeKind.EDITOR_OPEN: if (event.editor !== undefined && event.editorIndex !== undefined) { this._onDidTabOpen(groupId, event.editor, event.editorIndex); break; } case GroupModelChangeKind.EDITOR_CLOSE: if (event.editorIndex !== undefined) { this._onDidTabClose(groupId, event.editorIndex); break; } case GroupModelChangeKind.EDITOR_ACTIVE: if (event.editorIndex !== undefined) { this._onDidTabActiveChange(groupId, event.editorIndex); break; } case GroupModelChangeKind.EDITOR_DIRTY: if (event.editorIndex !== undefined && event.editor !== undefined) { this._onDidTabDirty(groupId, event.editorIndex, event.editor); break; } case GroupModelChangeKind.EDITOR_STICKY: if (event.editorIndex !== undefined && event.editor !== undefined) { this._onDidTabPinChange(groupId, event.editorIndex, event.editor); break; } case GroupModelChangeKind.EDITOR_PIN: if (event.editorIndex !== undefined && event.editor !== undefined) { this._onDidTabPreviewChange(groupId, event.editorIndex, event.editor); break; } case GroupModelChangeKind.EDITOR_TRANSIENT: break; case GroupModelChangeKind.EDITOR_MOVE: if (isGroupEditorMoveEvent(event) && event.editor && event.editorIndex !== undefined && event.oldEditorIndex !== undefined) { this._onDidTabMove(groupId, event.editorIndex, event.oldEditorIndex, event.editor); break; } default: this._createTabsModel(); } } $moveTab(tabId, index, viewColumn, preserveFocus) { const groupId = columnToEditorGroup(this._editorGroupsService, this._configurationService, viewColumn); const tabInfo = this._tabInfoLookup.get(tabId); const tab = tabInfo?.tab; if (!tab) { throw ( new Error(`Attempted to close tab with id ${tabId} which does not exist`)); } let targetGroup; const sourceGroup = this._editorGroupsService.getGroup(tabInfo.group.id); if (!sourceGroup) { return; } if (this._groupLookup.get(groupId) === undefined) { let direction = GroupDirection.RIGHT; if (viewColumn === SIDE_GROUP) { direction = preferredSideBySideGroupDirection(this._configurationService); } targetGroup = this._editorGroupsService.addGroup(this._editorGroupsService.groups[this._editorGroupsService.groups.length - 1], direction); } else { targetGroup = this._editorGroupsService.getGroup(groupId); } if (!targetGroup) { return; } if (index < 0 || index > targetGroup.editors.length) { index = targetGroup.editors.length; } const editorInput = tabInfo?.editorInput; if (!editorInput) { return; } sourceGroup.moveEditor(editorInput, targetGroup, { index, preserveFocus }); return; } async $closeTab(tabIds, preserveFocus) { const groups = ( new Map()); for (const tabId of tabIds) { const tabInfo = this._tabInfoLookup.get(tabId); const tab = tabInfo?.tab; const group = tabInfo?.group; const editorTab = tabInfo?.editorInput; if (!group || !tab || !tabInfo || !editorTab) { continue; } const groupEditors = groups.get(group); if (!groupEditors) { groups.set(group, [editorTab]); } else { groupEditors.push(editorTab); } } const results = []; for (const [group, editors] of groups) { results.push(await group.closeEditors(editors, { preserveFocus })); } return results.every(result => result); } async $closeGroup(groupIds, preserveFocus) { const groupCloseResults = []; for (const groupId of groupIds) { const group = this._editorGroupsService.getGroup(groupId); if (group) { groupCloseResults.push(await group.closeAllEditors()); if (group.count === 0 && this._editorGroupsService.getGroup(group.id)) { this._editorGroupsService.removeGroup(group); } } } return groupCloseResults.every(result => result); } }; MainThreadEditorTabs = __decorate([ extHostNamedCustomer(MainContext.MainThreadEditorTabs), ( __param(1, IEditorGroupsService)), ( __param(2, IConfigurationService)), ( __param(3, ILogService)), ( __param(4, IEditorService)) ], MainThreadEditorTabs); export { MainThreadEditorTabs };