@@ -661,10 +661,14 @@ namespace ts {
661
661
configFileParseResult . errors ;
662
662
}
663
663
664
+ function isProgramFromBuildInfo ( program : Program | ProgramFromBuildInfo ) : program is ProgramFromBuildInfo {
665
+ return ! ! ( program as ProgramFromBuildInfo ) . programFromBuildInfo ;
666
+ }
667
+
664
668
/**
665
669
* Determine if source file needs to be re-created even if its text hasn't changed
666
670
*/
667
- function shouldProgramCreateNewSourceFiles ( program : Program | undefined , newOptions : CompilerOptions ) : boolean {
671
+ function shouldProgramCreateNewSourceFiles ( program : Program | ProgramFromBuildInfo | undefined , newOptions : CompilerOptions ) : boolean {
668
672
if ( ! program ) return false ;
669
673
// If any compiler options change, we can't reuse old source file even if version match
670
674
// The change in options like these could result in change in syntax tree or `sourceFile.bindDiagnostics`.
@@ -692,6 +696,8 @@ namespace ts {
692
696
* @returns A 'Program' object.
693
697
*/
694
698
export function createProgram ( createProgramOptions : CreateProgramOptions ) : Program ;
699
+ /*@internal */
700
+ export function createProgram ( createProgramOptions : CreateProgramOptionsWithProgramFromBuildInfo ) : Program ; // eslint-disable-line @typescript-eslint/unified-signatures
695
701
/**
696
702
* Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
697
703
* that represent a compilation unit.
@@ -707,7 +713,7 @@ namespace ts {
707
713
* @returns A 'Program' object.
708
714
*/
709
715
export function createProgram ( rootNames : readonly string [ ] , options : CompilerOptions , host ?: CompilerHost , oldProgram ?: Program , configFileParsingDiagnostics ?: readonly Diagnostic [ ] ) : Program ;
710
- export function createProgram ( rootNamesOrOptions : readonly string [ ] | CreateProgramOptions , _options ?: CompilerOptions , _host ?: CompilerHost , _oldProgram ?: Program , _configFileParsingDiagnostics ?: readonly Diagnostic [ ] ) : Program {
716
+ export function createProgram ( rootNamesOrOptions : readonly string [ ] | CreateProgramOptions | CreateProgramOptionsWithProgramFromBuildInfo , _options ?: CompilerOptions , _host ?: CompilerHost , _oldProgram ?: Program , _configFileParsingDiagnostics ?: readonly Diagnostic [ ] ) : Program {
711
717
const createProgramOptions = isArray ( rootNamesOrOptions ) ? createCreateProgramOptions ( rootNamesOrOptions , _options ! , _host , _oldProgram , _configFileParsingDiagnostics ) : rootNamesOrOptions ; // TODO: GH#18217
712
718
const { rootNames, options, configFileParsingDiagnostics, projectReferences } = createProgramOptions ;
713
719
let { oldProgram } = createProgramOptions ;
@@ -812,7 +818,7 @@ namespace ts {
812
818
// Map from a stringified PackageId to the source file with that id.
813
819
// Only one source file may have a given packageId. Others become redirects (see createRedirectSourceFile).
814
820
// `packageIdToSourceFile` is only used while building the program, while `sourceFileToPackageName` and `isSourceFileTargetOfRedirect` are kept around.
815
- const packageIdToSourceFile = new Map < string , SourceFile > ( ) ;
821
+ let packageIdToSourceFile = new Map < string , SourceFile > ( ) ;
816
822
// Maps from a SourceFile's `.path` to the name of the package it was imported with.
817
823
let sourceFileToPackageName = new Map < string , string > ( ) ;
818
824
// Key is a file name. Value is the (non-empty, or undefined) list of files that redirect to it.
@@ -824,11 +830,11 @@ namespace ts {
824
830
* - false if sourceFile missing for source of project reference redirect
825
831
* - undefined otherwise
826
832
*/
827
- const filesByName = new Map < string , SourceFile | false | 0 > ( ) ;
833
+ const filesByName = new Map < Path , SourceFile | false | 0 > ( ) ;
828
834
let missingFilePaths : readonly Path [ ] | undefined ;
829
835
// stores 'filename -> file association' ignoring case
830
836
// used to track cases when two file names differ only in casing
831
- const filesByNameIgnoreCase = host . useCaseSensitiveFileNames ( ) ? new Map < string , SourceFile > ( ) : undefined ;
837
+ let filesByNameIgnoreCase = host . useCaseSensitiveFileNames ( ) ? new Map < string , SourceFile > ( ) : undefined ;
832
838
833
839
// A parallel array to projectReferences storing the results of reading in the referenced tsconfig files
834
840
let resolvedProjectReferences : readonly ( ResolvedProjectReference | undefined ) [ ] | undefined ;
@@ -921,17 +927,19 @@ namespace ts {
921
927
}
922
928
}
923
929
924
- missingFilePaths = arrayFrom ( mapDefinedIterator ( filesByName . entries ( ) , ( [ path , file ] ) => file === 0 ? path as Path : undefined ) ) ;
930
+ missingFilePaths = arrayFrom ( mapDefinedIterator ( filesByName . entries ( ) , ( [ path , file ] ) => file === 0 ? path : undefined ) ) ;
925
931
files = stableSort ( processingDefaultLibFiles , compareDefaultLibFiles ) . concat ( processingOtherFiles ) ;
926
932
processingDefaultLibFiles = undefined ;
927
933
processingOtherFiles = undefined ;
934
+ packageIdToSourceFile = undefined ! ;
935
+ filesByNameIgnoreCase = undefined ! ;
928
936
}
929
937
930
938
Debug . assert ( ! ! missingFilePaths ) ;
931
939
932
940
// Release any files we have acquired in the old program but are
933
941
// not part of the new program.
934
- if ( oldProgram && host . onReleaseOldSourceFile ) {
942
+ if ( oldProgram && ! isProgramFromBuildInfo ( oldProgram ) && host . onReleaseOldSourceFile ) {
935
943
const oldSourceFiles = oldProgram . getSourceFiles ( ) ;
936
944
for ( const oldSourceFile of oldSourceFiles ) {
937
945
const newFile = getSourceFileByPath ( oldSourceFile . resolvedPath ) ;
@@ -987,6 +995,7 @@ namespace ts {
987
995
getFileProcessingDiagnostics : ( ) => fileProcessingDiagnostics ,
988
996
getResolvedTypeReferenceDirectives : ( ) => resolvedTypeReferenceDirectives ,
989
997
isSourceFileFromExternalLibrary,
998
+ isSourceFileFromExternalLibraryPath,
990
999
isSourceFileDefaultLibrary,
991
1000
dropDiagnosticsProducingTypeChecker,
992
1001
getSourceFileFromReference,
@@ -1283,13 +1292,13 @@ namespace ts {
1283
1292
}
1284
1293
1285
1294
function canReuseProjectReferences ( ) : boolean {
1286
- let seenResolvedRefs : ResolvedProjectReference [ ] | undefined ;
1295
+ let seenResolvedRefs : ResolvedProjectReferenceOfProgramFromBuildInfo [ ] | undefined ;
1287
1296
return ! hasChangedReferences ( oldProgram ! . getProjectReferences ( ) , oldProgram ! . getResolvedProjectReferences ( ) , /*parent*/ undefined ) ;
1288
1297
1289
1298
function hasChangedReferences (
1290
1299
oldProjectReferences : readonly ProjectReference [ ] | undefined ,
1291
- oldResolvedProjectReferences : readonly ( ResolvedProjectReference | undefined ) [ ] | undefined ,
1292
- parent : ResolvedProjectReference | undefined ,
1300
+ oldResolvedProjectReferences : readonly ( ResolvedProjectReferenceOfProgramFromBuildInfo | undefined ) [ ] | undefined ,
1301
+ parent : ResolvedProjectReferenceOfProgramFromBuildInfo | undefined ,
1293
1302
) : boolean | undefined {
1294
1303
1295
1304
// Visit project references first
@@ -1310,13 +1319,13 @@ namespace ts {
1310
1319
}
1311
1320
}
1312
1321
1313
- function hasChangedProjectReferences ( oldProjectReferences : readonly ProjectReference [ ] | undefined , parent : ResolvedProjectReference | undefined ) {
1322
+ function hasChangedProjectReferences ( oldProjectReferences : readonly ProjectReference [ ] | undefined , parent : ResolvedProjectReferenceOfProgramFromBuildInfo | undefined ) {
1314
1323
// If array of references is changed, we cant resue old program
1315
1324
const newReferences = parent ? getResolvedProjectReferenceByPath ( parent . sourceFile . path ) ! . commandLine . projectReferences : projectReferences ;
1316
1325
return ! arrayIsEqualTo ( oldProjectReferences , newReferences , projectReferenceIsEqualTo ) ;
1317
1326
}
1318
1327
1319
- function hasChangedResolvedProjectReferences ( oldResolvedRef : ResolvedProjectReference | undefined , index : number , parent : ResolvedProjectReference | undefined ) {
1328
+ function hasChangedResolvedProjectReferences ( oldResolvedRef : ResolvedProjectReferenceOfProgramFromBuildInfo | undefined , index : number , parent : ResolvedProjectReferenceOfProgramFromBuildInfo | undefined ) {
1320
1329
const newRef = ( parent ? parent . commandLine . projectReferences : projectReferences ) ! [ index ] ;
1321
1330
const newResolvedRef = parseProjectReferenceConfigFile ( newRef ) ;
1322
1331
if ( oldResolvedRef ) {
@@ -1395,7 +1404,7 @@ namespace ts {
1395
1404
return StructureIsReused . Not ;
1396
1405
}
1397
1406
// redirect target should already be present
1398
- Debug . checkDefined ( find ( newSourceFiles , f => f . path === oldSourceFile . redirectInfo ? .redirectTarget . path ) ) ;
1407
+ Debug . checkDefined ( find ( newSourceFiles , f => f . path === oldSourceFile . redirectInfo ! . redirectTarget . path ) ) ;
1399
1408
// Add to the newSourceFiles for now and handle redirect if program is used completely
1400
1409
newSourceFiles . push ( newSourceFile ) ;
1401
1410
continue ;
@@ -1544,8 +1553,8 @@ namespace ts {
1544
1553
const oldSourceFile = oldProgram ! . getSourceFiles ( ) [ index ] ;
1545
1554
if ( oldSourceFile . redirectInfo ) {
1546
1555
const newRedirectTarget = filesByName . get ( oldSourceFile . redirectInfo . redirectTarget . path ) as SourceFile ;
1547
- newSourceFile = newRedirectTarget === oldSourceFile . redirectInfo . redirectTarget ?
1548
- oldSourceFile :
1556
+ newSourceFile = ! isProgramFromBuildInfo ( oldProgram ! ) && newRedirectTarget === oldSourceFile . redirectInfo . redirectTarget ?
1557
+ oldSourceFile as SourceFile :
1549
1558
// Create new redirect file
1550
1559
createRedirectSourceFile ( newRedirectTarget , newSourceFile , oldSourceFile . fileName , oldSourceFile . path , oldSourceFile . resolvedPath , oldSourceFile . originalFileName ) ;
1551
1560
newSourceFiles [ index ] = newSourceFile ;
@@ -1555,27 +1564,43 @@ namespace ts {
1555
1564
filesByName . set ( newSourceFile . path , newSourceFile ) ;
1556
1565
}
1557
1566
} ) ;
1558
- const oldFilesByNameMap = oldProgram . getFilesByNameMap ( ) ;
1567
+ const oldFilesByNameMap = oldProgram . getFilesByNameMap ( ) as ESMap < Path , SourceFile | Path | false | 0 > ;
1559
1568
oldFilesByNameMap . forEach ( ( oldFile , path ) => {
1560
1569
if ( ! oldFile ) {
1561
- filesByName . set ( path , oldFile ) ;
1570
+ filesByName . set ( path , oldFile as false | 0 ) ;
1562
1571
return ;
1563
1572
}
1564
- if ( oldFile . path === path ) {
1573
+ const oldPath = ! isString ( oldFile ) ? oldFile . path : oldFile ;
1574
+ if ( oldPath === path ) {
1565
1575
// Set the file as found during node modules search if it was found that way in old progra,
1566
- if ( oldProgram ! . isSourceFileFromExternalLibrary ( oldFile ) ) {
1567
- sourceFilesFoundSearchingNodeModules . set ( oldFile . path , true ) ;
1576
+ if ( oldProgram ! . isSourceFileFromExternalLibraryPath ( oldPath ) ) {
1577
+ sourceFilesFoundSearchingNodeModules . set ( oldPath , true ) ;
1568
1578
}
1569
1579
return ;
1570
1580
}
1571
- filesByName . set ( path , filesByName . get ( oldFile . path ) ! ) ;
1581
+ filesByName . set ( path , filesByName . get ( oldPath ) ! ) ;
1572
1582
} ) ;
1573
1583
1574
1584
files = newSourceFiles ;
1575
- fileProcessingDiagnostics = oldProgram . getFileProcessingDiagnostics ( ) ;
1576
1585
1577
- for ( const modifiedFile of modifiedSourceFiles || emptyArray ) {
1578
- fileProcessingDiagnostics . reattachFileDiagnostics ( modifiedFile ) ;
1586
+ if ( ! isProgramFromBuildInfo ( oldProgram ) ) {
1587
+ fileProcessingDiagnostics = oldProgram . getFileProcessingDiagnostics ( ) ;
1588
+ for ( const modifiedFile of modifiedSourceFiles || emptyArray ) {
1589
+ fileProcessingDiagnostics . reattachFileDiagnostics ( modifiedFile ) ;
1590
+ }
1591
+ }
1592
+ else {
1593
+ convertToDiagnostics (
1594
+ oldProgram . getFileProcessingDiagnostics ( ) ,
1595
+ {
1596
+ getCurrentDirectory : ( ) => currentDirectory ,
1597
+ getCompilerOptions : ( ) => options ,
1598
+ getSourceFileByPath
1599
+ } ,
1600
+ getCanonicalFileName
1601
+ ) . forEach (
1602
+ d => fileProcessingDiagnostics . add ( d )
1603
+ ) ;
1579
1604
}
1580
1605
resolvedTypeReferenceDirectives = oldProgram . getResolvedTypeReferenceDirectives ( ) ;
1581
1606
perFileModuleResolutions = oldProgram . getPerFileModuleResolutions ( ) ;
@@ -1665,7 +1690,11 @@ namespace ts {
1665
1690
}
1666
1691
1667
1692
function isSourceFileFromExternalLibrary ( file : SourceFile ) : boolean {
1668
- return ! ! sourceFilesFoundSearchingNodeModules . get ( file . path ) ;
1693
+ return isSourceFileFromExternalLibraryPath ( file . path ) ;
1694
+ }
1695
+
1696
+ function isSourceFileFromExternalLibraryPath ( file : Path ) : boolean {
1697
+ return ! ! sourceFilesFoundSearchingNodeModules . get ( file ) ;
1669
1698
}
1670
1699
1671
1700
function isSourceFileDefaultLibrary ( file : SourceFile ) : boolean {
@@ -2215,14 +2244,14 @@ namespace ts {
2215
2244
processSourceFile ( normalizePath ( fileName ) , isDefaultLib , ignoreNoDefaultLib , /*packageId*/ undefined ) ;
2216
2245
}
2217
2246
2218
- function fileReferenceIsEqualTo ( a : FileReference , b : FileReference ) : boolean {
2219
- return a . fileName === b . fileName ;
2247
+ function fileReferenceIsEqualTo ( oldReference : FileReference | string , newReference : FileReference ) : boolean {
2248
+ return ( ! isString ( oldReference ) ? oldReference . fileName : oldReference ) === newReference . fileName ;
2220
2249
}
2221
2250
2222
- function moduleNameIsEqualTo ( a : StringLiteralLike | Identifier , b : StringLiteralLike | Identifier ) : boolean {
2223
- return a . kind === SyntaxKind . Identifier
2224
- ? b . kind === SyntaxKind . Identifier && a . escapedText === b . escapedText
2225
- : b . kind === SyntaxKind . StringLiteral && a . text === b . text ;
2251
+ function moduleNameIsEqualTo ( oldName : StringLiteralLike | Identifier | ModuleNameOfProgramFromBuildInfo , newName : StringLiteralLike | Identifier ) : boolean {
2252
+ return oldName . kind === SyntaxKind . Identifier
2253
+ ? newName . kind === SyntaxKind . Identifier && oldName . escapedText === newName . escapedText
2254
+ : newName . kind === SyntaxKind . StringLiteral && oldName . text === newName . text ;
2226
2255
}
2227
2256
2228
2257
function collectExternalModuleReferences ( file : SourceFile ) : void {
0 commit comments