@@ -1346,14 +1346,52 @@ namespace ts {
1346
1346
}
1347
1347
1348
1348
function getUpToDateStatusWorker ( state : SolutionBuilderState , project : ParsedCommandLine , resolvedPath : ResolvedConfigFilePath ) : UpToDateStatus {
1349
- // Container if no files are specified in the project
1350
- if ( ! project . fileNames . length && ! canJsonReportNoInputFiles ( project . raw ) ) {
1349
+ // Container if no files are specified in the project
1350
+ if ( ! project . fileNames . length && ! canJsonReportNoInputFiles ( project . raw ) ) {
1351
1351
return {
1352
1352
type : UpToDateStatusType . ContainerOnly
1353
1353
} ;
1354
1354
}
1355
1355
1356
+ // Fast check to see if reference projects are buildable
1357
+ let referenceStatuses ;
1356
1358
const force = ! ! state . options . force ;
1359
+ if ( project . projectReferences ) {
1360
+ state . projectStatus . set ( resolvedPath , { type : UpToDateStatusType . ComputingUpstream } ) ;
1361
+ for ( const ref of project . projectReferences ) {
1362
+ const resolvedRef = resolveProjectReferencePath ( ref ) ;
1363
+ const resolvedRefPath = toResolvedConfigFilePath ( state , resolvedRef ) ;
1364
+ const refStatus = getUpToDateStatus ( state , parseConfigFile ( state , resolvedRef , resolvedRefPath ) , resolvedRefPath ) ;
1365
+
1366
+ // Its a circular reference ignore the status of this project
1367
+ if ( refStatus . type === UpToDateStatusType . ComputingUpstream ||
1368
+ refStatus . type === UpToDateStatusType . ContainerOnly ) { // Container only ignore this project
1369
+ continue ;
1370
+ }
1371
+
1372
+ // An upstream project is blocked
1373
+ if ( refStatus . type === UpToDateStatusType . Unbuildable ||
1374
+ refStatus . type === UpToDateStatusType . UpstreamBlocked ) {
1375
+ return {
1376
+ type : UpToDateStatusType . UpstreamBlocked ,
1377
+ upstreamProjectName : ref . path ,
1378
+ upstreamProjectBlocked : refStatus . type === UpToDateStatusType . UpstreamBlocked
1379
+ } ;
1380
+ }
1381
+
1382
+ // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
1383
+ if ( refStatus . type !== UpToDateStatusType . UpToDate ) {
1384
+ return {
1385
+ type : UpToDateStatusType . UpstreamOutOfDate ,
1386
+ upstreamProjectName : ref . path
1387
+ } ;
1388
+ }
1389
+
1390
+ if ( ! force ) ( referenceStatuses ||= [ ] ) . push ( { ref, refStatus } ) ;
1391
+ }
1392
+ }
1393
+
1394
+ // Check output files
1357
1395
let newestInputFileName : string = undefined ! ;
1358
1396
let newestInputFileTime = minimumDate ;
1359
1397
const { host } = state ;
@@ -1381,17 +1419,16 @@ namespace ts {
1381
1419
// Now see if all outputs are newer than the newest input
1382
1420
let oldestOutputFileName = "(none)" ;
1383
1421
let oldestOutputFileTime = maximumDate ;
1384
- let missingOutputFileName : string | undefined ;
1385
1422
let newestDeclarationFileContentChangedTime = minimumDate ;
1386
- let isOutOfDateWithInputs = false ;
1387
1423
if ( ! force ) {
1388
1424
for ( const output of outputs ) {
1389
1425
// Output is missing; can stop checking
1390
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
1391
1426
const outputTime = getModifiedTime ( host , output ) ;
1392
1427
if ( outputTime === missingFileModifiedTime ) {
1393
- missingOutputFileName = output ;
1394
- break ;
1428
+ return {
1429
+ type : UpToDateStatusType . OutputMissing ,
1430
+ missingOutputFileName : output
1431
+ } ;
1395
1432
}
1396
1433
1397
1434
if ( outputTime < oldestOutputFileTime ) {
@@ -1400,10 +1437,12 @@ namespace ts {
1400
1437
}
1401
1438
1402
1439
// If an output is older than the newest input, we can stop checking
1403
- // Don't immediately return because we can still be upstream-blocked, which is a higher-priority status
1404
1440
if ( outputTime < newestInputFileTime ) {
1405
- isOutOfDateWithInputs = true ;
1406
- break ;
1441
+ return {
1442
+ type : UpToDateStatusType . OutOfDateWithSelf ,
1443
+ outOfDateOutputFileName : oldestOutputFileName ,
1444
+ newerInputFileName : newestInputFileName
1445
+ } ;
1407
1446
}
1408
1447
1409
1448
// Keep track of when the most recent time a .d.ts file was changed.
@@ -1419,96 +1458,47 @@ namespace ts {
1419
1458
let pseudoUpToDate = false ;
1420
1459
let usesPrepend = false ;
1421
1460
let upstreamChangedProject : string | undefined ;
1422
- if ( project . projectReferences ) {
1423
- state . projectStatus . set ( resolvedPath , { type : UpToDateStatusType . ComputingUpstream } ) ;
1424
- for ( const ref of project . projectReferences ) {
1461
+ if ( referenceStatuses ) {
1462
+ for ( const { ref, refStatus } of referenceStatuses ) {
1425
1463
usesPrepend = usesPrepend || ! ! ( ref . prepend ) ;
1426
- const resolvedRef = resolveProjectReferencePath ( ref ) ;
1427
- const resolvedRefPath = toResolvedConfigFilePath ( state , resolvedRef ) ;
1428
- const refStatus = getUpToDateStatus ( state , parseConfigFile ( state , resolvedRef , resolvedRefPath ) , resolvedRefPath ) ;
1429
-
1430
- // Its a circular reference ignore the status of this project
1431
- if ( refStatus . type === UpToDateStatusType . ComputingUpstream ||
1432
- refStatus . type === UpToDateStatusType . ContainerOnly ) { // Container only ignore this project
1464
+ // If the upstream project's newest file is older than our oldest output, we
1465
+ // can't be out of date because of it
1466
+ if ( refStatus . newestInputFileTime && refStatus . newestInputFileTime <= oldestOutputFileTime ) {
1433
1467
continue ;
1434
1468
}
1435
1469
1436
- // An upstream project is blocked
1437
- if ( refStatus . type === UpToDateStatusType . Unbuildable ||
1438
- refStatus . type === UpToDateStatusType . UpstreamBlocked ) {
1439
- return {
1440
- type : UpToDateStatusType . UpstreamBlocked ,
1441
- upstreamProjectName : ref . path ,
1442
- upstreamProjectBlocked : refStatus . type === UpToDateStatusType . UpstreamBlocked
1443
- } ;
1444
- }
1445
-
1446
- // If the upstream project is out of date, then so are we (someone shouldn't have asked, though?)
1447
- if ( refStatus . type !== UpToDateStatusType . UpToDate ) {
1448
- return {
1449
- type : UpToDateStatusType . UpstreamOutOfDate ,
1450
- upstreamProjectName : ref . path
1451
- } ;
1470
+ // If the upstream project has only change .d.ts files, and we've built
1471
+ // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
1472
+ if ( refStatus . newestDeclarationFileContentChangedTime && refStatus . newestDeclarationFileContentChangedTime <= oldestOutputFileTime ) {
1473
+ pseudoUpToDate = true ;
1474
+ upstreamChangedProject = ref . path ;
1475
+ continue ;
1452
1476
}
1453
1477
1454
- // Check oldest output file name only if there is no missing output file name
1455
- // (a check we will have skipped if this is a forced build)
1456
- if ( ! force && ! missingOutputFileName ) {
1457
- // If the upstream project's newest file is older than our oldest output, we
1458
- // can't be out of date because of it
1459
- if ( refStatus . newestInputFileTime && refStatus . newestInputFileTime <= oldestOutputFileTime ) {
1460
- continue ;
1461
- }
1462
-
1463
- // If the upstream project has only change .d.ts files, and we've built
1464
- // *after* those files, then we're "psuedo up to date" and eligible for a fast rebuild
1465
- if ( refStatus . newestDeclarationFileContentChangedTime && refStatus . newestDeclarationFileContentChangedTime <= oldestOutputFileTime ) {
1466
- pseudoUpToDate = true ;
1467
- upstreamChangedProject = ref . path ;
1468
- continue ;
1469
- }
1470
-
1471
- // We have an output older than an upstream output - we are out of date
1472
- Debug . assert ( oldestOutputFileName !== undefined , "Should have an oldest output filename here" ) ;
1473
- return {
1474
- type : UpToDateStatusType . OutOfDateWithUpstream ,
1475
- outOfDateOutputFileName : oldestOutputFileName ,
1476
- newerProjectName : ref . path
1477
- } ;
1478
- }
1478
+ // We have an output older than an upstream output - we are out of date
1479
+ Debug . assert ( oldestOutputFileName !== undefined , "Should have an oldest output filename here" ) ;
1480
+ return {
1481
+ type : UpToDateStatusType . OutOfDateWithUpstream ,
1482
+ outOfDateOutputFileName : oldestOutputFileName ,
1483
+ newerProjectName : ref . path
1484
+ } ;
1479
1485
}
1480
1486
}
1481
1487
1482
- if ( missingOutputFileName !== undefined ) {
1483
- return {
1484
- type : UpToDateStatusType . OutputMissing ,
1485
- missingOutputFileName
1486
- } ;
1487
- }
1488
+ // Check tsconfig time
1489
+ const configStatus = checkConfigFileUpToDateStatus ( state , project . options . configFilePath ! , oldestOutputFileTime , oldestOutputFileName ) ;
1490
+ if ( configStatus ) return configStatus ;
1488
1491
1489
- if ( isOutOfDateWithInputs ) {
1490
- return {
1491
- type : UpToDateStatusType . OutOfDateWithSelf ,
1492
- outOfDateOutputFileName : oldestOutputFileName ,
1493
- newerInputFileName : newestInputFileName
1494
- } ;
1495
- }
1496
- else {
1497
- // Check tsconfig time
1498
- const configStatus = checkConfigFileUpToDateStatus ( state , project . options . configFilePath ! , oldestOutputFileTime , oldestOutputFileName ) ;
1499
- if ( configStatus ) return configStatus ;
1500
-
1501
- // Check extended config time
1502
- const extendedConfigStatus = forEach ( project . options . configFile ! . extendedSourceFiles || emptyArray , configFile => checkConfigFileUpToDateStatus ( state , configFile , oldestOutputFileTime , oldestOutputFileName ) ) ;
1503
- if ( extendedConfigStatus ) return extendedConfigStatus ;
1504
-
1505
- // Check package file time
1506
- const dependentPackageFileStatus = forEach (
1507
- state . lastCachedPackageJsonLookups . get ( resolvedPath ) || emptyArray ,
1508
- ( [ path ] ) => checkConfigFileUpToDateStatus ( state , path , oldestOutputFileTime , oldestOutputFileName )
1509
- ) ;
1510
- if ( dependentPackageFileStatus ) return dependentPackageFileStatus ;
1511
- }
1492
+ // Check extended config time
1493
+ const extendedConfigStatus = forEach ( project . options . configFile ! . extendedSourceFiles || emptyArray , configFile => checkConfigFileUpToDateStatus ( state , configFile , oldestOutputFileTime , oldestOutputFileName ) ) ;
1494
+ if ( extendedConfigStatus ) return extendedConfigStatus ;
1495
+
1496
+ // Check package file time
1497
+ const dependentPackageFileStatus = forEach (
1498
+ state . lastCachedPackageJsonLookups . get ( resolvedPath ) || emptyArray ,
1499
+ ( [ path ] ) => checkConfigFileUpToDateStatus ( state , path , oldestOutputFileTime , oldestOutputFileName )
1500
+ ) ;
1501
+ if ( dependentPackageFileStatus ) return dependentPackageFileStatus ;
1512
1502
1513
1503
if ( ! force && ! state . buildInfoChecked . has ( resolvedPath ) ) {
1514
1504
state . buildInfoChecked . set ( resolvedPath , true ) ;
0 commit comments