@@ -104,7 +104,7 @@ namespace ts {
104
104
return file ;
105
105
}
106
106
107
- export function createTestCompilerHost ( texts : ReadonlyArray < NamedSourceText > , target : ScriptTarget , oldProgram ?: ProgramWithSourceTexts ) : TestCompilerHost {
107
+ export function createTestCompilerHost ( texts : ReadonlyArray < NamedSourceText > , target : ScriptTarget , oldProgram ?: ProgramWithSourceTexts , useGetSourceFileByPath ?: boolean ) {
108
108
const files = arrayToMap ( texts , t => t . name , t => {
109
109
if ( oldProgram ) {
110
110
let oldFile = < SourceFileWithText > oldProgram . getSourceFile ( t . name ) ;
@@ -117,55 +117,47 @@ namespace ts {
117
117
}
118
118
return createSourceFileWithText ( t . name , t . text , target ) ;
119
119
} ) ;
120
+ const useCaseSensitiveFileNames = sys && sys . useCaseSensitiveFileNames ;
121
+ const getCanonicalFileName = createGetCanonicalFileName ( useCaseSensitiveFileNames ) ;
120
122
const trace : string [ ] = [ ] ;
121
-
122
- return {
123
+ const result : TestCompilerHost = {
123
124
trace : s => trace . push ( s ) ,
124
125
getTrace : ( ) => trace ,
125
- getSourceFile ( fileName ) : SourceFile {
126
- return files . get ( fileName ) ! ;
127
- } ,
128
- getDefaultLibFileName ( ) : string {
129
- return "lib.d.ts" ;
130
- } ,
126
+ getSourceFile : fileName => files . get ( fileName ) ,
127
+ getDefaultLibFileName : ( ) => "lib.d.ts" ,
131
128
writeFile : notImplemented ,
132
- getCurrentDirectory ( ) : string {
133
- return "" ;
134
- } ,
135
- getDirectories ( ) : string [ ] {
136
- return [ ] ;
137
- } ,
138
- getCanonicalFileName ( fileName ) : string {
139
- return sys && sys . useCaseSensitiveFileNames ? fileName : fileName . toLowerCase ( ) ;
140
- } ,
141
- useCaseSensitiveFileNames ( ) : boolean {
142
- return sys && sys . useCaseSensitiveFileNames ;
143
- } ,
144
- getNewLine ( ) : string {
145
- return sys ? sys . newLine : newLine ;
146
- } ,
129
+ getCurrentDirectory : ( ) => "" ,
130
+ getDirectories : ( ) => [ ] ,
131
+ getCanonicalFileName,
132
+ useCaseSensitiveFileNames : ( ) => useCaseSensitiveFileNames ,
133
+ getNewLine : ( ) => sys ? sys . newLine : newLine ,
147
134
fileExists : fileName => files . has ( fileName ) ,
148
135
readFile : fileName => {
149
136
const file = files . get ( fileName ) ;
150
137
return file && file . text ;
151
138
} ,
152
139
} ;
140
+ if ( useGetSourceFileByPath ) {
141
+ const filesByPath = mapEntries ( files , ( fileName , file ) => [ toPath ( fileName , "" , getCanonicalFileName ) , file ] ) ;
142
+ result . getSourceFileByPath = ( _fileName , path ) => filesByPath . get ( path ) ;
143
+ }
144
+ return result ;
153
145
}
154
146
155
- export function newProgram ( texts : NamedSourceText [ ] , rootNames : string [ ] , options : CompilerOptions ) : ProgramWithSourceTexts {
156
- const host = createTestCompilerHost ( texts , options . target ! ) ;
147
+ export function newProgram ( texts : NamedSourceText [ ] , rootNames : string [ ] , options : CompilerOptions , useGetSourceFileByPath ?: boolean ) : ProgramWithSourceTexts {
148
+ const host = createTestCompilerHost ( texts , options . target ! , /*oldProgram*/ undefined , useGetSourceFileByPath ) ;
157
149
const program = < ProgramWithSourceTexts > createProgram ( rootNames , options , host ) ;
158
150
program . sourceTexts = texts ;
159
151
program . host = host ;
160
152
return program ;
161
153
}
162
154
163
- export function updateProgram ( oldProgram : ProgramWithSourceTexts , rootNames : ReadonlyArray < string > , options : CompilerOptions , updater : ( files : NamedSourceText [ ] ) => void , newTexts ?: NamedSourceText [ ] ) {
155
+ export function updateProgram ( oldProgram : ProgramWithSourceTexts , rootNames : ReadonlyArray < string > , options : CompilerOptions , updater : ( files : NamedSourceText [ ] ) => void , newTexts ?: NamedSourceText [ ] , useGetSourceFileByPath ?: boolean ) {
164
156
if ( ! newTexts ) {
165
157
newTexts = oldProgram . sourceTexts ! . slice ( 0 ) ;
166
158
}
167
159
updater ( newTexts ) ;
168
- const host = createTestCompilerHost ( newTexts , options . target ! , oldProgram ) ;
160
+ const host = createTestCompilerHost ( newTexts , options . target ! , oldProgram , useGetSourceFileByPath ) ;
169
161
const program = < ProgramWithSourceTexts > createProgram ( rootNames , options , host , oldProgram ) ;
170
162
program . sourceTexts = newTexts ;
171
163
program . host = host ;
@@ -809,7 +801,7 @@ namespace ts {
809
801
const root = "/a.ts" ;
810
802
const compilerOptions = { target, moduleResolution : ModuleResolutionKind . NodeJs } ;
811
803
812
- function createRedirectProgram ( options ?: { bText : string , bVersion : string } ) : ProgramWithSourceTexts {
804
+ function createRedirectProgram ( useGetSourceFileByPath : boolean , options ?: { bText : string , bVersion : string } ) : ProgramWithSourceTexts {
813
805
const files : NamedSourceText [ ] = [
814
806
{
815
807
name : "/node_modules/a/index.d.ts" ,
@@ -841,55 +833,64 @@ namespace ts {
841
833
} ,
842
834
] ;
843
835
844
- return newProgram ( files , [ root ] , compilerOptions ) ;
836
+ return newProgram ( files , [ root ] , compilerOptions , useGetSourceFileByPath ) ;
845
837
}
846
838
847
- function updateRedirectProgram ( program : ProgramWithSourceTexts , updater : ( files : NamedSourceText [ ] ) => void ) : ProgramWithSourceTexts {
848
- return updateProgram ( program , [ root ] , compilerOptions , updater ) ;
839
+ function updateRedirectProgram ( program : ProgramWithSourceTexts , updater : ( files : NamedSourceText [ ] ) => void , useGetSourceFileByPath : boolean ) : ProgramWithSourceTexts {
840
+ return updateProgram ( program , [ root ] , compilerOptions , updater , /*newTexts*/ undefined , useGetSourceFileByPath ) ;
849
841
}
850
842
851
- it ( "No changes -> redirect not broken" , ( ) => {
852
- const program1 = createRedirectProgram ( ) ;
843
+ function verifyRedirects ( useGetSourceFileByPath : boolean ) {
844
+ it ( "No changes -> redirect not broken" , ( ) => {
845
+ const program1 = createRedirectProgram ( useGetSourceFileByPath ) ;
853
846
854
- const program2 = updateRedirectProgram ( program1 , files => {
855
- updateProgramText ( files , root , "const x = 1;" ) ;
847
+ const program2 = updateRedirectProgram ( program1 , files => {
848
+ updateProgramText ( files , root , "const x = 1;" ) ;
849
+ } , useGetSourceFileByPath ) ;
850
+ assert . equal ( program1 . structureIsReused , StructureIsReused . Completely ) ;
851
+ assert . lengthOf ( program2 . getSemanticDiagnostics ( ) , 0 ) ;
856
852
} ) ;
857
- assert . equal ( program1 . structureIsReused , StructureIsReused . Completely ) ;
858
- assert . lengthOf ( program2 . getSemanticDiagnostics ( ) , 0 ) ;
859
- } ) ;
860
853
861
- it ( "Target changes -> redirect broken" , ( ) => {
862
- const program1 = createRedirectProgram ( ) ;
863
- assert . lengthOf ( program1 . getSemanticDiagnostics ( ) , 0 ) ;
854
+ it ( "Target changes -> redirect broken" , ( ) => {
855
+ const program1 = createRedirectProgram ( useGetSourceFileByPath ) ;
856
+ assert . lengthOf ( program1 . getSemanticDiagnostics ( ) , 0 ) ;
864
857
865
- const program2 = updateRedirectProgram ( program1 , files => {
866
- updateProgramText ( files , axIndex , "export default class X { private x: number; private y: number; }" ) ;
867
- updateProgramText ( files , axPackage , JSON . stringify ( '{ name: "x", version: "1.2.4" }' ) ) ;
858
+ const program2 = updateRedirectProgram ( program1 , files => {
859
+ updateProgramText ( files , axIndex , "export default class X { private x: number; private y: number; }" ) ;
860
+ updateProgramText ( files , axPackage , JSON . stringify ( '{ name: "x", version: "1.2.4" }' ) ) ;
861
+ } , useGetSourceFileByPath ) ;
862
+ assert . equal ( program1 . structureIsReused , StructureIsReused . Not ) ;
863
+ assert . lengthOf ( program2 . getSemanticDiagnostics ( ) , 1 ) ;
868
864
} ) ;
869
- assert . equal ( program1 . structureIsReused , StructureIsReused . Not ) ;
870
- assert . lengthOf ( program2 . getSemanticDiagnostics ( ) , 1 ) ;
871
- } ) ;
872
865
873
- it ( "Underlying changes -> redirect broken" , ( ) => {
874
- const program1 = createRedirectProgram ( ) ;
866
+ it ( "Underlying changes -> redirect broken" , ( ) => {
867
+ const program1 = createRedirectProgram ( useGetSourceFileByPath ) ;
875
868
876
- const program2 = updateRedirectProgram ( program1 , files => {
877
- updateProgramText ( files , bxIndex , "export default class X { private x: number; private y: number; }" ) ;
878
- updateProgramText ( files , bxPackage , JSON . stringify ( { name : "x" , version : "1.2.4" } ) ) ;
869
+ const program2 = updateRedirectProgram ( program1 , files => {
870
+ updateProgramText ( files , bxIndex , "export default class X { private x: number; private y: number; }" ) ;
871
+ updateProgramText ( files , bxPackage , JSON . stringify ( { name : "x" , version : "1.2.4" } ) ) ;
872
+ } , useGetSourceFileByPath ) ;
873
+ assert . equal ( program1 . structureIsReused , StructureIsReused . Not ) ;
874
+ assert . lengthOf ( program2 . getSemanticDiagnostics ( ) , 1 ) ;
879
875
} ) ;
880
- assert . equal ( program1 . structureIsReused , StructureIsReused . Not ) ;
881
- assert . lengthOf ( program2 . getSemanticDiagnostics ( ) , 1 ) ;
882
- } ) ;
883
876
884
- it ( "Previously duplicate packages -> program structure not reused" , ( ) => {
885
- const program1 = createRedirectProgram ( { bVersion : "1.2.4" , bText : "export = class X { private x: number; }" } ) ;
877
+ it ( "Previously duplicate packages -> program structure not reused" , ( ) => {
878
+ const program1 = createRedirectProgram ( useGetSourceFileByPath , { bVersion : "1.2.4" , bText : "export = class X { private x: number; }" } ) ;
886
879
887
- const program2 = updateRedirectProgram ( program1 , files => {
888
- updateProgramText ( files , bxIndex , "export default class X { private x: number; }" ) ;
889
- updateProgramText ( files , bxPackage , JSON . stringify ( { name : "x" , version : "1.2.3" } ) ) ;
880
+ const program2 = updateRedirectProgram ( program1 , files => {
881
+ updateProgramText ( files , bxIndex , "export default class X { private x: number; }" ) ;
882
+ updateProgramText ( files , bxPackage , JSON . stringify ( { name : "x" , version : "1.2.3" } ) ) ;
883
+ } , useGetSourceFileByPath ) ;
884
+ assert . equal ( program1 . structureIsReused , StructureIsReused . Not ) ;
885
+ assert . deepEqual ( program2 . getSemanticDiagnostics ( ) , [ ] ) ;
890
886
} ) ;
891
- assert . equal ( program1 . structureIsReused , StructureIsReused . Not ) ;
892
- assert . deepEqual ( program2 . getSemanticDiagnostics ( ) , [ ] ) ;
887
+ }
888
+
889
+ describe ( "when host implements getSourceFile" , ( ) => {
890
+ verifyRedirects ( /*useGetSourceFileByPath*/ false ) ;
891
+ } ) ;
892
+ describe ( "when host implements getSourceFileByPath" , ( ) => {
893
+ verifyRedirects ( /*useGetSourceFileByPath*/ true ) ;
893
894
} ) ;
894
895
} ) ;
895
896
} ) ;
0 commit comments