@@ -8,8 +8,8 @@ import { URI } from '../../../base/common/uri.js';
88import { InstantiationType , registerSingleton } from '../../instantiation/common/extensions.js' ;
99import { IFileService , FileSystemProviderCapabilities , IFileSystemProviderCapabilitiesChangeEvent , IFileSystemProviderRegistrationEvent } from '../../files/common/files.js' ;
1010import { ExtUri , IExtUri , normalizePath } from '../../../base/common/resources.js' ;
11- import { Event , Emitter } from '../../../base/common/event.js' ;
12- import { Disposable , toDisposable } from '../../../base/common/lifecycle.js' ;
11+ import { Event } from '../../../base/common/event.js' ;
12+ import { DisposableStore } from '../../../base/common/lifecycle.js' ;
1313import { quickSelect } from '../../../base/common/arrays.js' ;
1414
1515class Entry {
@@ -22,95 +22,62 @@ class Entry {
2222 }
2323}
2424
25- interface IFileSystemCasingChangedEvent {
26- scheme : string ;
27- }
28-
29- class PathCasingCache extends Disposable {
30- private readonly _cache = new Map < string , boolean > ( ) ;
31-
32- private _onFileSystemCasingChanged : Emitter < IFileSystemCasingChangedEvent > ;
33- readonly onFileSystemCasingChanged : Event < IFileSystemCasingChangedEvent > ;
34-
35- constructor ( private readonly _fileService : IFileService ) {
36- super ( ) ;
37-
38- this . _onFileSystemCasingChanged = this . _register ( new Emitter < IFileSystemCasingChangedEvent > ( ) ) ;
39- this . onFileSystemCasingChanged = this . _onFileSystemCasingChanged . event ;
40-
41- this . _register ( Event . any <
42- | IFileSystemProviderCapabilitiesChangeEvent
43- | IFileSystemProviderRegistrationEvent
44- > (
45- _fileService . onDidChangeFileSystemProviderRegistrations ,
46- _fileService . onDidChangeFileSystemProviderCapabilities
47- ) ( e => this . _handleFileSystemProviderChangeEvent ( e ) ) ) ;
48- }
49-
50- private _calculateIgnorePathCasing ( scheme : string ) : boolean {
51- const uri = URI . from ( { scheme } ) ;
52- return this . _fileService . hasProvider ( uri ) &&
53- ! this . _fileService . hasCapability ( uri , FileSystemProviderCapabilities . PathCaseSensitive ) ;
54- }
55-
56- private _handleFileSystemProviderChangeEvent (
57- event :
58- | IFileSystemProviderRegistrationEvent
59- | IFileSystemProviderCapabilitiesChangeEvent ) {
60- const currentCasing = this . _cache . get ( event . scheme ) ;
61- if ( currentCasing === undefined ) {
62- return ;
63- }
64- const newCasing = this . _calculateIgnorePathCasing ( event . scheme ) ;
65- if ( currentCasing === newCasing ) {
66- return ;
67- }
68- this . _cache . set ( event . scheme , newCasing ) ;
69- this . _onFileSystemCasingChanged . fire ( { scheme : event . scheme } ) ;
70- }
71-
72- public shouldIgnorePathCasing ( uri : URI ) : boolean {
73- const cachedValue = this . _cache . get ( uri . scheme ) ;
74- if ( cachedValue !== undefined ) {
75- return cachedValue ;
76- }
77-
78- const ignorePathCasing = this . _calculateIgnorePathCasing ( uri . scheme ) ;
79- this . _cache . set ( uri . scheme , ignorePathCasing ) ;
80- return ignorePathCasing ;
81- }
82- }
83-
84- export class UriIdentityService extends Disposable implements IUriIdentityService {
25+ export class UriIdentityService implements IUriIdentityService {
8526
8627 declare readonly _serviceBrand : undefined ;
8728
8829 readonly extUri : IExtUri ;
8930
90- private readonly _pathCasingCache : PathCasingCache ;
31+ private readonly _dispooables = new DisposableStore ( ) ;
9132 private readonly _canonicalUris : Map < string , Entry > ;
9233 private readonly _limit = 2 ** 16 ;
9334
9435 constructor ( @IFileService private readonly _fileService : IFileService ) {
95- super ( ) ;
96-
97- this . _pathCasingCache = this . _register ( new PathCasingCache ( this . _fileService ) ) ;
9836
99- this . _register ( this . _pathCasingCache . onFileSystemCasingChanged (
100- e => this . _handleFileSystemCasingChanged ( e ) ) ) ;
37+ const schemeIgnoresPathCasingCache = new Map < string , boolean > ( ) ;
38+
39+ // assume path casing matters unless the file system provider spec'ed the opposite.
40+ // for all other cases path casing matters, e.g for
41+ // * virtual documents
42+ // * in-memory uris
43+ // * all kind of "private" schemes
44+ const ignorePathCasing = ( uri : URI ) : boolean => {
45+ let ignorePathCasing = schemeIgnoresPathCasingCache . get ( uri . scheme ) ;
46+ if ( ignorePathCasing === undefined ) {
47+ // retrieve once and then case per scheme until a change happens
48+ ignorePathCasing = _fileService . hasProvider ( uri ) && ! this . _fileService . hasCapability ( uri , FileSystemProviderCapabilities . PathCaseSensitive ) ;
49+ schemeIgnoresPathCasingCache . set ( uri . scheme , ignorePathCasing ) ;
50+ }
51+ return ignorePathCasing ;
52+ } ;
53+ this . _dispooables . add ( Event . any < IFileSystemProviderCapabilitiesChangeEvent | IFileSystemProviderRegistrationEvent > (
54+ _fileService . onDidChangeFileSystemProviderRegistrations ,
55+ _fileService . onDidChangeFileSystemProviderCapabilities
56+ ) ( e => {
57+ const oldIgnorePathCasingValue = schemeIgnoresPathCasingCache . get ( e . scheme ) ;
58+ if ( oldIgnorePathCasingValue === undefined ) {
59+ return ;
60+ }
61+ schemeIgnoresPathCasingCache . delete ( e . scheme ) ;
62+ const newIgnorePathCasingValue = ignorePathCasing ( URI . from ( { scheme : e . scheme } ) ) ;
63+ if ( newIgnorePathCasingValue === newIgnorePathCasingValue ) {
64+ return ;
65+ }
66+ for ( const [ key , entry ] of this . _canonicalUris . entries ( ) ) {
67+ if ( entry . uri . scheme !== e . scheme ) {
68+ continue ;
69+ }
70+ this . _canonicalUris . delete ( key ) ;
71+ }
72+ } ) ) ;
10173
102- this . extUri = new ExtUri ( uri => this . _pathCasingCache . shouldIgnorePathCasing ( uri ) ) ;
74+ this . extUri = new ExtUri ( ignorePathCasing ) ;
10375 this . _canonicalUris = new Map ( ) ;
104- this . _register ( toDisposable ( ( ) => this . _canonicalUris . clear ( ) ) ) ;
10576 }
10677
107- private _handleFileSystemCasingChanged ( e : IFileSystemCasingChangedEvent ) : void {
108- for ( const [ key , entry ] of this . _canonicalUris . entries ( ) ) {
109- if ( entry . uri . scheme !== e . scheme ) {
110- continue ;
111- }
112- this . _canonicalUris . delete ( key ) ;
113- }
78+ dispose ( ) : void {
79+ this . _dispooables . dispose ( ) ;
80+ this . _canonicalUris . clear ( ) ;
11481 }
11582
11683 asCanonicalUri ( uri : URI ) : URI {
0 commit comments