-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Description
Background: a while ago we introduced canonical resources as a way to solve issues on file systems that are case-preserving but case-insensitive. For example consider files:
some/path/FILE.txtsome/path/file.txt
Previously we would open 2 editors which pointed to the same file but with canonical URIs, we take the first file path into memory and normalize all subsequent ones that only differ in case to that form.
However, this can lead to issues where we we use editor.resource (e.g. from the active editor) and methods such as isEqual or relativePath or isEqualOrParent because the editor.resource will be canonical and may have a different form compared to the one to check against based on whoever first managed to open the editor with that URI (e.g. an extension).
As a solution we added a IURIIdentityService that can compare canonical URIs with others (e.g. IURIIdentityService.extUri.isEqual). Under the hood, this service will ignore casing if the file system provider for the scheme of the URI declares as such.
This issue is to report that some code is comparing URIs from the active editor without taking the URI identity into account. If an extension decides to open an editor with casing that is not as expected, this code will fail to work. Please review:
vscode/src/vs/workbench/contrib/timeline/browser/timelinePane.ts
Lines 341 to 374 in b1c54c1
| private onActiveEditorChanged() { | |
| if (!this.followActiveEditor) { | |
| return; | |
| } | |
| const uri = EditorResourceAccessor.getOriginalUri(this.editorService.activeEditor, { supportSideBySide: SideBySideEditor.PRIMARY }); | |
| if ((uri?.toString(true) === this.uri?.toString(true) && uri !== undefined) || | |
| // Fallback to match on fsPath if we are dealing with files or git schemes | |
| (uri?.fsPath === this.uri?.fsPath && (uri?.scheme === Schemas.file || uri?.scheme === 'git') && (this.uri?.scheme === Schemas.file || this.uri?.scheme === 'git'))) { | |
| // If the uri hasn't changed, make sure we have valid caches | |
| for (const source of this.timelineService.getSources()) { | |
| if (this.excludedSources.has(source.id)) { | |
| continue; | |
| } | |
| const timeline = this.timelinesBySource.get(source.id); | |
| if (timeline !== undefined && !timeline.stale) { | |
| continue; | |
| } | |
| if (timeline !== undefined) { | |
| this.updateTimeline(timeline, timeline.requiresReset); | |
| } else { | |
| this.loadTimelineForSource(source.id, uri, true); | |
| } | |
| } | |
| return; | |
| } | |
| this.setUriCore(uri, false); | |
| } |
PS: I recently added EditorResourceAccessor.getOriginalUri and EditorResourceAccessor.getCanonicalUri as a way to explicitly ask for either the canonical resource of an editor or the original URI the editor was created with. Once you adopted IURIIdentityService you can safely go back to editor.resource (which is the canonical form always). A use case for getOriginalUri is for example when presenting the URI to a user in a label. In that case we never want the canonical form.
//cc @jrieken