@@ -656,46 +656,33 @@ namespace ts {
656656 fileExists : ( fileName : string ) => boolean ,
657657 hasInvalidatedResolution : HasInvalidatedResolution ,
658658 hasChangedAutomaticTypeDirectiveNames : HasChangedAutomaticTypeDirectiveNames | undefined ,
659+ getParsedCommandLine : ( fileName : string ) => ParsedCommandLine | undefined ,
659660 projectReferences : readonly ProjectReference [ ] | undefined
660661 ) : boolean {
661662 // If we haven't created a program yet or have changed automatic type directives, then it is not up-to-date
662- if ( ! program || hasChangedAutomaticTypeDirectiveNames ?.( ) ) {
663- return false ;
664- }
663+ if ( ! program || hasChangedAutomaticTypeDirectiveNames ?.( ) ) return false ;
665664
666665 // If root file names don't match
667- if ( ! arrayIsEqualTo ( program . getRootFileNames ( ) , rootFileNames ) ) {
668- return false ;
669- }
666+ if ( ! arrayIsEqualTo ( program . getRootFileNames ( ) , rootFileNames ) ) return false ;
670667
671668 let seenResolvedRefs : ResolvedProjectReference [ ] | undefined ;
672669
673670 // If project references don't match
674- if ( ! arrayIsEqualTo ( program . getProjectReferences ( ) , projectReferences , projectReferenceUptoDate ) ) {
675- return false ;
676- }
671+ if ( ! arrayIsEqualTo ( program . getProjectReferences ( ) , projectReferences , projectReferenceUptoDate ) ) return false ;
677672
678673 // If any file is not up-to-date, then the whole program is not up-to-date
679- if ( program . getSourceFiles ( ) . some ( sourceFileNotUptoDate ) ) {
680- return false ;
681- }
674+ if ( program . getSourceFiles ( ) . some ( sourceFileNotUptoDate ) ) return false ;
682675
683676 // If any of the missing file paths are now created
684- if ( program . getMissingFilePaths ( ) . some ( fileExists ) ) {
685- return false ;
686- }
677+ if ( program . getMissingFilePaths ( ) . some ( fileExists ) ) return false ;
687678
688679 const currentOptions = program . getCompilerOptions ( ) ;
689680 // If the compilation settings do no match, then the program is not up-to-date
690- if ( ! compareDataObjects ( currentOptions , newOptions ) ) {
691- return false ;
692- }
681+ if ( ! compareDataObjects ( currentOptions , newOptions ) ) return false ;
693682
694683 // If everything matches but the text of config file is changed,
695684 // error locations can change for program options, so update the program
696- if ( currentOptions . configFile && newOptions . configFile ) {
697- return currentOptions . configFile . text === newOptions . configFile . text ;
698- }
685+ if ( currentOptions . configFile && newOptions . configFile ) return currentOptions . configFile . text === newOptions . configFile . text ;
699686
700687 return true ;
701688
@@ -709,23 +696,26 @@ namespace ts {
709696 }
710697
711698 function projectReferenceUptoDate ( oldRef : ProjectReference , newRef : ProjectReference , index : number ) {
712- if ( ! projectReferenceIsEqualTo ( oldRef , newRef ) ) {
713- return false ;
714- }
715- return resolvedProjectReferenceUptoDate ( program ! . getResolvedProjectReferences ( ) ! [ index ] , oldRef ) ;
699+ return projectReferenceIsEqualTo ( oldRef , newRef ) &&
700+ resolvedProjectReferenceUptoDate ( program ! . getResolvedProjectReferences ( ) ! [ index ] , oldRef ) ;
716701 }
717702
718703 function resolvedProjectReferenceUptoDate ( oldResolvedRef : ResolvedProjectReference | undefined , oldRef : ProjectReference ) : boolean {
719704 if ( oldResolvedRef ) {
720- if ( contains ( seenResolvedRefs , oldResolvedRef ) ) {
721705 // Assume true
722- return true ;
723- }
706+ if ( contains ( seenResolvedRefs , oldResolvedRef ) ) return true ;
724707
725- // If sourceFile for the oldResolvedRef existed, check the version for uptodate
726- if ( ! sourceFileVersionUptoDate ( oldResolvedRef . sourceFile ) ) {
727- return false ;
728- }
708+ const refPath = resolveProjectReferencePath ( oldRef ) ;
709+ const newParsedCommandLine = getParsedCommandLine ( refPath ) ;
710+
711+ // Check if config file exists
712+ if ( ! newParsedCommandLine ) return false ;
713+
714+ // If change in source file
715+ if ( oldResolvedRef . commandLine . options . configFile !== newParsedCommandLine . options . configFile ) return false ;
716+
717+ // check file names
718+ if ( ! arrayIsEqualTo ( oldResolvedRef . commandLine . fileNames , newParsedCommandLine . fileNames ) ) return false ;
729719
730720 // Add to seen before checking the referenced paths of this config file
731721 ( seenResolvedRefs || ( seenResolvedRefs = [ ] ) ) . push ( oldResolvedRef ) ;
@@ -737,7 +727,8 @@ namespace ts {
737727
738728 // In old program, not able to resolve project reference path,
739729 // so if config file doesnt exist, it is uptodate.
740- return ! fileExists ( resolveProjectReferencePath ( oldRef ) ) ;
730+ const refPath = resolveProjectReferencePath ( oldRef ) ;
731+ return ! getParsedCommandLine ( refPath ) ;
741732 }
742733 }
743734
@@ -1021,11 +1012,28 @@ namespace ts {
10211012 host . onReleaseOldSourceFile ( oldSourceFile , oldProgram . getCompilerOptions ( ) , ! ! getSourceFileByPath ( oldSourceFile . path ) ) ;
10221013 }
10231014 }
1024- oldProgram . forEachResolvedProjectReference ( resolvedProjectReference => {
1025- if ( ! getResolvedProjectReferenceByPath ( resolvedProjectReference . sourceFile . path ) ) {
1026- host . onReleaseOldSourceFile ! ( resolvedProjectReference . sourceFile , oldProgram ! . getCompilerOptions ( ) , /*hasSourceFileByPath*/ false ) ;
1015+ if ( ! host . getParsedCommandLine ) {
1016+ oldProgram . forEachResolvedProjectReference ( resolvedProjectReference => {
1017+ if ( ! getResolvedProjectReferenceByPath ( resolvedProjectReference . sourceFile . path ) ) {
1018+ host . onReleaseOldSourceFile ! ( resolvedProjectReference . sourceFile , oldProgram ! . getCompilerOptions ( ) , /*hasSourceFileByPath*/ false ) ;
1019+ }
1020+ } ) ;
1021+ }
1022+ }
1023+
1024+ // Release commandlines that new program does not use
1025+ if ( oldProgram && host . onReleaseParsedCommandLine ) {
1026+ forEachProjectReference (
1027+ oldProgram . getProjectReferences ( ) ,
1028+ oldProgram . getResolvedProjectReferences ( ) ,
1029+ ( oldResolvedRef , parent , index ) => {
1030+ const oldReference = parent ?. commandLine . projectReferences ! [ index ] || oldProgram ! . getProjectReferences ( ) ! [ index ] ;
1031+ const oldRefPath = resolveProjectReferencePath ( oldReference ) ;
1032+ if ( ! projectReferenceRedirects ?. has ( toPath ( oldRefPath ) ) ) {
1033+ host . onReleaseParsedCommandLine ! ( oldRefPath , oldResolvedRef , oldProgram ! . getCompilerOptions ( ) ) ;
1034+ }
10271035 }
1028- } ) ;
1036+ ) ;
10291037 }
10301038
10311039 // unconditionally set oldProgram to undefined to prevent it from being captured in closure
@@ -1367,7 +1375,9 @@ namespace ts {
13671375 const newResolvedRef = parseProjectReferenceConfigFile ( newRef ) ;
13681376 if ( oldResolvedRef ) {
13691377 // Resolved project reference has gone missing or changed
1370- return ! newResolvedRef || newResolvedRef . sourceFile !== oldResolvedRef . sourceFile ;
1378+ return ! newResolvedRef ||
1379+ newResolvedRef . sourceFile !== oldResolvedRef . sourceFile ||
1380+ ! arrayIsEqualTo ( oldResolvedRef . commandLine . fileNames , newResolvedRef . commandLine . fileNames ) ;
13711381 }
13721382 else {
13731383 // A previously-unresolved reference may be resolved now
0 commit comments