@@ -327,10 +327,12 @@ namespace ts.server {
327327 this . lsHost = undefined ;
328328
329329 // Clean up file watchers waiting for missing files
330- cleanExistingMap ( this . missingFilesMap , ( missingFilePath , fileWatcher ) => {
331- this . projectService . closeFileWatcher ( WatchType . MissingFilePath , this , missingFilePath , fileWatcher , WatcherCloseReason . ProjectClose ) ;
332- } ) ;
333- this . missingFilesMap = undefined ;
330+ if ( this . missingFilesMap ) {
331+ clearMap ( this . missingFilesMap , ( missingFilePath , fileWatcher ) => {
332+ this . projectService . closeFileWatcher ( WatchType . MissingFilePath , this , missingFilePath , fileWatcher , WatcherCloseReason . ProjectClose ) ;
333+ } ) ;
334+ this . missingFilesMap = undefined ;
335+ }
334336
335337 // signal language service to release source files acquired from document registry
336338 this . languageService . dispose ( ) ;
@@ -642,34 +644,37 @@ namespace ts.server {
642644 const missingFilePaths = this . program . getMissingFilePaths ( ) ;
643645 const newMissingFilePathMap = arrayToSet ( missingFilePaths ) ;
644646 // Update the missing file paths watcher
645- this . missingFilesMap = mutateExistingMapWithNewSet (
646- this . missingFilesMap , newMissingFilePathMap ,
647- // Watch the missing files
648- missingFilePath => {
649- const fileWatcher = this . projectService . addFileWatcher (
650- WatchType . MissingFilePath , this , missingFilePath ,
651- ( filename , eventKind ) => {
652- if ( eventKind === FileWatcherEventKind . Created && this . missingFilesMap . has ( missingFilePath ) ) {
653- this . missingFilesMap . delete ( missingFilePath ) ;
654- this . projectService . closeFileWatcher ( WatchType . MissingFilePath , this , missingFilePath , fileWatcher , WatcherCloseReason . FileCreated ) ;
655-
656- if ( this . projectKind === ProjectKind . Configured ) {
657- const absoluteNormalizedPath = getNormalizedAbsolutePath ( filename , getDirectoryPath ( missingFilePath ) ) ;
658- ( this . lsHost . host as CachedServerHost ) . addOrDeleteFileOrFolder ( toNormalizedPath ( absoluteNormalizedPath ) ) ;
647+ mutateMap (
648+ this . missingFilesMap || ( this . missingFilesMap = createMap ( ) ) ,
649+ newMissingFilePathMap ,
650+ {
651+ // Watch the missing files
652+ createNewValue : missingFilePath => {
653+ const fileWatcher = this . projectService . addFileWatcher (
654+ WatchType . MissingFilePath , this , missingFilePath ,
655+ ( filename , eventKind ) => {
656+ if ( eventKind === FileWatcherEventKind . Created && this . missingFilesMap . has ( missingFilePath ) ) {
657+ this . missingFilesMap . delete ( missingFilePath ) ;
658+ this . projectService . closeFileWatcher ( WatchType . MissingFilePath , this , missingFilePath , fileWatcher , WatcherCloseReason . FileCreated ) ;
659+
660+ if ( this . projectKind === ProjectKind . Configured ) {
661+ const absoluteNormalizedPath = getNormalizedAbsolutePath ( filename , getDirectoryPath ( missingFilePath ) ) ;
662+ ( this . lsHost . host as CachedServerHost ) . addOrDeleteFileOrFolder ( toNormalizedPath ( absoluteNormalizedPath ) ) ;
663+ }
664+
665+ // When a missing file is created, we should update the graph.
666+ this . markAsDirty ( ) ;
667+ this . projectService . delayUpdateProjectGraphAndInferredProjectsRefresh ( this ) ;
659668 }
660-
661- // When a missing file is created, we should update the graph.
662- this . markAsDirty ( ) ;
663- this . projectService . delayUpdateProjectGraphAndInferredProjectsRefresh ( this ) ;
664669 }
665- }
666- ) ;
667- return fileWatcher ;
668- } ,
669- // Files that are no longer missing (e.g. because they are no longer required)
670- // should no longer be watched.
671- ( missingFilePath , fileWatcher ) => {
672- this . projectService . closeFileWatcher ( WatchType . MissingFilePath , this , missingFilePath , fileWatcher , WatcherCloseReason . NotNeeded ) ;
670+ ) ;
671+ return fileWatcher ;
672+ } ,
673+ // Files that are no longer missing (e.g. because they are no longer required)
674+ // should no longer be watched.
675+ onDeleteExistingValue : ( missingFilePath , fileWatcher ) => {
676+ this . projectService . closeFileWatcher ( WatchType . MissingFilePath , this , missingFilePath , fileWatcher , WatcherCloseReason . NotNeeded ) ;
677+ }
673678 }
674679 ) ;
675680 }
@@ -970,7 +975,10 @@ namespace ts.server {
970975 }
971976 }
972977
973- type WildCardDirectoryWatchers = { watcher : FileWatcher , recursive : boolean } ;
978+ interface WildcardDirectoryWatcher {
979+ watcher : FileWatcher ;
980+ flags : WatchDirectoryFlags ;
981+ }
974982
975983 /**
976984 * If a file is opened, the server will look for a tsconfig (or jsconfig)
@@ -981,7 +989,7 @@ namespace ts.server {
981989 private typeAcquisition : TypeAcquisition ;
982990 /* @internal */
983991 configFileWatcher : FileWatcher ;
984- private directoriesWatchedForWildcards : Map < WildCardDirectoryWatchers > | undefined ;
992+ private directoriesWatchedForWildcards : Map < WildcardDirectoryWatcher > | undefined ;
985993 private typeRootsWatchers : Map < FileWatcher > | undefined ;
986994 readonly canonicalConfigFilePath : NormalizedPath ;
987995
@@ -1136,70 +1144,72 @@ namespace ts.server {
11361144 }
11371145
11381146 watchWildcards ( wildcardDirectories : Map < WatchDirectoryFlags > ) {
1139- this . directoriesWatchedForWildcards = mutateExistingMap (
1140- this . directoriesWatchedForWildcards , wildcardDirectories ,
1141- // Watcher is same if the recursive flags match
1142- ( { recursive : existingRecursive } , flag ) => {
1143- // If the recursive dont match, it needs update
1144- const recursive = ( flag & WatchDirectoryFlags . Recursive ) !== 0 ;
1145- return existingRecursive !== recursive ;
1146- } ,
1147- // Create new watch and recursive info
1148- ( directory , flag ) => {
1149- const recursive = ( flag & WatchDirectoryFlags . Recursive ) !== 0 ;
1150- return {
1151- watcher : this . projectService . addDirectoryWatcher (
1152- WatchType . WildCardDirectories , this , directory ,
1153- path => this . projectService . onFileAddOrRemoveInWatchedDirectoryOfProject ( this , path ) ,
1154- recursive
1155- ) ,
1156- recursive
1157- } ;
1158- } ,
1159- // Close existing watch thats not needed any more
1160- ( directory , { watcher, recursive } ) => this . projectService . closeDirectoryWatcher (
1161- WatchType . WildCardDirectories , this , directory , watcher , recursive , WatcherCloseReason . NotNeeded
1162- ) ,
1163- // Close existing watch that doesnt match in recursive flag
1164- ( directory , { watcher, recursive } ) => this . projectService . closeDirectoryWatcher (
1165- WatchType . WildCardDirectories , this , directory , watcher , recursive , WatcherCloseReason . RecursiveChanged
1166- )
1147+ mutateMap (
1148+ this . directoriesWatchedForWildcards || ( this . directoriesWatchedForWildcards = createMap ( ) ) ,
1149+ wildcardDirectories ,
1150+ {
1151+ // Watcher is same if the recursive flags match
1152+ isSameValue : ( { flags : existingFlags } , flags ) => existingFlags !== flags ,
1153+ // Create new watch and recursive info
1154+ createNewValue : ( directory , flags ) => {
1155+ return {
1156+ watcher : this . projectService . addDirectoryWatcher (
1157+ WatchType . WildCardDirectories , this , directory ,
1158+ path => this . projectService . onFileAddOrRemoveInWatchedDirectoryOfProject ( this , path ) ,
1159+ flags
1160+ ) ,
1161+ flags
1162+ } ;
1163+ } ,
1164+ // Close existing watch thats not needed any more or doesnt match recursive flags
1165+ onDeleteExistingValue : ( directory , wildcardDirectoryWatcher , isNotSame ) =>
1166+ this . closeWildcardDirectoryWatcher ( directory , wildcardDirectoryWatcher , isNotSame ? WatcherCloseReason . RecursiveChanged : WatcherCloseReason . NotNeeded ) ,
1167+ }
11671168 ) ;
11681169 }
11691170
1171+ private closeWildcardDirectoryWatcher ( directory : string , { watcher, flags } : WildcardDirectoryWatcher , closeReason : WatcherCloseReason ) {
1172+ this . projectService . closeDirectoryWatcher ( WatchType . WildCardDirectories , this , directory , watcher , flags , closeReason ) ;
1173+ }
1174+
11701175 stopWatchingWildCards ( reason : WatcherCloseReason ) {
1171- cleanExistingMap (
1172- this . directoriesWatchedForWildcards ,
1173- ( directory , { watcher , recursive } ) =>
1174- this . projectService . closeDirectoryWatcher ( WatchType . WildCardDirectories , this ,
1175- directory , watcher , recursive , reason )
1176- ) ;
1177- this . directoriesWatchedForWildcards = undefined ;
1176+ if ( this . directoriesWatchedForWildcards ) {
1177+ clearMap (
1178+ this . directoriesWatchedForWildcards ,
1179+ ( directory , wildcardDirectoryWatcher ) => this . closeWildcardDirectoryWatcher ( directory , wildcardDirectoryWatcher , reason )
1180+ ) ;
1181+ this . directoriesWatchedForWildcards = undefined ;
1182+ }
11781183 }
11791184
11801185 watchTypeRoots ( ) {
11811186 const newTypeRoots = arrayToSet ( this . getEffectiveTypeRoots ( ) , dir => this . projectService . toCanonicalFileName ( dir ) ) ;
1182- this . typeRootsWatchers = mutateExistingMapWithNewSet (
1183- this . typeRootsWatchers , newTypeRoots ,
1184- // Create new watch
1185- root => this . projectService . addDirectoryWatcher ( WatchType . TypeRoot , this , root ,
1186- path => this . projectService . onTypeRootFileChanged ( this , path ) , /*recursive*/ false
1187- ) ,
1188- // Close existing watch thats not needed any more
1189- ( directory , watcher ) => this . projectService . closeDirectoryWatcher (
1190- WatchType . TypeRoot , this , directory , watcher , /*recursive*/ false , WatcherCloseReason . NotNeeded
1191- )
1187+ mutateMap (
1188+ this . typeRootsWatchers || ( this . typeRootsWatchers = createMap ( ) ) ,
1189+ newTypeRoots ,
1190+ {
1191+ // Create new watch
1192+ createNewValue : root => this . projectService . addDirectoryWatcher ( WatchType . TypeRoot , this , root ,
1193+ path => this . projectService . onTypeRootFileChanged ( this , path ) , WatchDirectoryFlags . None
1194+ ) ,
1195+ // Close existing watch thats not needed any more
1196+ onDeleteExistingValue : ( directory , watcher ) => this . projectService . closeDirectoryWatcher (
1197+ WatchType . TypeRoot , this , directory , watcher , WatchDirectoryFlags . None , WatcherCloseReason . NotNeeded
1198+ )
1199+ }
11921200 ) ;
11931201 }
11941202
11951203 stopWatchingTypeRoots ( reason : WatcherCloseReason ) {
1196- cleanExistingMap (
1197- this . typeRootsWatchers ,
1198- ( directory , watcher ) =>
1199- this . projectService . closeDirectoryWatcher ( WatchType . TypeRoot , this ,
1200- directory , watcher , /*recursive*/ false , reason )
1201- ) ;
1202- this . typeRootsWatchers = undefined ;
1204+ if ( this . typeRootsWatchers ) {
1205+ clearMap (
1206+ this . typeRootsWatchers ,
1207+ ( directory , watcher ) =>
1208+ this . projectService . closeDirectoryWatcher ( WatchType . TypeRoot , this ,
1209+ directory , watcher , WatchDirectoryFlags . None , reason )
1210+ ) ;
1211+ this . typeRootsWatchers = undefined ;
1212+ }
12031213 }
12041214
12051215 close ( ) {
0 commit comments