@@ -757,7 +757,9 @@ namespace ts.server {
757
757
readonly watchFactory : WatchFactory < WatchType , Project > ;
758
758
759
759
/*@internal */
760
- private sharedExtendedConfigFilesMap = new Map < string , SharedExtendedConfigFileWatcher < Project > > ( ) ;
760
+ private sharedExtendedConfigFileMap = createMultiMap < Path , ConfiguredProject > ( ) ;
761
+ /*@internal */
762
+ private sharedExtendedConfigFileWatchers = new Map < Path , FileWatcher > ( ) ;
761
763
762
764
/*@internal */
763
765
readonly packageJsonCache : PackageJsonCache ;
@@ -1355,14 +1357,52 @@ namespace ts.server {
1355
1357
}
1356
1358
1357
1359
/*@internal */
1358
- onExtendedConfigChangedForConfiguredProject ( project : ConfiguredProject , extendedConfigFile : string ) {
1359
- this . logExtendedConfigFileWatchUpdate ( asNormalizedPath ( extendedConfigFile ) , project . canonicalConfigFilePath , ConfigFileWatcherStatus . ReloadingFiles ) ;
1360
+ private updateSharedExtendedConfigFileMap ( project : ConfiguredProject ) {
1361
+ const extendedSourceFiles = project . getCompilerOptions ( ) . configFile ?. extendedSourceFiles || emptyArray ;
1362
+ extendedSourceFiles . forEach ( ( extendedSourceFile : string ) => {
1363
+ const extendedConfigPath = this . toPath ( extendedSourceFile ) ;
1364
+ if ( ! this . sharedExtendedConfigFileMap . has ( extendedConfigPath ) ) {
1365
+ const watcher = this . watchFactory . watchFile (
1366
+ extendedConfigPath ,
1367
+ ( ) => this . onSharedExtendedConfigChanged ( extendedConfigPath ) ,
1368
+ PollingInterval . High ,
1369
+ this . hostConfiguration . watchOptions ,
1370
+ WatchType . ExtendedConfigFile
1371
+ ) ;
1372
+ this . sharedExtendedConfigFileWatchers . set ( extendedConfigPath , watcher ) ;
1373
+ }
1374
+ const otherProjects = this . sharedExtendedConfigFileMap . get ( extendedConfigPath ) ;
1375
+ if ( ! otherProjects || ! otherProjects . includes ( project ) ) {
1376
+ this . sharedExtendedConfigFileMap . add ( extendedConfigPath , project ) ;
1377
+ }
1378
+ } ) ;
1379
+ }
1360
1380
1361
- // Skip refresh if project is not yet loaded
1362
- if ( project . isInitialLoadPending ( ) ) return ;
1363
- project . pendingReload = ConfigFileProgramReloadLevel . Full ;
1364
- project . pendingReloadReason = `Change in extended config file ${ extendedConfigFile } detected` ;
1365
- this . delayUpdateProjectGraph ( project ) ;
1381
+ /*@internal */
1382
+ private removeProjectFromSharedExtendedConfigFileMap ( project : ConfiguredProject ) {
1383
+ for ( const key of arrayFrom ( this . sharedExtendedConfigFileMap . keys ( ) ) ) {
1384
+ this . sharedExtendedConfigFileMap . remove ( key , project ) ;
1385
+ const otherProjects = this . sharedExtendedConfigFileMap . get ( key ) || emptyArray ;
1386
+ if ( otherProjects . length === 0 ) {
1387
+ const watcher = this . sharedExtendedConfigFileWatchers . get ( key ) ;
1388
+ if ( watcher ) {
1389
+ watcher . close ( ) ;
1390
+ this . sharedExtendedConfigFileWatchers . delete ( key ) ;
1391
+ }
1392
+ }
1393
+ }
1394
+ }
1395
+
1396
+ /*@internal */
1397
+ private onSharedExtendedConfigChanged ( extendedConfigPath : Path ) {
1398
+ const projects = this . sharedExtendedConfigFileMap . get ( extendedConfigPath ) || emptyArray ;
1399
+ projects . forEach ( ( project : ConfiguredProject ) => {
1400
+ // Skip refresh if project is not yet loaded
1401
+ if ( project . isInitialLoadPending ( ) ) return ;
1402
+ project . pendingReload = ConfigFileProgramReloadLevel . Full ;
1403
+ project . pendingReloadReason = `Change in extended config file ${ extendedConfigPath } detected` ;
1404
+ this . delayUpdateProjectGraph ( project ) ;
1405
+ } ) ;
1366
1406
}
1367
1407
1368
1408
/**
@@ -1388,7 +1428,6 @@ namespace ts.server {
1388
1428
project . print ( /*writeProjectFileNames*/ true ) ;
1389
1429
1390
1430
project . close ( ) ;
1391
- removeProjectFromSharedExtendedConfigFilesWatch ( project , this . sharedExtendedConfigFilesMap ) ;
1392
1431
if ( Debug . shouldAssert ( AssertionLevel . Normal ) ) {
1393
1432
this . filenameToScriptInfo . forEach ( info => Debug . assert (
1394
1433
! info . isAttached ( project ) ,
@@ -1421,6 +1460,7 @@ namespace ts.server {
1421
1460
this . configuredProjects . delete ( ( < ConfiguredProject > project ) . canonicalConfigFilePath ) ;
1422
1461
this . projectToSizeMap . delete ( ( project as ConfiguredProject ) . canonicalConfigFilePath ) ;
1423
1462
this . setConfigFileExistenceInfoByClosedConfiguredProject ( < ConfiguredProject > project ) ;
1463
+ this . removeProjectFromSharedExtendedConfigFileMap ( project as ConfiguredProject ) ;
1424
1464
break ;
1425
1465
case ProjectKind . Inferred :
1426
1466
unorderedRemoveItem ( this . inferredProjects , < InferredProject > project ) ;
@@ -1689,18 +1729,6 @@ namespace ts.server {
1689
1729
this . logger . info ( `ConfigFilePresence:: Current Watches: ${ watches } :: File: ${ configFileName } Currently impacted open files: RootsOfInferredProjects: ${ inferredRoots } OtherOpenFiles: ${ otherFiles } Status: ${ status } ` ) ;
1690
1730
}
1691
1731
1692
- /*@internal */
1693
- private logExtendedConfigFileWatchUpdate ( extendedConfigFile : NormalizedPath , canonicalConfigFilePath : string , status : ConfigFileWatcherStatus ) {
1694
- if ( ! this . logger . hasLevel ( LogLevel . verbose ) ) {
1695
- return ;
1696
- }
1697
- const watches : WatchType [ ] = [ ] ;
1698
- if ( this . configuredProjects . has ( canonicalConfigFilePath ) ) {
1699
- watches . push ( WatchType . ExtendedConfigFile ) ;
1700
- }
1701
- this . logger . info ( `ExtendedConfigFilePresence:: Current Watches: ${ watches } :: File: ${ extendedConfigFile } Status: ${ status } ` ) ;
1702
- }
1703
-
1704
1732
/**
1705
1733
* Create the watcher for the configFileExistenceInfo
1706
1734
*/
@@ -2162,23 +2190,14 @@ namespace ts.server {
2162
2190
if ( lastFileExceededProgramSize ) {
2163
2191
project . disableLanguageService ( lastFileExceededProgramSize ) ;
2164
2192
project . stopWatchingWildCards ( ) ;
2165
- removeProjectFromSharedExtendedConfigFilesWatch ( project , this . sharedExtendedConfigFilesMap ) ;
2193
+ this . removeProjectFromSharedExtendedConfigFileMap ( project ) ;
2166
2194
}
2167
2195
else {
2168
2196
project . setCompilerOptions ( compilerOptions ) ;
2169
2197
project . setWatchOptions ( parsedCommandLine . watchOptions ) ;
2170
2198
project . enableLanguageService ( ) ;
2171
2199
project . watchWildcards ( new Map ( getEntries ( parsedCommandLine . wildcardDirectories ! ) ) ) ; // TODO: GH#18217
2172
- if ( compilerOptions . configFile ) {
2173
- updateSharedExtendedConfigFilesWatch (
2174
- project ,
2175
- ( fileName ) => this . onExtendedConfigChangedForConfiguredProject ( project , fileName ) ,
2176
- compilerOptions . configFile ,
2177
- this . sharedExtendedConfigFilesMap ,
2178
- this . watchFactory ,
2179
- this . hostConfiguration . watchOptions ,
2180
- ) ;
2181
- }
2200
+ this . updateSharedExtendedConfigFileMap ( project ) ;
2182
2201
}
2183
2202
project . enablePluginsWithOptions ( compilerOptions , this . currentPluginConfigOverrides ) ;
2184
2203
const filesToAdd = parsedCommandLine . fileNames . concat ( project . getExternalFiles ( ) ) ;
0 commit comments