diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts index 2796bab37d9..7992e85fb29 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts @@ -51,7 +51,7 @@ import { BreadcrumbsConfig, IBreadcrumbsService } from './breadcrumbs.js'; import { BreadcrumbsModel, FileElement, OutlineElement2 } from './breadcrumbsModel.js'; import { BreadcrumbsFilePicker, BreadcrumbsOutlinePicker } from './breadcrumbsPicker.js'; import { IEditorGroupView } from './editor.js'; -import { createEditorTypeActions, editorTypeDisplayLabel, getAvailableEditorTypes } from './editorTypePicker.js'; +import { createEditorTypeActions, editorTypeDisplayLabel, getAvailableEditorTypes, hasDefaultEditorAssociation } from './editorTypePicker.js'; import './media/breadcrumbscontrol.css'; import { ScrollbarVisibility } from '../../../../base/common/scrollable.js'; import { CancellationToken } from '../../../../base/common/cancellation.js'; @@ -534,7 +534,8 @@ export class BreadcrumbsControl { const previousWidth = wasHidden ? 0 : this._editorTypeNode.offsetWidth; const available = (this._options.showEditorTypePicker && this._cfShowEditorType.getValue()) ? getAvailableEditorTypes(this._editorGroup.activeEditor, this._editorResolverService) : undefined; - if (!available) { + const configuredDefaultEditor = available ? this._editorResolverService.getConfiguredDefaultEditor(available.resource, available.isDiffEditor) : undefined; + if (!available || !hasDefaultEditorAssociation(available, configuredDefaultEditor)) { this._editorTypeNode.classList.toggle('hidden', true); } else { const current = available.editors.find(editor => editor.id === available.currentId); diff --git a/src/vs/workbench/browser/parts/editor/editorTypePicker.ts b/src/vs/workbench/browser/parts/editor/editorTypePicker.ts index 2a946675d6d..787a84fe80d 100644 --- a/src/vs/workbench/browser/parts/editor/editorTypePicker.ts +++ b/src/vs/workbench/browser/parts/editor/editorTypePicker.ts @@ -10,7 +10,7 @@ import { localize } from '../../../../nls.js'; import { ICommandService } from '../../../../platform/commands/common/commands.js'; import { DEFAULT_EDITOR_ASSOCIATION, EditorResourceAccessor, SideBySideEditor, isDiffEditorInput } from '../../../common/editor.js'; import { EditorInput } from '../../../common/editor/editorInput.js'; -import { IEditorResolverService, RegisteredEditorInfo } from '../../../services/editor/common/editorResolverService.js'; +import { IEditorResolverService, RegisteredEditorInfo, RegisteredEditorPriority, priorityToRank } from '../../../services/editor/common/editorResolverService.js'; import { IEditorService } from '../../../services/editor/common/editorService.js'; import { REOPEN_ACTIVE_EDITOR_WITH_COMMAND_ID } from './editorCommands.js'; @@ -52,6 +52,22 @@ export function getAvailableEditorTypes(activeEditor: EditorInput | null | undef }; } +/** Whether a custom editor can be selected by default for the resource. */ +export function hasDefaultEditorAssociation(available: IAvailableEditorTypes, configuredDefaultEditor: string | undefined): boolean { + if (configuredDefaultEditor !== undefined && configuredDefaultEditor !== DEFAULT_EDITOR_ASSOCIATION.id) { + return true; + } + + return available.editors.some(editor => { + if (editor.id === DEFAULT_EDITOR_ASSOCIATION.id) { + return false; + } + + const priority = available.isDiffEditor ? editor.priority.diff : editor.priority.editor; + return priorityToRank(priority) >= priorityToRank(RegisteredEditorPriority.builtin); + }); +} + /** * The label to show for an editor type. In a diff context the default text editor is presented as * "Text Diff Editor" to match how it actually opens. diff --git a/src/vs/workbench/test/browser/parts/editor/editorTypePicker.test.ts b/src/vs/workbench/test/browser/parts/editor/editorTypePicker.test.ts new file mode 100644 index 00000000000..fe90c8dd8f7 --- /dev/null +++ b/src/vs/workbench/test/browser/parts/editor/editorTypePicker.test.ts @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { URI } from '../../../../../base/common/uri.js'; +import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js'; +import { DEFAULT_EDITOR_ASSOCIATION } from '../../../../common/editor.js'; +import { IAvailableEditorTypes, hasDefaultEditorAssociation } from '../../../../browser/parts/editor/editorTypePicker.js'; +import { RegisteredEditorInfo, RegisteredEditorPriority } from '../../../../services/editor/common/editorResolverService.js'; + +suite('Editor Type Picker', () => { + + ensureNoDisposablesAreLeakedInTestSuite(); + + function editor(id: string, editorPriority: RegisteredEditorPriority, diffPriority = editorPriority): RegisteredEditorInfo { + return { + id, + label: id, + priority: { + editor: editorPriority, + diff: diffPriority, + merge: editorPriority, + } + }; + } + + function available(customEditor: RegisteredEditorInfo, isDiffEditor = false): IAvailableEditorTypes { + return { + resource: URI.file('/test.txt'), + isDiffEditor, + currentId: DEFAULT_EDITOR_ASSOCIATION.id, + editors: [ + editor(DEFAULT_EDITOR_ASSOCIATION.id, RegisteredEditorPriority.builtin), + customEditor, + ] + }; + } + + test('default editor association visibility', () => { + const optionalEditor = available(editor('test.optionalEditor', RegisteredEditorPriority.option)); + const defaultEditor = available(editor('test.defaultEditor', RegisteredEditorPriority.default)); + const builtinEditor = available(editor('test.builtinEditor', RegisteredEditorPriority.builtin)); + const diffDefaultEditor = available(editor('test.diffDefaultEditor', RegisteredEditorPriority.option, RegisteredEditorPriority.default), true); + + assert.deepStrictEqual({ + optionalEditor: hasDefaultEditorAssociation(optionalEditor, undefined), + configuredOptionalEditor: hasDefaultEditorAssociation(optionalEditor, 'test.optionalEditor'), + configuredTextEditor: hasDefaultEditorAssociation(optionalEditor, DEFAULT_EDITOR_ASSOCIATION.id), + defaultEditor: hasDefaultEditorAssociation(defaultEditor, undefined), + defaultEditorOverriddenWithText: hasDefaultEditorAssociation(defaultEditor, DEFAULT_EDITOR_ASSOCIATION.id), + builtinEditor: hasDefaultEditorAssociation(builtinEditor, undefined), + diffDefaultEditor: hasDefaultEditorAssociation(diffDefaultEditor, undefined), + }, { + optionalEditor: false, + configuredOptionalEditor: true, + configuredTextEditor: false, + defaultEditor: true, + defaultEditorOverriddenWithText: true, + builtinEditor: true, + diffDefaultEditor: true, + }); + }); +}); \ No newline at end of file