@@ -3,13 +3,15 @@ import {
3
3
AffectedFileResult ,
4
4
append ,
5
5
arrayFrom ,
6
+ arrayIsEqualTo ,
6
7
arrayToMap ,
7
8
BuilderProgram ,
8
9
BuilderProgramHost ,
9
10
BuilderState ,
10
11
BuildInfo ,
11
12
BuildInfoFileVersionMap ,
12
13
CancellationToken ,
14
+ combinePaths ,
13
15
CommandLineOption ,
14
16
compareStringsCaseSensitive ,
15
17
compareValues ,
@@ -60,6 +62,7 @@ import {
60
62
isIncrementalCompilation ,
61
63
isJsonSourceFile ,
62
64
isNumber ,
65
+ isPackageJsonInfo ,
63
66
isString ,
64
67
map ,
65
68
mapDefinedIterator ,
@@ -80,6 +83,8 @@ import {
80
83
skipAlias ,
81
84
skipTypeCheckingIgnoringNoCheck ,
82
85
some ,
86
+ sortAndDeduplicate ,
87
+ SortedReadonlyArray ,
83
88
SourceFile ,
84
89
sourceFileMayBeEmitted ,
85
90
SourceMapEmitResult ,
@@ -180,6 +185,7 @@ export interface ReusableBuilderProgramState extends BuilderState {
180
185
latestChangedDtsFile : string | undefined ;
181
186
/** Recorded if program had errors */
182
187
hasErrors ?: boolean ;
188
+ packageJsons ?: SortedReadonlyArray < string > ;
183
189
}
184
190
185
191
// dprint-ignore
@@ -260,6 +266,7 @@ export interface BuilderProgramState extends BuilderState, ReusableBuilderProgra
260
266
/** Already seen program emit */
261
267
seenProgramEmit : BuilderFileEmit | undefined ;
262
268
hasErrorsFromOldState ?: boolean ;
269
+ packageJsonsFromOldState ?: SortedReadonlyArray < string > ;
263
270
}
264
271
265
272
interface BuilderProgramStateWithDefinedProgram extends BuilderProgramState {
@@ -365,6 +372,7 @@ function createBuilderProgramState(
365
372
canCopyEmitDiagnostics = false ;
366
373
}
367
374
state . hasErrorsFromOldState = oldState ! . hasErrors ;
375
+ state . packageJsonsFromOldState = oldState ! . packageJsons ;
368
376
}
369
377
else {
370
378
// We arent using old state, so atleast emit buildInfo with current information
@@ -1139,6 +1147,7 @@ export interface IncrementalBuildInfoBase extends BuildInfo {
1139
1147
latestChangedDtsFile ?: string | undefined ;
1140
1148
errors : true | undefined ;
1141
1149
checkPending : true | undefined ;
1150
+ packageJsons : string [ ] | undefined ;
1142
1151
}
1143
1152
1144
1153
/** @internal */
@@ -1187,6 +1196,7 @@ export interface NonIncrementalBuildInfo extends BuildInfo {
1187
1196
root : readonly string [ ] ;
1188
1197
errors : true | undefined ;
1189
1198
checkPending : true | undefined ;
1199
+ packageJsons : string [ ] | undefined ;
1190
1200
}
1191
1201
1192
1202
function isNonIncrementalBuildInfo ( info : BuildInfo ) : info is NonIncrementalBuildInfo {
@@ -1217,22 +1227,44 @@ function ensureHasErrorsForState(state: BuilderProgramStateWithDefinedProgram) {
1217
1227
}
1218
1228
}
1219
1229
1230
+ function ensurePackageJsonsForState ( state : BuilderProgramStateWithDefinedProgram , host : BuilderProgramHost ) {
1231
+ if ( state . packageJsons !== undefined ) return ;
1232
+ let packageJsons : string [ ] = [ ] ;
1233
+ if ( state . program . getCompilerOptions ( ) . configFilePath ) {
1234
+ const internalMap = state . program . getModuleResolutionCache ( ) ?. getPackageJsonInfoCache ( ) . getInternalMap ( ) ;
1235
+ if ( internalMap ) {
1236
+ internalMap . forEach ( value => {
1237
+ if ( isPackageJsonInfo ( value ) ) {
1238
+ let path = combinePaths ( value . packageDirectory , "package.json" ) ;
1239
+ if ( host . realpath ) {
1240
+ path = host . realpath ( path ) ;
1241
+ }
1242
+ packageJsons . push ( path ) ;
1243
+ }
1244
+ } ) ;
1245
+ }
1246
+ }
1247
+ state . packageJsons = sortAndDeduplicate ( packageJsons ) ;
1248
+ }
1249
+
1220
1250
function hasSyntaxOrGlobalErrors ( state : BuilderProgramStateWithDefinedProgram ) {
1221
1251
return ! ! state . program . getConfigFileParsingDiagnostics ( ) . length ||
1222
1252
! ! state . program . getSyntacticDiagnostics ( ) . length ||
1223
1253
! ! state . program . getOptionsDiagnostics ( ) . length ||
1224
1254
! ! state . program . getGlobalDiagnostics ( ) . length ;
1225
1255
}
1226
1256
1227
- function getBuildInfoEmitPending ( state : BuilderProgramStateWithDefinedProgram ) {
1257
+ function getBuildInfoEmitPending ( state : BuilderProgramStateWithDefinedProgram , host : BuilderProgramHost ) {
1228
1258
ensureHasErrorsForState ( state ) ;
1229
- return state . buildInfoEmitPending ??= ! ! state . hasErrorsFromOldState !== ! ! state . hasErrors ;
1259
+ ensurePackageJsonsForState ( state , host ) ;
1260
+ return state . buildInfoEmitPending ??= ! ! state . hasErrorsFromOldState !== ! ! state . hasErrors ||
1261
+ ! arrayIsEqualTo ( state . packageJsons , state . packageJsonsFromOldState ) ;
1230
1262
}
1231
1263
1232
1264
/**
1233
1265
* Gets the program information to be emitted in buildInfo so that we can use it to create new program
1234
1266
*/
1235
- function getBuildInfo ( state : BuilderProgramStateWithDefinedProgram ) : BuildInfo {
1267
+ function getBuildInfo ( state : BuilderProgramStateWithDefinedProgram , host : BuilderProgramHost ) : BuildInfo {
1236
1268
const currentDirectory = state . program . getCurrentDirectory ( ) ;
1237
1269
const buildInfoDirectory = getDirectoryPath ( getNormalizedAbsolutePath ( getTsBuildInfoEmitOutputFilePath ( state . compilerOptions ) ! , currentDirectory ) ) ;
1238
1270
// Convert the file name to Path here if we set the fileName instead to optimize multiple d.ts file emits and having to compute Canonical path
@@ -1241,11 +1273,13 @@ function getBuildInfo(state: BuilderProgramStateWithDefinedProgram): BuildInfo {
1241
1273
const fileNameToFileId = new Map < string , IncrementalBuildInfoFileId > ( ) ;
1242
1274
const rootFileNames = new Set ( state . program . getRootFileNames ( ) . map ( f => toPath ( f , currentDirectory , state . program . getCanonicalFileName ) ) ) ;
1243
1275
ensureHasErrorsForState ( state ) ;
1276
+ ensurePackageJsonsForState ( state , host ) ;
1244
1277
if ( ! isIncrementalCompilation ( state . compilerOptions ) ) {
1245
1278
const buildInfo : NonIncrementalBuildInfo = {
1246
1279
root : arrayFrom ( rootFileNames , r => relativeToBuildInfo ( r ) ) ,
1247
1280
errors : state . hasErrors ? true : undefined ,
1248
1281
checkPending : state . checkPending ,
1282
+ packageJsons : toPackageJsons ( ) ,
1249
1283
version,
1250
1284
} ;
1251
1285
return buildInfo ;
@@ -1281,6 +1315,7 @@ function getBuildInfo(state: BuilderProgramStateWithDefinedProgram): BuildInfo {
1281
1315
state . programEmitPending , // Actual value
1282
1316
errors : state . hasErrors ? true : undefined ,
1283
1317
checkPending : state . checkPending ,
1318
+ packageJsons : toPackageJsons ( ) ,
1284
1319
version,
1285
1320
} ;
1286
1321
return buildInfo ;
@@ -1373,6 +1408,7 @@ function getBuildInfo(state: BuilderProgramStateWithDefinedProgram): BuildInfo {
1373
1408
latestChangedDtsFile,
1374
1409
errors : state . hasErrors ? true : undefined ,
1375
1410
checkPending : state . checkPending ,
1411
+ packageJsons : toPackageJsons ( ) ,
1376
1412
version,
1377
1413
} ;
1378
1414
return buildInfo ;
@@ -1564,6 +1600,10 @@ function getBuildInfo(state: BuilderProgramStateWithDefinedProgram): BuildInfo {
1564
1600
}
1565
1601
return changeFileSet ;
1566
1602
}
1603
+
1604
+ function toPackageJsons ( ) {
1605
+ return state . packageJsons ?. length ? state . packageJsons . map ( relativeToBuildInfo ) : undefined ;
1606
+ }
1567
1607
}
1568
1608
1569
1609
/** @internal */
@@ -1683,7 +1723,7 @@ export function createBuilderProgram(
1683
1723
}
1684
1724
1685
1725
const state = createBuilderProgramState ( newProgram , oldState ) ;
1686
- newProgram . getBuildInfo = ( ) => getBuildInfo ( toBuilderProgramStateWithDefinedProgram ( state ) ) ;
1726
+ newProgram . getBuildInfo = ( ) => getBuildInfo ( toBuilderProgramStateWithDefinedProgram ( state ) , host ) ;
1687
1727
1688
1728
// To ensure that we arent storing any references to old program or new program without state
1689
1729
newProgram = undefined ! ;
@@ -1722,7 +1762,7 @@ export function createBuilderProgram(
1722
1762
cancellationToken : CancellationToken | undefined ,
1723
1763
) : EmitResult {
1724
1764
Debug . assert ( isBuilderProgramStateWithDefinedProgram ( state ) ) ;
1725
- if ( getBuildInfoEmitPending ( state ) ) {
1765
+ if ( getBuildInfoEmitPending ( state , host ) ) {
1726
1766
const result = state . program . emitBuildInfo (
1727
1767
writeFile || maybeBind ( host , host . writeFile ) ,
1728
1768
cancellationToken ,
@@ -1809,7 +1849,7 @@ export function createBuilderProgram(
1809
1849
1810
1850
if ( ! affected ) {
1811
1851
// Emit buildinfo if pending
1812
- if ( isForDtsErrors || ! getBuildInfoEmitPending ( state ) ) return undefined ;
1852
+ if ( isForDtsErrors || ! getBuildInfoEmitPending ( state , host ) ) return undefined ;
1813
1853
const affected = state . program ;
1814
1854
const result = affected . emitBuildInfo (
1815
1855
writeFile || maybeBind ( host , host . writeFile ) ,
@@ -2282,6 +2322,7 @@ export function createBuilderProgramUsingIncrementalBuildInfo(
2282
2322
programEmitPending : buildInfo . pendingEmit === undefined ? undefined : toProgramEmitPending ( buildInfo . pendingEmit , buildInfo . options ) ,
2283
2323
hasErrors : buildInfo . errors ,
2284
2324
checkPending : buildInfo . checkPending ,
2325
+ packageJsons : toPackageJsons ( ) ,
2285
2326
} ;
2286
2327
}
2287
2328
else {
@@ -2320,6 +2361,7 @@ export function createBuilderProgramUsingIncrementalBuildInfo(
2320
2361
emitSignatures : emitSignatures ?. size ? emitSignatures : undefined ,
2321
2362
hasErrors : buildInfo . errors ,
2322
2363
checkPending : buildInfo . checkPending ,
2364
+ packageJsons : toPackageJsons ( ) ,
2323
2365
} ;
2324
2366
}
2325
2367
@@ -2389,6 +2431,10 @@ export function createBuilderProgramUsingIncrementalBuildInfo(
2389
2431
function toPerFileEmitDiagnostics ( diagnostics : readonly IncrementalBuildInfoEmitDiagnostic [ ] | undefined ) : Map < Path , readonly ReusableDiagnostic [ ] > | undefined {
2390
2432
return diagnostics && arrayToMap ( diagnostics , value => toFilePath ( value [ 0 ] ) , value => value [ 1 ] ) ;
2391
2433
}
2434
+
2435
+ function toPackageJsons ( ) {
2436
+ return buildInfo . packageJsons ?. map ( toAbsolutePath ) as unknown as SortedReadonlyArray < string > ?? emptyArray ;
2437
+ }
2392
2438
}
2393
2439
2394
2440
/** @internal */
0 commit comments