diff --git a/src/vs/workbench/services/uriIdentity/common/uriIdentityService.ts b/src/vs/workbench/services/uriIdentity/common/uriIdentityService.ts index b0b670bdc81..1b2fc624c9c 100644 --- a/src/vs/workbench/services/uriIdentity/common/uriIdentityService.ts +++ b/src/vs/workbench/services/uriIdentity/common/uriIdentityService.ts @@ -6,9 +6,11 @@ import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { URI } from 'vs/base/common/uri'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IFileService, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; +import { IFileService, FileSystemProviderCapabilities, IFileSystemProviderCapabilitiesChangeEvent, IFileSystemProviderRegistrationEvent } from 'vs/platform/files/common/files'; import { ExtUri, IExtUri, normalizePath } from 'vs/base/common/resources'; import { SkipList } from 'vs/base/common/skipList'; +import { Event } from 'vs/base/common/event'; +import { DisposableStore } from 'vs/base/common/lifecycle'; class Entry { static _clock = 0; @@ -26,27 +28,45 @@ export class UriIdentityService implements IUriIdentityService { readonly extUri: IExtUri; + private readonly _dispooables = new DisposableStore(); private readonly _canonicalUris: SkipList; private readonly _limit = 2 ** 16; constructor(@IFileService private readonly _fileService: IFileService) { - // assume path casing matters unless the file system provider spec'ed the opposite + const schemeIgnoresPathCasingCache = new Map(); + + // assume path casing matters unless the file system provider spec'ed the opposite. + // for all other cases path casing matters, e.g for + // * virtual documents + // * in-memory uris + // * all kind of "private" schemes const ignorePathCasing = (uri: URI): boolean => { - // perf@jrieken cache this information - if (this._fileService.canHandleResource(uri)) { - return !this._fileService.hasCapability(uri, FileSystemProviderCapabilities.PathCaseSensitive); + let ignorePathCasing = schemeIgnoresPathCasingCache.get(uri.scheme); + if (ignorePathCasing === undefined) { + // retrieve once and then case per scheme until a change happens + ignorePathCasing = _fileService.canHandleResource(uri) && !this._fileService.hasCapability(uri, FileSystemProviderCapabilities.PathCaseSensitive); + schemeIgnoresPathCasingCache.set(uri.scheme, ignorePathCasing); } - // this defaults to false which is a good default for - // * virtual documents - // * in-memory uris - // * all kind of "private" schemes - return false; + return ignorePathCasing; }; + this._dispooables.add(Event.any( + _fileService.onDidChangeFileSystemProviderRegistrations, + _fileService.onDidChangeFileSystemProviderCapabilities + )(e => { + // remove from cache + schemeIgnoresPathCasingCache.delete(e.scheme); + })); + this.extUri = new ExtUri(ignorePathCasing); this._canonicalUris = new SkipList((a, b) => this.extUri.compare(a, b, true), this._limit); } + dispose(): void { + this._dispooables.dispose(); + this._canonicalUris.clear(); + } + asCanonicalUri(uri: URI): URI { // (1) normalize URI diff --git a/src/vs/workbench/services/uriIdentity/test/common/uriIdentityService.test.ts b/src/vs/workbench/services/uriIdentity/test/common/uriIdentityService.test.ts index ea422ca1a14..683fb6675d7 100644 --- a/src/vs/workbench/services/uriIdentity/test/common/uriIdentityService.test.ts +++ b/src/vs/workbench/services/uriIdentity/test/common/uriIdentityService.test.ts @@ -8,11 +8,15 @@ import { UriIdentityService } from 'vs/workbench/services/uriIdentity/common/uri import { mock } from 'vs/workbench/test/common/workbenchTestServices'; import { IFileService, FileSystemProviderCapabilities } from 'vs/platform/files/common/files'; import { URI } from 'vs/base/common/uri'; +import { Event } from 'vs/base/common/event'; suite('URI Identity', function () { class FakeFileService extends mock() { + onDidChangeFileSystemProviderCapabilities = Event.None; + onDidChangeFileSystemProviderRegistrations = Event.None; + constructor(readonly data: Map) { super(); }