@@ -43,7 +43,7 @@ namespace ts.server.typingsInstaller {
43
43
private readonly packageNameToTypingLocation : Map < JsTyping . CachedTyping > = createMap < JsTyping . CachedTyping > ( ) ;
44
44
private readonly missingTypingsSet : Map < true > = createMap < true > ( ) ;
45
45
private readonly knownCachesSet : Map < true > = createMap < true > ( ) ;
46
- private readonly projectWatchers : Map < FileWatcher [ ] > = createMap < FileWatcher [ ] > ( ) ;
46
+ private readonly projectWatchers = createMap < Map < FileWatcher > > ( ) ;
47
47
private safeList : JsTyping . SafeList | undefined ;
48
48
readonly pendingRunRequests : PendingRequest [ ] = [ ] ;
49
49
@@ -80,10 +80,7 @@ namespace ts.server.typingsInstaller {
80
80
}
81
81
return ;
82
82
}
83
- for ( const w of watchers ) {
84
- w . close ( ) ;
85
- }
86
-
83
+ clearMap ( watchers , closeFileWatcher ) ;
87
84
this . projectWatchers . delete ( projectName ) ;
88
85
89
86
if ( this . log . isEnabled ( ) ) {
@@ -345,27 +342,49 @@ namespace ts.server.typingsInstaller {
345
342
346
343
private watchFiles ( projectName : string , files : string [ ] ) {
347
344
if ( ! files . length ) {
345
+ // shut down existing watchers
346
+ this . closeWatchers ( projectName ) ;
348
347
return ;
349
348
}
350
- // shut down existing watchers
351
- this . closeWatchers ( projectName ) ;
349
+
350
+ let watchers = this . projectWatchers . get ( projectName ) ;
351
+ if ( ! watchers ) {
352
+ watchers = createMap ( ) ;
353
+ this . projectWatchers . set ( projectName , watchers ) ;
354
+ }
352
355
353
356
// handler should be invoked once for the entire set of files since it will trigger full rediscovery of typings
354
357
let isInvoked = false ;
355
- const watchers : FileWatcher [ ] = [ ] ;
356
- for ( const file of files ) {
357
- const w = this . installTypingHost . watchFile ( file , f => {
358
- if ( this . log . isEnabled ( ) ) {
359
- this . log . writeLine ( `Got FS notification for ${ f } , handler is already invoked '${ isInvoked } '` ) ;
360
- }
361
- if ( ! isInvoked ) {
362
- this . sendResponse ( { projectName, kind : ActionInvalidate } ) ;
363
- isInvoked = true ;
364
- }
365
- } , /*pollingInterval*/ 2000 ) ;
366
- watchers . push ( w ) ;
367
- }
368
- this . projectWatchers . set ( projectName , watchers ) ;
358
+ const isLoggingEnabled = this . log . isEnabled ( ) ;
359
+ mutateMap (
360
+ watchers ,
361
+ arrayToSet ( files ) ,
362
+ {
363
+ // Watch the missing files
364
+ createNewValue : file => {
365
+ if ( isLoggingEnabled ) {
366
+ this . log . writeLine ( `FileWatcher:: Added:: WatchInfo: ${ file } ` ) ;
367
+ }
368
+ const watcher = this . installTypingHost . watchFile ( file , ( f , eventKind ) => {
369
+ if ( isLoggingEnabled ) {
370
+ this . log . writeLine ( `FileWatcher:: Triggered with ${ f } eventKind: ${ FileWatcherEventKind [ eventKind ] } :: WatchInfo: ${ file } :: handler is already invoked '${ isInvoked } '` ) ;
371
+ }
372
+ if ( ! isInvoked ) {
373
+ this . sendResponse ( { projectName, kind : ActionInvalidate } ) ;
374
+ isInvoked = true ;
375
+ }
376
+ } , /*pollingInterval*/ 2000 ) ;
377
+ return isLoggingEnabled ? {
378
+ close : ( ) => {
379
+ this . log . writeLine ( `FileWatcher:: Closed:: WatchInfo: ${ file } ` ) ;
380
+ }
381
+ } : watcher ;
382
+ } ,
383
+ // Files that are no longer missing (e.g. because they are no longer required)
384
+ // should no longer be watched.
385
+ onDeleteValue : closeFileWatcher
386
+ }
387
+ ) ;
369
388
}
370
389
371
390
private createSetTypings ( request : DiscoverTypings , typings : string [ ] ) : SetTypings {
0 commit comments