@@ -280,6 +280,18 @@ namespace ts {
280
280
}
281
281
}
282
282
283
+ export function setCreateSourceFileAsHashVersioned ( compilerHost : CompilerHost , host : ProgramHost < any > ) {
284
+ const originalGetSourceFile = compilerHost . getSourceFile ;
285
+ const computeHash = host . createHash || generateDjb2Hash ;
286
+ compilerHost . getSourceFile = ( ...args ) => {
287
+ const result = originalGetSourceFile . call ( compilerHost , ...args ) ;
288
+ if ( result ) {
289
+ result . version = computeHash . call ( host , result . text ) ;
290
+ }
291
+ return result ;
292
+ } ;
293
+ }
294
+
283
295
/**
284
296
* Creates the watch compiler host that can be extended with config file or root file names and options host
285
297
*/
@@ -524,8 +536,6 @@ namespace ts {
524
536
}
525
537
}
526
538
527
- const initialVersion = 1 ;
528
-
529
539
/**
530
540
* Creates the watch from the host for root files and compiler options
531
541
*/
@@ -536,13 +546,14 @@ namespace ts {
536
546
export function createWatchProgram < T extends BuilderProgram > ( host : WatchCompilerHostOfConfigFile < T > ) : WatchOfConfigFile < T > ;
537
547
export function createWatchProgram < T extends BuilderProgram > ( host : WatchCompilerHostOfFilesAndCompilerOptions < T > & WatchCompilerHostOfConfigFile < T > ) : WatchOfFilesAndCompilerOptions < T > | WatchOfConfigFile < T > {
538
548
interface FilePresentOnHost {
539
- version : number ;
549
+ version : string ;
540
550
sourceFile : SourceFile ;
541
551
fileWatcher : FileWatcher ;
542
552
}
543
- type FileMissingOnHost = number ;
553
+ type FileMissingOnHost = false ;
544
554
interface FilePresenceUnknownOnHost {
545
- version : number ;
555
+ version : false ;
556
+ fileWatcher ?: FileWatcher ;
546
557
}
547
558
type FileMayBePresentOnHost = FilePresentOnHost | FilePresenceUnknownOnHost ;
548
559
type HostFileInfo = FilePresentOnHost | FileMissingOnHost | FilePresenceUnknownOnHost ;
@@ -597,6 +608,7 @@ namespace ts {
597
608
}
598
609
599
610
const compilerHost = createCompilerHostFromProgramHost ( host , ( ) => compilerOptions , directoryStructureHost ) as CompilerHost & ResolutionCacheHost ;
611
+ setCreateSourceFileAsHashVersioned ( compilerHost , host ) ;
600
612
// Members for CompilerHost
601
613
const getNewSourceFile = compilerHost . getSourceFile ;
602
614
compilerHost . getSourceFile = ( fileName , ...args ) => getVersionedSourceFileByPath ( fileName , toPath ( fileName ) , ...args ) ;
@@ -731,64 +743,59 @@ namespace ts {
731
743
return ts . toPath ( fileName , currentDirectory , getCanonicalFileName ) ;
732
744
}
733
745
734
- function isFileMissingOnHost ( hostSourceFile : HostFileInfo ) : hostSourceFile is FileMissingOnHost {
735
- return typeof hostSourceFile === "number " ;
746
+ function isFileMissingOnHost ( hostSourceFile : HostFileInfo | undefined ) : hostSourceFile is FileMissingOnHost {
747
+ return typeof hostSourceFile === "boolean " ;
736
748
}
737
749
738
- function isFilePresentOnHost ( hostSourceFile : FileMayBePresentOnHost ) : hostSourceFile is FilePresentOnHost {
739
- return ! ! ( hostSourceFile as FilePresentOnHost ) . sourceFile ;
750
+ function isFilePresenceUnknownOnHost ( hostSourceFile : FileMayBePresentOnHost ) : hostSourceFile is FilePresenceUnknownOnHost {
751
+ return typeof ( hostSourceFile as FilePresenceUnknownOnHost ) . version === "boolean" ;
740
752
}
741
753
742
754
function fileExists ( fileName : string ) {
743
755
const path = toPath ( fileName ) ;
744
756
// If file is missing on host from cache, we can definitely say file doesnt exist
745
757
// otherwise we need to ensure from the disk
746
- if ( isFileMissingOnHost ( sourceFilesCache . get ( path ) ! ) ) {
758
+ if ( isFileMissingOnHost ( sourceFilesCache . get ( path ) ) ) {
747
759
return true ;
748
760
}
749
761
750
762
return directoryStructureHost . fileExists ( fileName ) ;
751
763
}
752
764
753
765
function getVersionedSourceFileByPath ( fileName : string , path : Path , languageVersion : ScriptTarget , onError ?: ( message : string ) => void , shouldCreateNewSourceFile ?: boolean ) : SourceFile | undefined {
754
- const hostSourceFile = sourceFilesCache . get ( path ) ! ;
766
+ const hostSourceFile = sourceFilesCache . get ( path ) ;
755
767
// No source file on the host
756
768
if ( isFileMissingOnHost ( hostSourceFile ) ) {
757
769
return undefined ;
758
770
}
759
771
760
772
// Create new source file if requested or the versions dont match
761
- if ( ! hostSourceFile || shouldCreateNewSourceFile || ! isFilePresentOnHost ( hostSourceFile ) || hostSourceFile . version . toString ( ) !== hostSourceFile . sourceFile . version ) {
773
+ if ( hostSourceFile === undefined || shouldCreateNewSourceFile || isFilePresenceUnknownOnHost ( hostSourceFile ) ) {
762
774
const sourceFile = getNewSourceFile ( fileName , languageVersion , onError ) ;
763
775
if ( hostSourceFile ) {
764
- if ( shouldCreateNewSourceFile ) {
765
- hostSourceFile . version ++ ;
766
- }
767
-
768
776
if ( sourceFile ) {
769
777
// Set the source file and create file watcher now that file was present on the disk
770
778
( hostSourceFile as FilePresentOnHost ) . sourceFile = sourceFile ;
771
- sourceFile . version = hostSourceFile . version . toString ( ) ;
772
- if ( ! ( hostSourceFile as FilePresentOnHost ) . fileWatcher ) {
773
- ( hostSourceFile as FilePresentOnHost ) . fileWatcher = watchFilePath ( host , fileName , onSourceFileChange , PollingInterval . Low , path , WatchType . SourceFile ) ;
779
+ hostSourceFile . version = sourceFile . version ;
780
+ if ( ! hostSourceFile . fileWatcher ) {
781
+ hostSourceFile . fileWatcher = watchFilePath ( host , fileName , onSourceFileChange , PollingInterval . Low , path , WatchType . SourceFile ) ;
774
782
}
775
783
}
776
784
else {
777
785
// There is no source file on host any more, close the watch, missing file paths will track it
778
- if ( isFilePresentOnHost ( hostSourceFile ) ) {
786
+ if ( hostSourceFile . fileWatcher ) {
779
787
hostSourceFile . fileWatcher . close ( ) ;
780
788
}
781
- sourceFilesCache . set ( path , hostSourceFile . version ) ;
789
+ sourceFilesCache . set ( path , false ) ;
782
790
}
783
791
}
784
792
else {
785
793
if ( sourceFile ) {
786
- sourceFile . version = initialVersion . toString ( ) ;
787
794
const fileWatcher = watchFilePath ( host , fileName , onSourceFileChange , PollingInterval . Low , path , WatchType . SourceFile ) ;
788
- sourceFilesCache . set ( path , { sourceFile, version : initialVersion , fileWatcher } ) ;
795
+ sourceFilesCache . set ( path , { sourceFile, version : sourceFile . version , fileWatcher } ) ;
789
796
}
790
797
else {
791
- sourceFilesCache . set ( path , initialVersion ) ;
798
+ sourceFilesCache . set ( path , false ) ;
792
799
}
793
800
}
794
801
return sourceFile ;
@@ -801,17 +808,17 @@ namespace ts {
801
808
if ( hostSourceFile !== undefined ) {
802
809
if ( isFileMissingOnHost ( hostSourceFile ) ) {
803
810
// The next version, lets set it as presence unknown file
804
- sourceFilesCache . set ( path , { version : Number ( hostSourceFile ) + 1 } ) ;
811
+ sourceFilesCache . set ( path , { version : false } ) ;
805
812
}
806
813
else {
807
- hostSourceFile . version ++ ;
814
+ ( hostSourceFile as FilePresenceUnknownOnHost ) . version = false ;
808
815
}
809
816
}
810
817
}
811
818
812
819
function getSourceVersion ( path : Path ) : string | undefined {
813
820
const hostSourceFile = sourceFilesCache . get ( path ) ;
814
- return ! hostSourceFile || isFileMissingOnHost ( hostSourceFile ) ? undefined : hostSourceFile . version . toString ( ) ;
821
+ return ! hostSourceFile || ! hostSourceFile . version ? undefined : hostSourceFile . version ;
815
822
}
816
823
817
824
function onReleaseOldSourceFile ( oldSourceFile : SourceFile , _oldOptions : CompilerOptions , hasSourceFileByPath : boolean ) {
@@ -820,14 +827,14 @@ namespace ts {
820
827
// remove the cached entry.
821
828
// Note we arent deleting entry if file became missing in new program or
822
829
// there was version update and new source file was created.
823
- if ( hostSourceFileInfo ) {
830
+ if ( hostSourceFileInfo !== undefined ) {
824
831
// record the missing file paths so they can be removed later if watchers arent tracking them
825
832
if ( isFileMissingOnHost ( hostSourceFileInfo ) ) {
826
833
( missingFilePathsRequestedForRelease || ( missingFilePathsRequestedForRelease = [ ] ) ) . push ( oldSourceFile . path ) ;
827
834
}
828
835
else if ( ( hostSourceFileInfo as FilePresentOnHost ) . sourceFile === oldSourceFile ) {
829
- if ( ( hostSourceFileInfo as FilePresentOnHost ) . fileWatcher ) {
830
- ( hostSourceFileInfo as FilePresentOnHost ) . fileWatcher . close ( ) ;
836
+ if ( hostSourceFileInfo . fileWatcher ) {
837
+ hostSourceFileInfo . fileWatcher . close ( ) ;
831
838
}
832
839
sourceFilesCache . delete ( oldSourceFile . resolvedPath ) ;
833
840
if ( ! hasSourceFileByPath ) {
@@ -924,7 +931,7 @@ namespace ts {
924
931
updateCachedSystemWithFile ( fileName , path , eventKind ) ;
925
932
926
933
// Update the source file cache
927
- if ( eventKind === FileWatcherEventKind . Deleted && sourceFilesCache . get ( path ) ) {
934
+ if ( eventKind === FileWatcherEventKind . Deleted && sourceFilesCache . has ( path ) ) {
928
935
resolutionCache . invalidateResolutionOfFile ( path ) ;
929
936
}
930
937
resolutionCache . removeResolutionsFromProjectReferenceRedirects ( path ) ;
0 commit comments