@@ -10,7 +10,9 @@ import {
10
10
clearMap ,
11
11
closeFileWatcher ,
12
12
closeFileWatcherOf ,
13
+ combinePaths ,
13
14
commonOptionsWithBuild ,
15
+ compareDataObjects ,
14
16
CompilerHost ,
15
17
CompilerOptions ,
16
18
CompilerOptionsValue ,
@@ -63,6 +65,7 @@ import {
63
65
getLocaleTimeString ,
64
66
getModifiedTime as ts_getModifiedTime ,
65
67
getNormalizedAbsolutePath ,
68
+ GetOrLoadUserWatchFactoryDetailsForFactory ,
66
69
getParsedCommandLineOfConfigFile ,
67
70
getPendingEmitKind ,
68
71
getSourceFileVersionAsHashFromText ,
@@ -119,6 +122,7 @@ import {
119
122
updateWatchingWildcardDirectories ,
120
123
UpToDateStatus ,
121
124
UpToDateStatusType ,
125
+ UserWatchFactoryWithName ,
122
126
version ,
123
127
WatchFactory ,
124
128
WatchHost ,
@@ -414,6 +418,7 @@ interface SolutionBuilderState<T extends BuilderProgram> extends WatchFactory<Wa
414
418
readonly allWatchedConfigFiles : Map < ResolvedConfigFilePath , FileWatcher > ;
415
419
readonly allWatchedExtendedConfigFiles : Map < Path , SharedExtendedConfigFileWatcher < ResolvedConfigFilePath > > ;
416
420
readonly allWatchedPackageJsonFiles : Map < ResolvedConfigFilePath , Map < Path , FileWatcher > > ;
421
+ readonly allWatchFactories : Map < ResolvedConfigFilePath , UserWatchFactoryWithName | false > ;
417
422
readonly filesWatched : Map < Path , FileWatcherWithModifiedTime | Date > ;
418
423
readonly outputTimeStamps : Map < ResolvedConfigFilePath , Map < Path , Date > > ;
419
424
@@ -424,7 +429,7 @@ interface SolutionBuilderState<T extends BuilderProgram> extends WatchFactory<Wa
424
429
writeLog : ( s : string ) => void ;
425
430
}
426
431
427
- function createSolutionBuilderState < T extends BuilderProgram > ( watch : boolean , hostOrHostWithWatch : SolutionBuilderHost < T > | SolutionBuilderWithWatchHost < T > , rootNames : readonly string [ ] , options : BuildOptions , baseWatchOptions : WatchOptions | undefined ) : SolutionBuilderState < T > {
432
+ function createSolutionBuilderAndState < T extends BuilderProgram > ( watch : boolean , hostOrHostWithWatch : SolutionBuilderHost < T > | SolutionBuilderWithWatchHost < T > , rootNames : readonly string [ ] , options : BuildOptions , baseWatchOptions : WatchOptions | undefined ) : SolutionBuilder < T > {
428
433
const host = hostOrHostWithWatch as SolutionBuilderHost < T > ;
429
434
const hostWithWatch = hostOrHostWithWatch as SolutionBuilderWithWatchHost < T > ;
430
435
@@ -482,7 +487,11 @@ function createSolutionBuilderState<T extends BuilderProgram>(watch: boolean, ho
482
487
}
483
488
compilerHost . getBuildInfo = ( fileName , configFilePath ) => getBuildInfo ( state , fileName , toResolvedConfigFilePath ( state , configFilePath as ResolvedConfigFileName ) , /*modifiedTime*/ undefined ) ;
484
489
485
- const { watchFile, watchDirectory, writeLog } = createWatchFactory < ResolvedConfigFileName > ( hostWithWatch , options ) ;
490
+ const { watchFile, watchDirectory, writeLog } = createWatchFactory < ResolvedConfigFileName > (
491
+ hostWithWatch ,
492
+ resolved => getOrLoadUserWatchFactoryDetails ( state , ( ) => solution , resolved ! ) ,
493
+ options ,
494
+ ) ;
486
495
487
496
const state : SolutionBuilderState < T > = {
488
497
host,
@@ -529,6 +538,7 @@ function createSolutionBuilderState<T extends BuilderProgram>(watch: boolean, ho
529
538
allWatchedConfigFiles : new Map ( ) ,
530
539
allWatchedExtendedConfigFiles : new Map ( ) ,
531
540
allWatchedPackageJsonFiles : new Map ( ) ,
541
+ allWatchFactories : new Map ( ) ,
532
542
filesWatched : new Map ( ) ,
533
543
534
544
lastCachedPackageJsonLookups : new Map ( ) ,
@@ -540,7 +550,25 @@ function createSolutionBuilderState<T extends BuilderProgram>(watch: boolean, ho
540
550
writeLog,
541
551
} ;
542
552
543
- return state ;
553
+ const solution : SolutionBuilder < T > = {
554
+ build : ( project , cancellationToken , writeFile , getCustomTransformers ) => build ( state , project , cancellationToken , writeFile , getCustomTransformers ) ,
555
+ clean : project => clean ( state , project ) ,
556
+ buildReferences : ( project , cancellationToken , writeFile , getCustomTransformers ) => build ( state , project , cancellationToken , writeFile , getCustomTransformers , /*onlyReferences*/ true ) ,
557
+ cleanReferences : project => clean ( state , project , /*onlyReferences*/ true ) ,
558
+ getNextInvalidatedProject : cancellationToken => {
559
+ setupInitialBuild ( state , cancellationToken ) ;
560
+ return getNextInvalidatedProject ( state , getBuildOrder ( state ) , /*reportQueue*/ false ) ;
561
+ } ,
562
+ getBuildOrder : ( ) => getBuildOrder ( state ) ,
563
+ getUpToDateStatusOfProject : project => {
564
+ const configFileName = resolveProjectName ( state , project ) ;
565
+ const configFilePath = toResolvedConfigFilePath ( state , configFileName ) ;
566
+ return getUpToDateStatus ( state , parseConfigFile ( state , configFileName , configFilePath ) , configFilePath ) ;
567
+ } ,
568
+ invalidateProject : ( configFilePath , reloadLevel ) => invalidateProject ( state , configFilePath , reloadLevel || ConfigFileProgramReloadLevel . None ) ,
569
+ close : ( ) => stopWatching ( state ) ,
570
+ } ;
571
+ return solution ;
544
572
}
545
573
546
574
function toPath < T extends BuilderProgram > ( state : SolutionBuilderState < T > , fileName : string ) {
@@ -704,6 +732,8 @@ function createStateBuildOrder<T extends BuilderProgram>(state: SolutionBuilderS
704
732
currentProjects ,
705
733
{ onDeleteValue : existingMap => existingMap . forEach ( closeFileWatcher ) }
706
734
) ;
735
+
736
+ mutateMapSkippingNewValues ( state . allWatchFactories , currentProjects , noopOnDelete ) ;
707
737
}
708
738
return state . buildOrder = buildOrder ;
709
739
}
@@ -1397,6 +1427,7 @@ function getNextInvalidatedProjectCreateInfo<T extends BuilderProgram>(
1397
1427
reportBuildQueue ( state , buildOrder ) ;
1398
1428
}
1399
1429
1430
+ const oldConfig = getCachedParsedConfigFile ( state , projectPath ) ;
1400
1431
const config = parseConfigFile ( state , project , projectPath ) ;
1401
1432
if ( ! config ) {
1402
1433
reportParseConfigFileDiagnostic ( state , projectPath ) ;
@@ -1405,8 +1436,9 @@ function getNextInvalidatedProjectCreateInfo<T extends BuilderProgram>(
1405
1436
}
1406
1437
1407
1438
if ( reloadLevel === ConfigFileProgramReloadLevel . Full ) {
1439
+ releaseExistingUseWatchFactory ( state , projectPath , oldConfig , config ) ;
1408
1440
watchConfigFile ( state , project , projectPath , config ) ;
1409
- watchExtendedConfigFiles ( state , projectPath , config ) ;
1441
+ watchExtendedConfigFiles ( state , project , projectPath , config ) ;
1410
1442
watchWildCardDirectories ( state , project , projectPath , config ) ;
1411
1443
watchInputFiles ( state , project , projectPath , config ) ;
1412
1444
watchPackageJsonFiles ( state , project , projectPath , config ) ;
@@ -1593,7 +1625,7 @@ function getModifiedTime<T extends BuilderProgram>(state: SolutionBuilderState<T
1593
1625
return result ;
1594
1626
}
1595
1627
1596
- function watchFile < T extends BuilderProgram > ( state : SolutionBuilderState < T > , file : string , callback : FileWatcherCallback , pollingInterval : PollingInterval , options : WatchOptions | undefined , watchType : WatchType , project ? : ResolvedConfigFileName ) : FileWatcher {
1628
+ function watchFile < T extends BuilderProgram > ( state : SolutionBuilderState < T > , file : string , callback : FileWatcherCallback , pollingInterval : PollingInterval , options : WatchOptions | undefined , watchType : WatchType , project : ResolvedConfigFileName ) : FileWatcher {
1597
1629
const path = toPath ( state , file ) ;
1598
1630
const existing = state . filesWatched . get ( path ) ;
1599
1631
if ( existing && isFileWatcherWithModifiedTime ( existing ) ) {
@@ -2319,6 +2351,19 @@ function buildNextInvalidatedProjectWorker<T extends BuilderProgram>(state: Solu
2319
2351
return buildOrder ;
2320
2352
}
2321
2353
2354
+ function releaseExistingUseWatchFactory < T extends BuilderProgram > (
2355
+ state : SolutionBuilderState < T > ,
2356
+ resolvedPath : ResolvedConfigFilePath ,
2357
+ oldConfig : ParsedCommandLine | undefined ,
2358
+ newConfig : ParsedCommandLine ,
2359
+ ) {
2360
+ const existing = state . allWatchFactories . get ( resolvedPath ) ;
2361
+ if ( existing !== undefined &&
2362
+ ! compareDataObjects ( oldConfig ?. watchOptions ?. watchFactory , newConfig . watchOptions ?. watchFactory ) ) {
2363
+ state . allWatchFactories . delete ( resolvedPath ) ;
2364
+ }
2365
+ }
2366
+
2322
2367
function watchConfigFile < T extends BuilderProgram > ( state : SolutionBuilderState < T > , resolved : ResolvedConfigFileName , resolvedPath : ResolvedConfigFilePath , parsed : ParsedCommandLine | undefined ) {
2323
2368
if ( ! state . watch || state . allWatchedConfigFiles . has ( resolvedPath ) ) return ;
2324
2369
state . allWatchedConfigFiles . set ( resolvedPath , watchFile (
@@ -2332,7 +2377,7 @@ function watchConfigFile<T extends BuilderProgram>(state: SolutionBuilderState<T
2332
2377
) ) ;
2333
2378
}
2334
2379
2335
- function watchExtendedConfigFiles < T extends BuilderProgram > ( state : SolutionBuilderState < T > , resolvedPath : ResolvedConfigFilePath , parsed : ParsedCommandLine | undefined ) {
2380
+ function watchExtendedConfigFiles < T extends BuilderProgram > ( state : SolutionBuilderState < T > , resolved : ResolvedConfigFileName , resolvedPath : ResolvedConfigFilePath , parsed : ParsedCommandLine | undefined ) {
2336
2381
updateSharedExtendedConfigFileWatcher (
2337
2382
resolvedPath ,
2338
2383
parsed ?. options ,
@@ -2345,6 +2390,7 @@ function watchExtendedConfigFiles<T extends BuilderProgram>(state: SolutionBuild
2345
2390
PollingInterval . High ,
2346
2391
parsed ?. watchOptions ,
2347
2392
WatchType . ExtendedConfigFile ,
2393
+ resolved ,
2348
2394
) ,
2349
2395
fileName => toPath ( state , fileName ) ,
2350
2396
) ;
@@ -2430,7 +2476,7 @@ function startWatching<T extends BuilderProgram>(state: SolutionBuilderState<T>,
2430
2476
const cfg = parseConfigFile ( state , resolved , resolvedPath ) ;
2431
2477
// Watch this file
2432
2478
watchConfigFile ( state , resolved , resolvedPath , cfg ) ;
2433
- watchExtendedConfigFiles ( state , resolvedPath , cfg ) ;
2479
+ watchExtendedConfigFiles ( state , resolved , resolvedPath , cfg ) ;
2434
2480
if ( cfg ) {
2435
2481
// Update watchers for wildcard directories
2436
2482
watchWildCardDirectories ( state , resolved , resolvedPath , cfg ) ;
@@ -2452,6 +2498,7 @@ function stopWatching<T extends BuilderProgram>(state: SolutionBuilderState<T>)
2452
2498
clearMap ( state . allWatchedWildcardDirectories , watchedWildcardDirectories => clearMap ( watchedWildcardDirectories , closeFileWatcherOf ) ) ;
2453
2499
clearMap ( state . allWatchedInputFiles , watchedWildcardDirectories => clearMap ( watchedWildcardDirectories , closeFileWatcher ) ) ;
2454
2500
clearMap ( state . allWatchedPackageJsonFiles , watchedPacageJsonFiles => clearMap ( watchedPacageJsonFiles , closeFileWatcher ) ) ;
2501
+ state . allWatchFactories . clear ( ) ;
2455
2502
}
2456
2503
2457
2504
/**
@@ -2461,25 +2508,7 @@ function stopWatching<T extends BuilderProgram>(state: SolutionBuilderState<T>)
2461
2508
function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : false , host : SolutionBuilderHost < T > , rootNames : readonly string [ ] , defaultOptions : BuildOptions ) : SolutionBuilder < T > ;
2462
2509
function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : true , host : SolutionBuilderWithWatchHost < T > , rootNames : readonly string [ ] , defaultOptions : BuildOptions , baseWatchOptions ?: WatchOptions ) : SolutionBuilder < T > ;
2463
2510
function createSolutionBuilderWorker < T extends BuilderProgram > ( watch : boolean , hostOrHostWithWatch : SolutionBuilderHost < T > | SolutionBuilderWithWatchHost < T > , rootNames : readonly string [ ] , options : BuildOptions , baseWatchOptions ?: WatchOptions ) : SolutionBuilder < T > {
2464
- const state = createSolutionBuilderState ( watch , hostOrHostWithWatch , rootNames , options , baseWatchOptions ) ;
2465
- return {
2466
- build : ( project , cancellationToken , writeFile , getCustomTransformers ) => build ( state , project , cancellationToken , writeFile , getCustomTransformers ) ,
2467
- clean : project => clean ( state , project ) ,
2468
- buildReferences : ( project , cancellationToken , writeFile , getCustomTransformers ) => build ( state , project , cancellationToken , writeFile , getCustomTransformers , /*onlyReferences*/ true ) ,
2469
- cleanReferences : project => clean ( state , project , /*onlyReferences*/ true ) ,
2470
- getNextInvalidatedProject : cancellationToken => {
2471
- setupInitialBuild ( state , cancellationToken ) ;
2472
- return getNextInvalidatedProject ( state , getBuildOrder ( state ) , /*reportQueue*/ false ) ;
2473
- } ,
2474
- getBuildOrder : ( ) => getBuildOrder ( state ) ,
2475
- getUpToDateStatusOfProject : project => {
2476
- const configFileName = resolveProjectName ( state , project ) ;
2477
- const configFilePath = toResolvedConfigFilePath ( state , configFileName ) ;
2478
- return getUpToDateStatus ( state , parseConfigFile ( state , configFileName , configFilePath ) , configFilePath ) ;
2479
- } ,
2480
- invalidateProject : ( configFilePath , reloadLevel ) => invalidateProject ( state , configFilePath , reloadLevel || ConfigFileProgramReloadLevel . None ) ,
2481
- close : ( ) => stopWatching ( state ) ,
2482
- } ;
2511
+ return createSolutionBuilderAndState ( watch , hostOrHostWithWatch , rootNames , options , baseWatchOptions ) ;
2483
2512
}
2484
2513
2485
2514
function relName < T extends BuilderProgram > ( state : SolutionBuilderState < T > , path : string ) : string {
@@ -2693,3 +2722,22 @@ function verboseReportProjectStatus<T extends BuilderProgram>(state: SolutionBui
2693
2722
reportUpToDateStatus ( state , configFileName , status ) ;
2694
2723
}
2695
2724
}
2725
+
2726
+ function getOrLoadUserWatchFactoryDetails < T extends BuilderProgram > (
2727
+ state : SolutionBuilderState < T > ,
2728
+ getSolution : ( ) => SolutionBuilder < T > ,
2729
+ resolved : ResolvedConfigFileName ,
2730
+ ) : GetOrLoadUserWatchFactoryDetailsForFactory {
2731
+ const resolvedPath = toResolvedConfigFilePath ( state , resolved ) ;
2732
+ return {
2733
+ getCurrentUserWatchFactory : ( ) => state . allWatchFactories . get ( resolvedPath ) ,
2734
+ setUserWatchFactory : userWatchFactory => state . allWatchFactories . set ( resolvedPath , userWatchFactory ) ,
2735
+ getSearchList : ( ) => [
2736
+ getDirectoryPath ( resolved ) ,
2737
+ state . host . getCurrentDirectory ( ) ,
2738
+ // ../../.. to walk from X/node_modules/typescript/lib/tsserver.js to X/node_modules/
2739
+ ...( state . host . getDefaultLibLocation ? [ combinePaths ( state . host . getDefaultLibLocation ( ) , "../.." ) ] : emptyArray ) ,
2740
+ ] ,
2741
+ getSolution,
2742
+ } ;
2743
+ }
0 commit comments