@@ -10,18 +10,13 @@ namespace ts {
1010 export interface ReusableDiagnosticRelatedInformation {
1111 category : DiagnosticCategory ;
1212 code : number ;
13- file : Path | undefined ;
13+ file : string | undefined ;
1414 start : number | undefined ;
1515 length : number | undefined ;
1616 messageText : string | ReusableDiagnosticMessageChain ;
1717 }
1818
19- export interface ReusableDiagnosticMessageChain {
20- messageText : string ;
21- category : DiagnosticCategory ;
22- code : number ;
23- next ?: ReusableDiagnosticMessageChain ;
24- }
19+ export type ReusableDiagnosticMessageChain = DiagnosticMessageChain ;
2520
2621 export interface ReusableBuilderProgramState extends ReusableBuilderState {
2722 /**
@@ -227,7 +222,7 @@ namespace ts {
227222 // Unchanged file copy diagnostics
228223 const diagnostics = oldState ! . semanticDiagnosticsPerFile ! . get ( sourceFilePath ) ;
229224 if ( diagnostics ) {
230- state . semanticDiagnosticsPerFile ! . set ( sourceFilePath , oldState ! . hasReusableDiagnostic ? convertToDiagnostics ( diagnostics as ReadonlyArray < ReusableDiagnostic > , newProgram ) : diagnostics as ReadonlyArray < Diagnostic > ) ;
225+ state . semanticDiagnosticsPerFile ! . set ( sourceFilePath , oldState ! . hasReusableDiagnostic ? convertToDiagnostics ( diagnostics as ReadonlyArray < ReusableDiagnostic > , newProgram , getCanonicalFileName ) : diagnostics as ReadonlyArray < Diagnostic > ) ;
231226 if ( ! state . semanticDiagnosticsFromOldState ) {
232227 state . semanticDiagnosticsFromOldState = createMap < true > ( ) ;
233228 }
@@ -246,37 +241,32 @@ namespace ts {
246241 return state ;
247242 }
248243
249- function convertToDiagnostics ( diagnostics : ReadonlyArray < ReusableDiagnostic > , newProgram : Program ) : ReadonlyArray < Diagnostic > {
244+ function convertToDiagnostics ( diagnostics : ReadonlyArray < ReusableDiagnostic > , newProgram : Program , getCanonicalFileName : GetCanonicalFileName ) : ReadonlyArray < Diagnostic > {
250245 if ( ! diagnostics . length ) return emptyArray ;
246+ const buildInfoDirectory = getDirectoryPath ( getOutputPathForBuildInfo ( newProgram . getCompilerOptions ( ) ) ! ) ;
251247 return diagnostics . map ( diagnostic => {
252- const result : Diagnostic = convertToDiagnosticRelatedInformation ( diagnostic , newProgram ) ;
248+ const result : Diagnostic = convertToDiagnosticRelatedInformation ( diagnostic , newProgram , toPath ) ;
253249 result . reportsUnnecessary = diagnostic . reportsUnnecessary ;
254250 result . source = diagnostic . source ;
255251 const { relatedInformation } = diagnostic ;
256252 result . relatedInformation = relatedInformation ?
257253 relatedInformation . length ?
258- relatedInformation . map ( r => convertToDiagnosticRelatedInformation ( r , newProgram ) ) :
254+ relatedInformation . map ( r => convertToDiagnosticRelatedInformation ( r , newProgram , toPath ) ) :
259255 emptyArray :
260256 undefined ;
261257 return result ;
262258 } ) ;
263- }
264259
265- function convertToDiagnosticRelatedInformation ( diagnostic : ReusableDiagnosticRelatedInformation , newProgram : Program ) : DiagnosticRelatedInformation {
266- const { file, messageText } = diagnostic ;
267- return {
268- ...diagnostic ,
269- file : file && newProgram . getSourceFileByPath ( file ) ,
270- messageText : messageText === undefined || isString ( messageText ) ?
271- messageText :
272- convertToDiagnosticMessageChain ( messageText , newProgram )
273- } ;
260+ function toPath ( path : string ) {
261+ return ts . toPath ( path , buildInfoDirectory , getCanonicalFileName ) ;
262+ }
274263 }
275264
276- function convertToDiagnosticMessageChain ( diagnostic : ReusableDiagnosticMessageChain , newProgram : Program ) : DiagnosticMessageChain {
265+ function convertToDiagnosticRelatedInformation ( diagnostic : ReusableDiagnosticRelatedInformation , newProgram : Program , toPath : ( path : string ) => Path ) : DiagnosticRelatedInformation {
266+ const { file } = diagnostic ;
277267 return {
278268 ...diagnostic ,
279- next : diagnostic . next && convertToDiagnosticMessageChain ( diagnostic . next , newProgram )
269+ file : file ? newProgram . getSourceFileByPath ( toPath ( file ) ) : undefined
280270 } ;
281271 }
282272
@@ -620,19 +610,20 @@ namespace ts {
620610 /**
621611 * Gets the program information to be emitted in buildInfo so that we can use it to create new program
622612 */
623- function getProgramBuildInfo ( state : Readonly < ReusableBuilderProgramState > ) : ProgramBuildInfo | undefined {
613+ function getProgramBuildInfo ( state : Readonly < ReusableBuilderProgramState > , getCanonicalFileName : GetCanonicalFileName ) : ProgramBuildInfo | undefined {
624614 if ( state . compilerOptions . outFile || state . compilerOptions . out ) return undefined ;
615+ const buildInfoDirectory = getDirectoryPath ( getOutputPathForBuildInfo ( state . compilerOptions ) ! ) ;
625616 const fileInfos : MapLike < BuilderState . FileInfo > = { } ;
626617 state . fileInfos . forEach ( ( value , key ) => {
627618 const signature = state . currentAffectedFilesSignatures && state . currentAffectedFilesSignatures . get ( key ) ;
628- fileInfos [ key ] = signature === undefined ? value : { version : value . version , signature } ;
619+ fileInfos [ relativeToBuildInfo ( key ) ] = signature === undefined ? value : { version : value . version , signature } ;
629620 } ) ;
630621
631622 const result : ProgramBuildInfo = { fileInfos, options : state . compilerOptions } ;
632623 if ( state . referencedMap ) {
633624 const referencedMap : MapLike < string [ ] > = { } ;
634625 state . referencedMap . forEach ( ( value , key ) => {
635- referencedMap [ key ] = arrayFrom ( value . keys ( ) ) ;
626+ referencedMap [ relativeToBuildInfo ( key ) ] = arrayFrom ( value . keys ( ) , relativeToBuildInfo ) ;
636627 } ) ;
637628 result . referencedMap = referencedMap ;
638629 }
@@ -642,9 +633,9 @@ namespace ts {
642633 state . exportedModulesMap . forEach ( ( value , key ) => {
643634 const newValue = state . currentAffectedFilesExportedModulesMap && state . currentAffectedFilesExportedModulesMap . get ( key ) ;
644635 // Not in temporary cache, use existing value
645- if ( newValue === undefined ) exportedModulesMap [ key ] = arrayFrom ( value . keys ( ) ) ;
636+ if ( newValue === undefined ) exportedModulesMap [ relativeToBuildInfo ( key ) ] = arrayFrom ( value . keys ( ) , relativeToBuildInfo ) ;
646637 // Value in cache and has updated value map, use that
647- else if ( newValue ) exportedModulesMap [ key ] = arrayFrom ( newValue . keys ( ) ) ;
638+ else if ( newValue ) exportedModulesMap [ relativeToBuildInfo ( key ) ] = arrayFrom ( newValue . keys ( ) , relativeToBuildInfo ) ;
648639 } ) ;
649640 result . exportedModulesMap = exportedModulesMap ;
650641 }
@@ -655,50 +646,44 @@ namespace ts {
655646 state . semanticDiagnosticsPerFile . forEach ( ( value , key ) => semanticDiagnosticsPerFile . push (
656647 value . length ?
657648 [
658- key ,
649+ relativeToBuildInfo ( key ) ,
659650 state . hasReusableDiagnostic ?
660651 value as ReadonlyArray < ReusableDiagnostic > :
661- convertToReusableDiagnostics ( value as ReadonlyArray < Diagnostic > )
652+ convertToReusableDiagnostics ( value as ReadonlyArray < Diagnostic > , relativeToBuildInfo )
662653 ] :
663- key
654+ relativeToBuildInfo ( key )
664655 ) ) ;
665656 result . semanticDiagnosticsPerFile = semanticDiagnosticsPerFile ;
666657 }
667658
668659 return result ;
660+
661+ function relativeToBuildInfo ( path : string ) {
662+ return ensurePathIsNonModuleName ( getRelativePathFromDirectory ( buildInfoDirectory , path , getCanonicalFileName ) ) ;
663+ }
669664 }
670665
671- function convertToReusableDiagnostics ( diagnostics : ReadonlyArray < Diagnostic > ) : ReadonlyArray < ReusableDiagnostic > {
666+ function convertToReusableDiagnostics ( diagnostics : ReadonlyArray < Diagnostic > , relativeToBuildInfo : ( path : string ) => string ) : ReadonlyArray < ReusableDiagnostic > {
672667 Debug . assert ( ! ! diagnostics . length ) ;
673668 return diagnostics . map ( diagnostic => {
674- const result : ReusableDiagnostic = convertToReusableDiagnosticRelatedInformation ( diagnostic ) ;
669+ const result : ReusableDiagnostic = convertToReusableDiagnosticRelatedInformation ( diagnostic , relativeToBuildInfo ) ;
675670 result . reportsUnnecessary = diagnostic . reportsUnnecessary ;
676671 result . source = diagnostic . source ;
677672 const { relatedInformation } = diagnostic ;
678673 result . relatedInformation = relatedInformation ?
679674 relatedInformation . length ?
680- relatedInformation . map ( r => convertToReusableDiagnosticRelatedInformation ( r ) ) :
675+ relatedInformation . map ( r => convertToReusableDiagnosticRelatedInformation ( r , relativeToBuildInfo ) ) :
681676 emptyArray :
682677 undefined ;
683678 return result ;
684679 } ) ;
685680 }
686681
687- function convertToReusableDiagnosticRelatedInformation ( diagnostic : DiagnosticRelatedInformation ) : ReusableDiagnosticRelatedInformation {
688- const { file, messageText } = diagnostic ;
682+ function convertToReusableDiagnosticRelatedInformation ( diagnostic : DiagnosticRelatedInformation , relativeToBuildInfo : ( path : string ) => string ) : ReusableDiagnosticRelatedInformation {
683+ const { file } = diagnostic ;
689684 return {
690685 ...diagnostic ,
691- file : file && file . path ,
692- messageText : messageText === undefined || isString ( messageText ) ?
693- messageText :
694- convertToReusableDiagnosticMessageChain ( messageText )
695- } ;
696- }
697-
698- function convertToReusableDiagnosticMessageChain ( diagnostic : DiagnosticMessageChain ) : ReusableDiagnosticMessageChain {
699- return {
700- ...diagnostic ,
701- next : diagnostic . next && convertToReusableDiagnosticMessageChain ( diagnostic . next )
686+ file : file ? relativeToBuildInfo ( file . path ) : undefined
702687 } ;
703688 }
704689
@@ -767,7 +752,7 @@ namespace ts {
767752 const computeHash = host . createHash || generateDjb2Hash ;
768753 let state = createBuilderProgramState ( newProgram , getCanonicalFileName , oldState ) ;
769754 let backupState : BuilderProgramState | undefined ;
770- newProgram . getProgramBuildInfo = ( ) => getProgramBuildInfo ( state ) ;
755+ newProgram . getProgramBuildInfo = ( ) => getProgramBuildInfo ( state , getCanonicalFileName ) ;
771756
772757 // To ensure that we arent storing any references to old program or new program without state
773758 newProgram = undefined ! ; // TODO: GH#18217
@@ -980,26 +965,35 @@ namespace ts {
980965 }
981966 }
982967
983- function getMapOfReferencedSet ( mapLike : MapLike < ReadonlyArray < string > > | undefined ) : ReadonlyMap < BuilderState . ReferencedSet > | undefined {
968+ function getMapOfReferencedSet ( mapLike : MapLike < ReadonlyArray < string > > | undefined , toPath : ( path : string ) => Path ) : ReadonlyMap < BuilderState . ReferencedSet > | undefined {
984969 if ( ! mapLike ) return undefined ;
985970 const map = createMap < BuilderState . ReferencedSet > ( ) ;
986971 // Copies keys/values from template. Note that for..in will not throw if
987972 // template is undefined, and instead will just exit the loop.
988973 for ( const key in mapLike ) {
989974 if ( hasProperty ( mapLike , key ) ) {
990- map . set ( key , arrayToSet ( mapLike [ key ] ) ) ;
975+ map . set ( toPath ( key ) , arrayToSet ( mapLike [ key ] , toPath ) ) ;
991976 }
992977 }
993978 return map ;
994979 }
995980
996- export function createBuildProgramUsingProgramBuildInfo ( program : ProgramBuildInfo ) : EmitAndSemanticDiagnosticsBuilderProgram {
997- const fileInfos = createMapFromTemplate ( program . fileInfos ) ;
981+ export function createBuildProgramUsingProgramBuildInfo ( program : ProgramBuildInfo , buildInfoPath : string , useCaseSensitiveFileNames : boolean ) : EmitAndSemanticDiagnosticsBuilderProgram {
982+ const buildInfoDirectory = getDirectoryPath ( buildInfoPath ) ;
983+ const getCanonicalFileName = createGetCanonicalFileName ( useCaseSensitiveFileNames ) ;
984+
985+ const fileInfos = createMap < BuilderState . FileInfo > ( ) ;
986+ for ( const key in program . fileInfos ) {
987+ if ( hasProperty ( program . fileInfos , key ) ) {
988+ fileInfos . set ( toPath ( key ) , program . fileInfos [ key ] ) ;
989+ }
990+ }
991+
998992 const state : ReusableBuilderProgramState = {
999993 fileInfos,
1000994 compilerOptions : program . options ,
1001- referencedMap : getMapOfReferencedSet ( program . referencedMap ) ,
1002- exportedModulesMap : getMapOfReferencedSet ( program . exportedModulesMap ) ,
995+ referencedMap : getMapOfReferencedSet ( program . referencedMap , toPath ) ,
996+ exportedModulesMap : getMapOfReferencedSet ( program . exportedModulesMap , toPath ) ,
1003997 semanticDiagnosticsPerFile : program . semanticDiagnosticsPerFile && arrayToMap ( program . semanticDiagnosticsPerFile , value => isString ( value ) ? value : value [ 0 ] , value => isString ( value ) ? emptyArray : value [ 1 ] ) ,
1004998 hasReusableDiagnostic : true
1005999 } ;
@@ -1025,6 +1019,10 @@ namespace ts {
10251019 emitNextAffectedFile : notImplemented ,
10261020 getSemanticDiagnosticsOfNextAffectedFile : notImplemented ,
10271021 } ;
1022+
1023+ function toPath ( path : string ) {
1024+ return ts . toPath ( path , buildInfoDirectory , getCanonicalFileName ) ;
1025+ }
10281026 }
10291027
10301028 export function createRedirectedBuilderProgram ( state : { program : Program | undefined ; compilerOptions : CompilerOptions ; } , configFileParsingDiagnostics : ReadonlyArray < Diagnostic > ) : BuilderProgram {
0 commit comments