@@ -547,14 +547,24 @@ export class FSProvider {
547547 public existsSync ( filePath : string ) : boolean {
548548 return fs . existsSync ( filePath ) ;
549549 }
550+ public statSync ( filePath : string ) : fs . Stats {
551+ return fs . statSync ( filePath ) ;
552+ }
550553 public readFileSync ( _moduleId : string , filePath : string ) : Buffer {
551554 return fs . readFileSync ( filePath ) ;
552555 }
553556}
554557
558+ class CacheEntry {
559+ constructor (
560+ public readonly sourceFile : ts . SourceFile ,
561+ public readonly mtime : number
562+ ) { }
563+ }
564+
555565export class DeclarationResolver {
556566
557- private _sourceFileCache : { [ moduleId : string ] : ts . SourceFile | null ; } ;
567+ private _sourceFileCache : { [ moduleId : string ] : CacheEntry | null ; } ;
558568
559569 constructor ( private readonly _fsProvider : FSProvider ) {
560570 this . _sourceFileCache = Object . create ( null ) ;
@@ -565,32 +575,51 @@ export class DeclarationResolver {
565575 }
566576
567577 public getDeclarationSourceFile ( moduleId : string ) : ts . SourceFile | null {
578+ if ( this . _sourceFileCache [ moduleId ] ) {
579+ // Since we cannot trust file watching to invalidate the cache, check also the mtime
580+ const fileName = this . _getFileName ( moduleId ) ;
581+ const mtime = this . _fsProvider . statSync ( fileName ) . mtime . getTime ( ) ;
582+ if ( this . _sourceFileCache [ moduleId ] ! . mtime !== mtime ) {
583+ this . _sourceFileCache [ moduleId ] = null ;
584+ }
585+ }
568586 if ( ! this . _sourceFileCache [ moduleId ] ) {
569587 this . _sourceFileCache [ moduleId ] = this . _getDeclarationSourceFile ( moduleId ) ;
570588 }
571- return this . _sourceFileCache [ moduleId ] ;
589+ return this . _sourceFileCache [ moduleId ] ? this . _sourceFileCache [ moduleId ] ! . sourceFile : null ;
572590 }
573591
574- private _getDeclarationSourceFile ( moduleId : string ) : ts . SourceFile | null {
592+ private _getFileName ( moduleId : string ) : string {
575593 if ( / \. d \. t s $ / . test ( moduleId ) ) {
576- const fileName = path . join ( SRC , moduleId ) ;
577- if ( ! this . _fsProvider . existsSync ( fileName ) ) {
578- return null ;
579- }
580- const fileContents = this . _fsProvider . readFileSync ( moduleId , fileName ) . toString ( ) ;
581- return ts . createSourceFile ( fileName , fileContents , ts . ScriptTarget . ES5 ) ;
594+ return path . join ( SRC , moduleId ) ;
582595 }
583- const fileName = path . join ( SRC , `${ moduleId } .ts` ) ;
596+ return path . join ( SRC , `${ moduleId } .ts` ) ;
597+ }
598+
599+ private _getDeclarationSourceFile ( moduleId : string ) : CacheEntry | null {
600+ const fileName = this . _getFileName ( moduleId ) ;
584601 if ( ! this . _fsProvider . existsSync ( fileName ) ) {
585602 return null ;
586603 }
604+ const mtime = this . _fsProvider . statSync ( fileName ) . mtime . getTime ( ) ;
605+ if ( / \. d \. t s $ / . test ( moduleId ) ) {
606+ // const mtime = this._fsProvider.statFileSync()
607+ const fileContents = this . _fsProvider . readFileSync ( moduleId , fileName ) . toString ( ) ;
608+ return new CacheEntry (
609+ ts . createSourceFile ( fileName , fileContents , ts . ScriptTarget . ES5 ) ,
610+ mtime
611+ ) ;
612+ }
587613 const fileContents = this . _fsProvider . readFileSync ( moduleId , fileName ) . toString ( ) ;
588614 const fileMap : IFileMap = {
589615 'file.ts' : fileContents
590616 } ;
591617 const service = ts . createLanguageService ( new TypeScriptLanguageServiceHost ( { } , fileMap , { } ) ) ;
592618 const text = service . getEmitOutput ( 'file.ts' , true ) . outputFiles [ 0 ] . text ;
593- return ts . createSourceFile ( fileName , text , ts . ScriptTarget . ES5 ) ;
619+ return new CacheEntry (
620+ ts . createSourceFile ( fileName , text , ts . ScriptTarget . ES5 ) ,
621+ mtime
622+ ) ;
594623 }
595624}
596625
0 commit comments