From 84afb9f0453be803864bbc5030af39535237765b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Mon, 28 Sep 2020 11:06:20 +0200 Subject: [PATCH] debt - adopt some preferred URIs across the code --- .../parts/editor/breadcrumbsControl.ts | 16 ++--- .../browser/parts/editor/editorGroupView.ts | 4 +- .../browser/parts/editor/editorQuickAccess.ts | 2 +- .../browser/parts/editor/editorStatus.ts | 6 +- .../parts/editor/noTabsTitleControl.ts | 2 +- .../browser/parts/editor/tabsTitleControl.ts | 4 +- .../browser/parts/titlebar/titlebarPart.ts | 18 +++-- src/vs/workbench/common/editor.ts | 65 +++++++++++++++---- .../common/editor/textResourceEditorInput.ts | 4 +- .../files/browser/editors/textFileEditor.ts | 10 +-- .../contrib/files/browser/fileActions.ts | 10 +-- .../contrib/files/browser/fileCommands.ts | 2 +- .../workbench/contrib/files/browser/files.ts | 2 +- .../files/browser/views/explorerView.ts | 2 +- .../files/browser/views/explorerViewer.ts | 6 +- .../files/browser/views/openEditorsView.ts | 4 +- .../files/common/editors/fileEditorInput.ts | 2 +- .../contrib/files/common/explorerService.ts | 3 +- .../workbench/contrib/files/common/files.ts | 2 +- .../fileActions.contribution.ts | 7 +- .../workbench/contrib/scm/browser/activity.ts | 7 +- .../contrib/scm/browser/scmViewPane.ts | 8 +-- .../search/browser/anythingQuickAccess.ts | 12 ++-- .../contrib/search/browser/searchActions.ts | 11 ++-- .../contrib/timeline/browser/timelinePane.ts | 7 +- src/vs/workbench/electron-sandbox/window.ts | 4 +- .../browser/configurationResolverService.ts | 13 ++-- .../services/editor/browser/editorService.ts | 7 +- .../services/editor/common/editorOpenWith.ts | 9 +-- .../services/history/browser/history.ts | 13 ++-- .../test/browser/parts/editor/editor.test.ts | 16 ++++- 31 files changed, 159 insertions(+), 119 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts index 4d102995f79..fd73e9a9507 100644 --- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts +++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts @@ -38,7 +38,7 @@ import { ResourceLabel } from 'vs/workbench/browser/labels'; import { BreadcrumbsConfig, IBreadcrumbsService } from 'vs/workbench/browser/parts/editor/breadcrumbs'; import { BreadcrumbElement, EditorBreadcrumbsModel, FileElement } from 'vs/workbench/browser/parts/editor/breadcrumbsModel'; import { BreadcrumbsPicker, createBreadcrumbsPicker } from 'vs/workbench/browser/parts/editor/breadcrumbsPicker'; -import { IEditorPartOptions, toResource, SideBySideEditor, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions } from 'vs/workbench/common/editor'; +import { IEditorPartOptions, toResource, SideBySideEditor } from 'vs/workbench/common/editor'; import { ACTIVE_GROUP, ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; @@ -49,7 +49,6 @@ import { withNullAsUndefined, withUndefinedAsNull } from 'vs/base/common/types'; import { ILabelService } from 'vs/platform/label/common/label'; import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfigurationService'; import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor'; -import { Registry } from 'vs/platform/registry/common/platform'; import { CATEGORIES } from 'vs/workbench/common/actions'; class Item extends BreadcrumbsItem { @@ -250,15 +249,8 @@ export class BreadcrumbsControl { } } - // display uri which can be derived from file input - let fileInfoUri = uri; - let input = this._editorGroup.activeEditor; - if (input instanceof SideBySideEditorInput) { - input = input.primary; - } - if (Registry.as(Extensions.EditorInputFactories).getFileEditorInputFactory().isFileEditorInput(input)) { - fileInfoUri = input.preferredResource; - } + // display uri which can be derived from certain inputs + const fileInfoUri = toResource(this._editorGroup.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); this.domNode.classList.toggle('hidden', false); this._ckBreadcrumbsVisible.set(true); @@ -266,7 +258,7 @@ export class BreadcrumbsControl { const editor = this._getActiveCodeEditor(); const model = new EditorBreadcrumbsModel( - fileInfoUri, + fileInfoUri ?? uri, uri, editor, this._configurationService, this._textResourceConfigurationService, diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 9f5c4d3ee01..abf411ec137 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -5,7 +5,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, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, Deprecated_EditorPinnedContext, Deprecated_EditorDirtyContext } from 'vs/workbench/common/editor'; +import { EditorInput, EditorOptions, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorCloseEvent, ActiveEditorDirtyContext, IEditorPane, EditorGroupEditorsCountContext, SaveReason, IEditorPartOptionsChangeEvent, EditorsOrder, IVisibleEditorPane, ActiveEditorStickyContext, ActiveEditorPinnedContext, Deprecated_EditorPinnedContext, Deprecated_EditorDirtyContext, toResource } from 'vs/workbench/common/editor'; import { Event, Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor } from 'vs/base/browser/dom'; @@ -575,7 +575,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { private toEditorTelemetryDescriptor(editor: EditorInput): object { const descriptor = editor.getTelemetryDescriptor(); - const resource = editor.resource; + const resource = toResource(editor, { usePreferredResource: true }); const path = resource ? resource.scheme === Schemas.file ? resource.fsPath : resource.path : undefined; if (resource && path) { descriptor['resource'] = { mimeType: guessMimeTypes(resource).join(', '), scheme: resource.scheme, ext: extname(resource), path: hash(path) }; diff --git a/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts b/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts index 231efdd147a..ff67d715cb9 100644 --- a/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts +++ b/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts @@ -137,7 +137,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro } return this.doGetEditors().map(({ editor, groupId }): IEditorQuickPickItem => { - const resource = toResource(editor, { supportSideBySide: SideBySideEditor.PRIMARY }); + const resource = toResource(editor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); const isDirty = editor.isDirty() && !editor.isSaving(); const description = editor.getDescription(); const nameAndDescription = description ? `${editor.getName()} ${description}` : editor.getName(); diff --git a/src/vs/workbench/browser/parts/editor/editorStatus.ts b/src/vs/workbench/browser/parts/editor/editorStatus.ts index ac5936cf082..a5f8a200b3b 100644 --- a/src/vs/workbench/browser/parts/editor/editorStatus.ts +++ b/src/vs/workbench/browser/parts/editor/editorStatus.ts @@ -1059,7 +1059,7 @@ export class ChangeModeAction extends Action { } const textModel = activeTextEditorControl.getModel(); - const resource = this.editorService.activeEditor ? toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }) : null; + const resource = this.editorService.activeEditor ? toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }) : null; let hasLanguageSupport = !!resource; if (resource?.scheme === Schemas.untitled && !this.textFileService.untitled.get(resource)?.hasAssociatedFilePath) { @@ -1157,7 +1157,7 @@ export class ChangeModeAction extends Action { let languageSelection: ILanguageSelection | undefined; if (pick === autoDetectMode) { if (textModel) { - const resource = toResource(activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }); + const resource = toResource(activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); if (resource) { languageSelection = this.modeService.createByFilepathOrFirstLine(resource, textModel.getLineContent(1)); } @@ -1336,7 +1336,7 @@ export class ChangeEncodingAction extends Action { await timeout(50); // quick input is sensitive to being opened so soon after another - const resource = toResource(activeEditorPane.input, { supportSideBySide: SideBySideEditor.PRIMARY }); + const resource = toResource(activeEditorPane.input, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); if (!resource || (!this.fileService.canHandleResource(resource) && resource.scheme !== Schemas.untitled)) { return; // encoding detection only possible for resources the file service can handle or that are untitled } diff --git a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts index c42ffee0434..3fe68d3e368 100644 --- a/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/noTabsTitleControl.ts @@ -274,7 +274,7 @@ export class NoTabsTitleControl extends TitleControl { editorLabel.setResource( { - resource: toResource(editor, { supportSideBySide: SideBySideEditor.BOTH }), + resource: toResource(editor, { supportSideBySide: SideBySideEditor.BOTH, usePreferredResource: true }), name: editor.getName(), description }, diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 9e2651550e4..cb5914e3d69 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -1114,12 +1114,12 @@ export class TabsTitleControl extends TitleControl { // Label tabLabelWidget.setResource( - { name, description, resource: toResource(editor, { supportSideBySide: SideBySideEditor.BOTH }) }, + { name, description, resource: toResource(editor, { supportSideBySide: SideBySideEditor.BOTH, usePreferredResource: true }) }, { title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel } ); // Tests helper - const resource = toResource(editor, { supportSideBySide: SideBySideEditor.PRIMARY }); + const resource = toResource(editor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); if (resource) { tabContainer.setAttribute('data-resource-name', basenameOrAuthority(resource)); } else { diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts index fa7ce81e939..32c5cb8c260 100644 --- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts +++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/titlebarpart'; -import * as resources from 'vs/base/common/resources'; +import { dirname, basename } from 'vs/base/common/resources'; import { Part } from 'vs/workbench/browser/part'; import { ITitleService, ITitleProperties } from 'vs/workbench/services/title/common/titleService'; import { getZoomFactor } from 'vs/base/browser/browser'; @@ -40,6 +40,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IProductService } from 'vs/platform/product/common/productService'; import { Schemas } from 'vs/base/common/network'; +import { withNullAsUndefined } from 'vs/base/common/types'; export class TitlebarPart extends Part implements ITitleService { @@ -258,8 +259,8 @@ export class TitlebarPart extends Part implements ITitleService { } // Compute active editor folder - const editorResource = editor ? toResource(editor) : undefined; - let editorFolderResource = editorResource ? resources.dirname(editorResource) : undefined; + const editorResource = toResource(editor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); + let editorFolderResource = editorResource ? dirname(editorResource) : undefined; if (editorFolderResource?.path === '.') { editorFolderResource = undefined; } @@ -267,21 +268,18 @@ export class TitlebarPart extends Part implements ITitleService { // Compute folder resource // Single Root Workspace: always the root single workspace in this case // Otherwise: root folder of the currently active file if any - let folder: IWorkspaceFolder | null = null; + let folder: IWorkspaceFolder | undefined = undefined; if (this.contextService.getWorkbenchState() === WorkbenchState.FOLDER) { folder = workspace.folders[0]; - } else { - const resource = toResource(editor, { supportSideBySide: SideBySideEditor.PRIMARY }); - if (resource) { - folder = this.contextService.getWorkspaceFolder(resource); - } + } else if (editorResource) { + folder = withNullAsUndefined(this.contextService.getWorkspaceFolder(editorResource)); } // Variables const activeEditorShort = editor ? editor.getTitle(Verbosity.SHORT) : ''; const activeEditorMedium = editor ? editor.getTitle(Verbosity.MEDIUM) : activeEditorShort; const activeEditorLong = editor ? editor.getTitle(Verbosity.LONG) : activeEditorMedium; - const activeFolderShort = editorFolderResource ? resources.basename(editorFolderResource) : ''; + const activeFolderShort = editorFolderResource ? basename(editorFolderResource) : ''; const activeFolderMedium = editorFolderResource ? this.labelService.getUriLabel(editorFolderResource, { relative: true }) : ''; const activeFolderLong = editorFolderResource ? this.labelService.getUriLabel(editorFolderResource) : ''; const rootName = this.labelService.getWorkspaceLabel(workspace); diff --git a/src/vs/workbench/common/editor.ts b/src/vs/workbench/common/editor.ts index c4da1e0b2e2..8a460e3ec95 100644 --- a/src/vs/workbench/common/editor.ts +++ b/src/vs/workbench/common/editor.ts @@ -659,11 +659,35 @@ export interface IModeSupport { setMode(mode: string): void; } +export interface IEditorInputWithPreferredResource { + + /** + * An editor may provide an additional preferred resource alongside + * the `resource` property. While the `resource` property serves as + * unique identifier of the editor that should be used whenever we + * compare to other editors, the `preferredResource` should be used + * in places where e.g. the resource is shown to the user. + * + * For example: on Windows and macOS, the same URI with different + * casing may point to the same file. The editor may chose to + * "normalize" the URIs so that only one editor opens for different + * URIs. But when displaying the editor label to the user, the + * preferred URI should be used. + */ + readonly preferredResource: URI; +} + +export function isEditorInputWithPreferredResource(obj: unknown): obj is IEditorInputWithPreferredResource { + const editorInputWithPreferredResource = obj as IEditorInputWithPreferredResource; + + return editorInputWithPreferredResource && !!editorInputWithPreferredResource.preferredResource; +} + /** * This is a tagging interface to declare an editor input being capable of dealing with files. It is only used in the editor registry * to register this kind of input to the platform. */ -export interface IFileEditorInput extends IEditorInput, IEncodingSupport, IModeSupport { +export interface IFileEditorInput extends IEditorInput, IEncodingSupport, IModeSupport, IEditorInputWithPreferredResource { /** * Gets the resource this file input is about. This will always be the @@ -673,14 +697,6 @@ export interface IFileEditorInput extends IEditorInput, IEncodingSupport, IModeS */ readonly resource: URI; - /** - * Gets the preferred resource of the editor. In most cases this will - * be identical to the resource. But in some cases the preferredResource - * may differ in path casing to the actual resource because we keep - * canonical forms of resources in-memory. - */ - readonly preferredResource: URI; - /** * Sets the preferred resource to use for this file input. */ @@ -1267,8 +1283,33 @@ export enum SideBySideEditor { } export interface IResourceOptions { + + /** + * Allows to access the `resource` of side by side editors. + */ supportSideBySide?: SideBySideEditor; + + /** + * Allows to filter the scheme to consider. + */ filterByScheme?: string | string[]; + + /** + * Will return the `preferredResource` of an editor if any. + * + * An editor may provide an additional preferred resource alongside + * the `resource` property. While the `resource` property serves as + * unique identifier of the editor that should be used whenever we + * compare to other editors, the `preferredResource` should be used + * in places where e.g. the resource is shown to the user. + * + * For example: on Windows and macOS, the same URI with different + * casing may point to the same file. The editor may chose to + * "normalize" the URIs so that only one editor opens for different + * URIs. But when displaying the editor label to the user, the + * preferred URI should be used. + */ + usePreferredResource?: boolean; } export function toResource(editor: IEditorInput | undefined | null): URI | undefined; @@ -1282,15 +1323,15 @@ export function toResource(editor: IEditorInput | undefined | null, options?: IR if (options?.supportSideBySide && editor instanceof SideBySideEditorInput) { if (options?.supportSideBySide === SideBySideEditor.BOTH) { return { - primary: toResource(editor.primary, { filterByScheme: options.filterByScheme }), - secondary: toResource(editor.secondary, { filterByScheme: options.filterByScheme }) + primary: toResource(editor.primary, { filterByScheme: options.filterByScheme, usePreferredResource: options.usePreferredResource }), + secondary: toResource(editor.secondary, { filterByScheme: options.filterByScheme, usePreferredResource: options.usePreferredResource }) }; } editor = options.supportSideBySide === SideBySideEditor.PRIMARY ? editor.primary : editor.secondary; } - const resource = editor.resource; + const resource = (options?.usePreferredResource && isEditorInputWithPreferredResource(editor)) ? editor.preferredResource : editor.resource; if (!resource || !options || !options.filterByScheme) { return resource; } diff --git a/src/vs/workbench/common/editor/textResourceEditorInput.ts b/src/vs/workbench/common/editor/textResourceEditorInput.ts index 40a50a7c44b..32c0fab3c2e 100644 --- a/src/vs/workbench/common/editor/textResourceEditorInput.ts +++ b/src/vs/workbench/common/editor/textResourceEditorInput.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { EditorInput, Verbosity, GroupIdentifier, IEditorInput, ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor'; +import { EditorInput, Verbosity, GroupIdentifier, IEditorInput, ISaveOptions, IRevertOptions, IEditorInputWithPreferredResource } from 'vs/workbench/common/editor'; import { URI } from 'vs/base/common/uri'; import { ITextFileService, ITextFileSaveOptions } from 'vs/workbench/services/textfile/common/textfiles'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; @@ -18,7 +18,7 @@ import { dirname, extUri } from 'vs/base/common/resources'; /** * The base class for all editor inputs that open in text editors. */ -export abstract class AbstractTextResourceEditorInput extends EditorInput { +export abstract class AbstractTextResourceEditorInput extends EditorInput implements IEditorInputWithPreferredResource { private static readonly MEMOIZER = createMemoizer(); diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts index d40c20d8c66..ad397db18b6 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileEditor.ts @@ -160,14 +160,14 @@ export class TextFileEditor extends BaseTextEditor { } // Offer to create a file from the error if we have a file not found and the name is valid - if ((error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND && isValidBasename(basename(input.resource))) { + if ((error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND && isValidBasename(basename(input.preferredResource))) { throw createErrorWithActions(toErrorMessage(error), { actions: [ new Action('workbench.files.action.createMissingFile', nls.localize('createFile', "Create File"), undefined, true, async () => { - await this.textFileService.create(input.resource); + await this.textFileService.create(input.preferredResource); return this.editorService.openEditor({ - resource: input.resource, + resource: input.preferredResource, options: { pinned: true // new file gets pinned by default } @@ -207,10 +207,10 @@ export class TextFileEditor extends BaseTextEditor { await this.group.closeEditor(this.input); // Best we can do is to reveal the folder in the explorer - if (this.contextService.isInsideWorkspace(input.resource)) { + if (this.contextService.isInsideWorkspace(input.preferredResource)) { await this.viewletService.openViewlet(VIEWLET_ID); - this.explorerService.select(input.resource, true); + this.explorerService.select(input.preferredResource, true); } } diff --git a/src/vs/workbench/contrib/files/browser/fileActions.ts b/src/vs/workbench/contrib/files/browser/fileActions.ts index 041deec72e9..188b8e30378 100644 --- a/src/vs/workbench/contrib/files/browser/fileActions.ts +++ b/src/vs/workbench/contrib/files/browser/fileActions.ts @@ -451,7 +451,7 @@ export class GlobalCompareResourcesAction extends Action { async run(): Promise { const activeInput = this.editorService.activeEditor; - const activeResource = activeInput ? activeInput.resource : undefined; + const activeResource = toResource(activeInput, { usePreferredResource: true }); if (activeResource && this.textModelService.canHandleResource(activeResource)) { // Compare with next editor that opens @@ -462,7 +462,7 @@ export class GlobalCompareResourcesAction extends Action { toDispose.dispose(); // Open editor as diff - const resource = editor.resource; + const resource = toResource(editor, { usePreferredResource: true }); if (resource && this.textModelService.canHandleResource(resource)) { return { override: this.editorService.openEditor({ @@ -633,7 +633,7 @@ export class ShowActiveFileInExplorer extends Action { } async run(): Promise { - const resource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }); + const resource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); if (resource) { this.commandService.executeCommand(REVEAL_IN_EXPLORER_COMMAND_ID, resource); } else { @@ -701,7 +701,7 @@ export class ShowOpenedFileInNewWindow extends Action { } async run(): Promise { - const fileResource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }); + const fileResource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); if (fileResource) { if (this.fileService.canHandleResource(fileResource)) { this.hostService.openWindow([{ fileUri: fileResource }], { forceNewWindow: true }); @@ -813,7 +813,7 @@ export class CompareWithClipboardAction extends Action { } async run(): Promise { - const resource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }); + const resource = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); const scheme = `clipboardCompare${CompareWithClipboardAction.SCHEME_COUNTER++}`; if (resource && (this.fileService.canHandleResource(resource) || resource.scheme === Schemas.untitled)) { if (!this.registrationDisposal) { diff --git a/src/vs/workbench/contrib/files/browser/fileCommands.ts b/src/vs/workbench/contrib/files/browser/fileCommands.ts index 66a5bd24f00..c1dddaa9c4b 100644 --- a/src/vs/workbench/contrib/files/browser/fileCommands.ts +++ b/src/vs/workbench/contrib/files/browser/fileCommands.ts @@ -305,7 +305,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ handler: async (accessor) => { const editorService = accessor.get(IEditorService); const activeInput = editorService.activeEditor; - const resource = activeInput ? activeInput.resource : null; + const resource = toResource(activeInput, { usePreferredResource: true, supportSideBySide: SideBySideEditor.PRIMARY }); const resources = resource ? [resource] : []; await resourcesToClipboard(resources, false, accessor.get(IClipboardService), accessor.get(INotificationService), accessor.get(ILabelService)); } diff --git a/src/vs/workbench/contrib/files/browser/files.ts b/src/vs/workbench/contrib/files/browser/files.ts index ac012e62fc4..655aa10427a 100644 --- a/src/vs/workbench/contrib/files/browser/files.ts +++ b/src/vs/workbench/contrib/files/browser/files.ts @@ -50,7 +50,7 @@ export function getResourceForCommand(resource: URI | object | undefined, listSe return focus.getResource(); } - return editorService.activeEditor ? toResource(editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }) : undefined; + return toResource(editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); } export function getMultiSelectedResources(resource: URI | object | undefined, listService: IListService, editorService: IEditorService, explorerService: IExplorerService): Array { diff --git a/src/vs/workbench/contrib/files/browser/views/explorerView.ts b/src/vs/workbench/contrib/files/browser/views/explorerView.ts index df7c870fee2..30120d429fa 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerView.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerView.ts @@ -680,7 +680,7 @@ export class ExplorerView extends ViewPane { } // check for files - return withNullAsUndefined(toResource(input, { supportSideBySide: SideBySideEditor.PRIMARY })); + return withNullAsUndefined(toResource(input, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true })); } public async selectResource(resource: URI | undefined, reveal = this.autoReveal, retry = 0): Promise { diff --git a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts index bb47af156f8..4f7558b6cad 100644 --- a/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts +++ b/src/vs/workbench/contrib/files/browser/views/explorerViewer.ts @@ -57,6 +57,7 @@ import { domEvent } from 'vs/base/browser/event'; import { IEditableData } from 'vs/workbench/common/views'; import { IEditorInput } from 'vs/workbench/common/editor'; import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation'; +import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; export class ExplorerDelegate implements IListVirtualDelegate { @@ -541,6 +542,7 @@ export class FilesFilter implements ITreeFilter { @IConfigurationService private readonly configurationService: IConfigurationService, @IExplorerService private readonly explorerService: IExplorerService, @IEditorService private readonly editorService: IEditorService, + @IUriIdentityService private readonly uriIdentityService: IUriIdentityService ) { this.hiddenExpressionPerRoot = new Map(); this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => this.updateConfiguration())); @@ -554,7 +556,7 @@ export class FilesFilter implements ITreeFilter { let shouldFire = false; this.hiddenUris.forEach(u => { editors.forEach(e => { - if (e.resource && isEqualOrParent(e.resource, u)) { + if (e.resource && this.uriIdentityService.extUri.isEqualOrParent(e.resource, u)) { // A filtered resource suddenly became visible since user opened an editor shouldFire = true; } @@ -629,7 +631,7 @@ export class FilesFilter implements ITreeFilter { if ((cached && cached.parsed(path.relative(stat.root.resource.path, stat.resource.path), stat.name, name => !!(stat.parent && stat.parent.getChild(name)))) || stat.parent?.isExcluded) { stat.isExcluded = true; const editors = this.editorService.visibleEditors; - const editor = editors.find(e => e.resource && isEqualOrParent(e.resource, stat.resource)); + const editor = editors.find(e => e.resource && this.uriIdentityService.extUri.isEqualOrParent(e.resource, stat.resource)); if (editor) { this.editorsAffectingFilter.add(editor); return true; // Show all opened files and their parents diff --git a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts index 7bbdaa69a66..04d7bcc2fad 100644 --- a/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts +++ b/src/vs/workbench/contrib/files/browser/views/openEditorsView.ts @@ -379,7 +379,7 @@ export class OpenEditorsView extends ViewPane { const element = e.element; const actions: IAction[] = []; - const actionsDisposable = createAndFillInContextMenuActions(this.contributedContextMenu, { shouldForwardArgs: true, arg: element instanceof OpenEditor ? element.editor.resource : {} }, actions, this.contextMenuService); + const actionsDisposable = createAndFillInContextMenuActions(this.contributedContextMenu, { shouldForwardArgs: true, arg: element instanceof OpenEditor ? toResource(element.editor, { usePreferredResource: true }) : {} }, actions, this.contextMenuService); this.contextMenuService.showContextMenu({ getAnchor: () => e.anchor, @@ -597,7 +597,7 @@ class OpenEditorRenderer implements IListRenderer { - return this.instantiationService.createInstance(BinaryEditorModel, this.resource, this.getName()).load(); + return this.instantiationService.createInstance(BinaryEditorModel, this.preferredResource, this.getName()).load(); } isResolved(): boolean { diff --git a/src/vs/workbench/contrib/files/common/explorerService.ts b/src/vs/workbench/contrib/files/common/explorerService.ts index 27da4f1effe..54803e7e1ae 100644 --- a/src/vs/workbench/contrib/files/common/explorerService.ts +++ b/src/vs/workbench/contrib/files/common/explorerService.ts @@ -19,6 +19,7 @@ import { IExpression } from 'vs/base/common/glob'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditableData } from 'vs/workbench/common/views'; +import { toResource } from 'vs/workbench/common/editor'; function getFileEventsExcludes(configurationService: IConfigurationService, root?: URI): IExpression { const scope = root ? { resource: root } : undefined; @@ -193,7 +194,7 @@ export class ExplorerService implements IExplorerService { this.model.roots.forEach(r => r.forgetChildren()); if (this.view) { await this.view.refresh(true); - const resource = this.editorService.activeEditor ? this.editorService.activeEditor.resource : undefined; + const resource = toResource(this.editorService.activeEditor, { usePreferredResource: true }); const autoReveal = this.configurationService.getValue().explorer.autoReveal; if (reveal && resource && autoReveal) { diff --git a/src/vs/workbench/contrib/files/common/files.ts b/src/vs/workbench/contrib/files/common/files.ts index 4de94e9698d..d578edd56a9 100644 --- a/src/vs/workbench/contrib/files/common/files.ts +++ b/src/vs/workbench/contrib/files/common/files.ts @@ -263,6 +263,6 @@ export class OpenEditor implements IEditorIdentifier { } getResource(): URI | undefined { - return toResource(this.editor, { supportSideBySide: SideBySideEditor.PRIMARY }); + return toResource(this.editor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); } } diff --git a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts index ce2717a4f2a..a6255a0f345 100644 --- a/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts +++ b/src/vs/workbench/contrib/files/electron-sandbox/fileActions.contribution.ts @@ -22,6 +22,7 @@ import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { ResourceContextKey } from 'vs/workbench/common/resources'; import { appendToCommandPalette, appendEditorTitleContextMenuItem } from 'vs/workbench/contrib/files/browser/fileActions.contribution'; import { IExplorerService } from 'vs/workbench/contrib/files/common/files'; +import { SideBySideEditor, toResource } from 'vs/workbench/common/editor'; const REVEAL_IN_OS_COMMAND_ID = 'revealFileInOS'; const REVEAL_IN_OS_LABEL = isWindows ? nls.localize('revealInWindows', "Reveal in File Explorer") : isMacintosh ? nls.localize('revealInMac', "Reveal in Finder") : nls.localize('openContainer', "Open Containing Folder"); @@ -40,15 +41,17 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ } }); +const REVEAL_ACTIVE_FILE_IN_OS_COMMAND_ID = 'workbench.action.files.revealActiveFileInWindows'; + KeybindingsRegistry.registerCommandAndKeybindingRule({ weight: KeybindingWeight.WorkbenchContrib, when: undefined, primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_R), - id: 'workbench.action.files.revealActiveFileInWindows', + id: REVEAL_ACTIVE_FILE_IN_OS_COMMAND_ID, handler: (accessor: ServicesAccessor) => { const editorService = accessor.get(IEditorService); const activeInput = editorService.activeEditor; - const resource = activeInput ? activeInput.resource : null; + const resource = toResource(activeInput, { filterByScheme: Schemas.file, usePreferredResource: true, supportSideBySide: SideBySideEditor.PRIMARY }); const resources = resource ? [resource] : []; revealResourcesInOS(resources, accessor.get(INativeHostService), accessor.get(INotificationService), accessor.get(IWorkspaceContextService)); } diff --git a/src/vs/workbench/contrib/scm/browser/activity.ts b/src/vs/workbench/contrib/scm/browser/activity.ts index c2ef67dfb97..0287a9a1508 100644 --- a/src/vs/workbench/contrib/scm/browser/activity.ts +++ b/src/vs/workbench/contrib/scm/browser/activity.ts @@ -14,6 +14,7 @@ import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/c import { IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/workbench/services/statusbar/common/statusbar'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { toResource } from 'vs/workbench/common/editor'; function getCount(repository: ISCMRepository): number { if (typeof repository.provider.count === 'number') { @@ -56,11 +57,7 @@ export class SCMStatusController implements IWorkbenchContribution { } private tryFocusRepositoryBasedOnActiveEditor(): boolean { - if (!this.editorService.activeEditor) { - return false; - } - - const resource = this.editorService.activeEditor.resource; + const resource = toResource(this.editorService.activeEditor, { usePreferredResource: true }); if (!resource) { return false; diff --git a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts index 0220cf2a22e..0faeaf37f83 100644 --- a/src/vs/workbench/contrib/scm/browser/scmViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmViewPane.ts @@ -959,13 +959,7 @@ class ViewModel { return; } - const editor = this.editorService.activeEditor; - - if (!editor) { - return; - } - - const uri = toResource(editor, { supportSideBySide: SideBySideEditor.PRIMARY }); + const uri = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, usePreferredResource: true }); if (!uri) { return; diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index f534a3e85c4..9cecc8662c0 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -15,7 +15,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { untildify } from 'vs/base/common/labels'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { URI } from 'vs/base/common/uri'; -import { toLocalResource, dirname, basenameOrAuthority, isEqual } from 'vs/base/common/resources'; +import { toLocalResource, dirname, basenameOrAuthority } from 'vs/base/common/resources'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IFileService } from 'vs/platform/files/common/files'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -27,7 +27,7 @@ import { IModeService } from 'vs/editor/common/services/modeService'; import { localize } from 'vs/nls'; import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { IWorkbenchEditorConfiguration, IEditorInput, EditorInput } from 'vs/workbench/common/editor'; +import { IWorkbenchEditorConfiguration, IEditorInput, EditorInput, toResource } from 'vs/workbench/common/editor'; import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService'; import { Range, IRange } from 'vs/editor/common/core/range'; import { ThrottledDelayer } from 'vs/base/common/async'; @@ -49,6 +49,7 @@ import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsSe import { getIEditor } from 'vs/editor/browser/editorBrowser'; import { withNullAsUndefined } from 'vs/base/common/types'; import { Codicon, stripCodicons } from 'vs/base/common/codicons'; +import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; interface IAnythingQuickPickItem extends IPickerQuickAccessItem, IQuickPickItemWithResource { } @@ -173,7 +174,8 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider { - const file = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, filterByScheme: Schemas.file }); + const file = toResource(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY, filterByScheme: Schemas.file, usePreferredResource: true }); // Represented Filename this.updateRepresentedFilename(file?.fsPath); diff --git a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts index 680b8a562f6..f686ec565d7 100644 --- a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts @@ -7,7 +7,7 @@ import { URI as uri } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; import * as Types from 'vs/base/common/types'; import { Schemas } from 'vs/base/common/network'; -import { toResource } from 'vs/workbench/common/editor'; +import { SideBySideEditor, toResource } from 'vs/workbench/common/editor'; import { IStringDictionary, forEach, fromMap } from 'vs/base/common/collections'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; @@ -16,7 +16,6 @@ import { IWorkspaceFolder, IWorkspaceContextService, WorkbenchState } from 'vs/p import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/common/variableResolver'; import { isCodeEditor } from 'vs/editor/browser/editorBrowser'; -import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { IQuickInputService, IInputOptions, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput'; import { ConfiguredInput, IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IProcessEnvironment } from 'vs/base/common/platform'; @@ -52,11 +51,11 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR return context.getExecPath(); }, getFilePath: (): string | undefined => { - let activeEditor = editorService.activeEditor; - if (activeEditor instanceof DiffEditorInput) { - activeEditor = activeEditor.modifiedInput; - } - const fileResource = toResource(activeEditor, { filterByScheme: [Schemas.file, Schemas.userData, Schemas.vscodeRemote] }); + const fileResource = toResource(editorService.activeEditor, { + supportSideBySide: SideBySideEditor.PRIMARY, + filterByScheme: [Schemas.file, Schemas.userData, Schemas.vscodeRemote], + usePreferredResource: true + }); if (!fileResource) { return undefined; } diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 39ff228070e..ee8e7404591 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -877,7 +877,6 @@ export class EditorService extends Disposable implements EditorServiceImpl { // with different resource forms (e.g. path casing on Windows) const canonicalResource = this.asCanonicalEditorResource(preferredResource); - return this.createOrGetCached(canonicalResource, () => { // File @@ -970,11 +969,9 @@ export class EditorService extends Disposable implements EditorServiceImpl { } private toSideBySideLabel(leftInput: EditorInput, rightInput: EditorInput, divider: string): string | undefined { - const leftResource = leftInput.resource; - const rightResource = rightInput.resource; // Without any resource, do not try to compute a label - if (!leftResource || !rightResource) { + if (!leftInput.resource || !rightInput.resource) { return undefined; } @@ -982,7 +979,7 @@ export class EditorService extends Disposable implements EditorServiceImpl { // by adding the relative path of both inputs to the label. This // makes it easier to understand a file-based comparison. if (this.fileEditorInputFactory.isFileEditorInput(leftInput) && this.fileEditorInputFactory.isFileEditorInput(rightInput)) { - return `${this.labelService.getUriLabel(leftResource, { relative: true })} ${divider} ${this.labelService.getUriLabel(rightResource, { relative: true })}`; + return `${this.labelService.getUriLabel(leftInput.preferredResource, { relative: true })} ${divider} ${this.labelService.getUriLabel(rightInput.preferredResource, { relative: true })}`; } // Signal back that the label should be computed from within the editor diff --git a/src/vs/workbench/services/editor/common/editorOpenWith.ts b/src/vs/workbench/services/editor/common/editorOpenWith.ts index 807464f51f8..c278c5de03b 100644 --- a/src/vs/workbench/services/editor/common/editorOpenWith.ts +++ b/src/vs/workbench/services/editor/common/editorOpenWith.ts @@ -9,7 +9,7 @@ import { IConfigurationNode, IConfigurationRegistry, Extensions } from 'vs/platf import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; import { Registry } from 'vs/platform/registry/common/platform'; import { ICustomEditorInfo, IEditorService, IOpenEditorOverrideHandler, IOpenEditorOverrideEntry } from 'vs/workbench/services/editor/common/editorService'; -import { IEditorInput, IEditorPane, IEditorInputFactoryRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor'; +import { IEditorInput, IEditorPane, IEditorInputFactoryRegistry, Extensions as EditorExtensions, toResource } from 'vs/workbench/common/editor'; import { ITextEditorOptions, IEditorOptions } from 'vs/platform/editor/common/editor'; import { IEditorGroup, OpenEditorContext } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -37,7 +37,7 @@ export async function openEditorWith( configurationService: IConfigurationService, quickInputService: IQuickInputService, ): Promise { - const resource = input.resource; + const resource = toResource(input, { usePreferredResource: true }); if (!resource) { return; } @@ -146,11 +146,12 @@ export function getAllAvailableEditors( overrides.unshift([ { open: (input: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup) => { - if (!input.resource) { + const resource = toResource(input, { usePreferredResource: true }); + if (!resource) { return; } - const fileEditorInput = editorService.createEditorInput({ resource: input.resource, forceFile: true }); + const fileEditorInput = editorService.createEditorInput({ resource, forceFile: true }); const textOptions: IEditorOptions | ITextEditorOptions = options ? { ...options, override: false } : { override: false }; return { override: editorService.openEditor(fileEditorInput, textOptions, group) }; } diff --git a/src/vs/workbench/services/history/browser/history.ts b/src/vs/workbench/services/history/browser/history.ts index b3d33f213d2..97e4521adc7 100644 --- a/src/vs/workbench/services/history/browser/history.ts +++ b/src/vs/workbench/services/history/browser/history.ts @@ -32,10 +32,10 @@ import { addDisposableListener, EventType, EventHelper } from 'vs/base/browser/d import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces'; import { Schemas } from 'vs/base/common/network'; import { onUnexpectedError } from 'vs/base/common/errors'; -import { extUri } from 'vs/base/common/resources'; import { IdleValue } from 'vs/base/common/async'; import { ResourceGlobMatcher } from 'vs/workbench/common/resources'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; +import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; /** * Stores the selection & view state of an editor and allows to compare it to other selection states. @@ -119,7 +119,8 @@ export class HistoryService extends Disposable implements IHistoryService { @IInstantiationService private readonly instantiationService: IInstantiationService, @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IPathService private readonly pathService: IPathService + @IPathService private readonly pathService: IPathService, + @IUriIdentityService private readonly uriIdentityService: IUriIdentityService ) { super(); @@ -581,7 +582,7 @@ export class HistoryService extends Disposable implements IHistoryService { const resourceEditorInputA = arg1 as IResourceEditorInput; const resourceEditorInputB = inputB as IResourceEditorInput; - return resourceEditorInputA && resourceEditorInputB && extUri.isEqual(resourceEditorInputA.resource, resourceEditorInputB.resource); + return resourceEditorInputA && resourceEditorInputB && this.uriIdentityService.extUri.isEqual(resourceEditorInputA.resource, resourceEditorInputB.resource); } private matchesFile(resource: URI, arg2: IEditorInput | IResourceEditorInput | FileChangesEvent): boolean { @@ -599,12 +600,12 @@ export class HistoryService extends Disposable implements IHistoryService { return false; // make sure to only check this when workbench has restored (for https://github.com/microsoft/vscode/issues/48275) } - return extUri.isEqual(inputResource, resource); + return this.uriIdentityService.extUri.isEqual(inputResource, resource); } const resourceEditorInput = arg2 as IResourceEditorInput; - return extUri.isEqual(resourceEditorInput?.resource, resource); + return this.uriIdentityService.extUri.isEqual(resourceEditorInput?.resource, resource); } //#endregion @@ -1001,7 +1002,7 @@ export class HistoryService extends Disposable implements IHistoryService { for (const input of this.getHistory()) { let resource: URI | undefined; if (input instanceof EditorInput) { - resource = toResource(input, { filterByScheme }); + resource = toResource(input, { filterByScheme, usePreferredResource: true }); } else { resource = (input as IResourceEditorInput).resource; } diff --git a/src/vs/workbench/test/browser/parts/editor/editor.test.ts b/src/vs/workbench/test/browser/parts/editor/editor.test.ts index 74821dc414f..c6ae52f7bf3 100644 --- a/src/vs/workbench/test/browser/parts/editor/editor.test.ts +++ b/src/vs/workbench/test/browser/parts/editor/editor.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { toResource, SideBySideEditor } from 'vs/workbench/common/editor'; +import { toResource, SideBySideEditor, IEditorInputWithPreferredResource } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; import { URI } from 'vs/base/common/uri'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -12,6 +12,13 @@ import { workbenchInstantiationService, TestServiceAccessor, TestEditorInput } f import { Schemas } from 'vs/base/common/network'; import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/untitledTextEditorInput'; +export class TestEditorInputWithPreferredResource extends TestEditorInput implements IEditorInputWithPreferredResource { + + constructor(resource: URI, public preferredResource: URI, typeId: string) { + super(resource, typeId); + } +} + suite('Workbench editor', () => { let instantiationService: IInstantiationService; @@ -71,5 +78,12 @@ suite('Workbench editor', () => { assert.equal((toResource(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource.toString()); assert.equal((toResource(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: Schemas.untitled }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource.toString()); assert.equal((toResource(diffEditorInput, { supportSideBySide: SideBySideEditor.BOTH, filterByScheme: [Schemas.file, Schemas.untitled] }) as { primary: URI, secondary: URI }).secondary.toString(), untitled.resource.toString()); + + const resource = URI.file('/some/path.txt'); + const preferredResource = URI.file('/some/PATH.txt'); + const fileWithPreferredResource = new TestEditorInputWithPreferredResource(URI.file('/some/path.txt'), URI.file('/some/PATH.txt'), 'editorResourceFileTest'); + + assert.equal(toResource(fileWithPreferredResource)?.toString(), resource.toString()); + assert.equal(toResource(fileWithPreferredResource, { usePreferredResource: true })?.toString(), preferredResource.toString()); }); }); -- GitLab