@@ -159,12 +159,14 @@ namespace ts {
159159 return program ;
160160 }
161161
162- function updateProgram ( oldProgram : ProgramWithSourceTexts , rootNames : string [ ] , options : CompilerOptions , updater : ( files : NamedSourceText [ ] ) => void ) {
163- const texts : NamedSourceText [ ] = ( < ProgramWithSourceTexts > oldProgram ) . sourceTexts . slice ( 0 ) ;
164- updater ( texts ) ;
165- const host = createTestCompilerHost ( texts , options . target , oldProgram ) ;
162+ function updateProgram ( oldProgram : ProgramWithSourceTexts , rootNames : string [ ] , options : CompilerOptions , updater : ( files : NamedSourceText [ ] ) => void , newTexts ?: NamedSourceText [ ] ) {
163+ if ( ! newTexts ) {
164+ newTexts = ( < ProgramWithSourceTexts > oldProgram ) . sourceTexts . slice ( 0 ) ;
165+ }
166+ updater ( newTexts ) ;
167+ const host = createTestCompilerHost ( newTexts , options . target , oldProgram ) ;
166168 const program = < ProgramWithSourceTexts > createProgram ( rootNames , options , host , oldProgram ) ;
167- program . sourceTexts = texts ;
169+ program . sourceTexts = newTexts ;
168170 program . host = host ;
169171 return program ;
170172 }
@@ -391,6 +393,70 @@ namespace ts {
391393 checkResolvedTypeDirectivesCache ( program_1 , "/a.ts" , createMapFromTemplate ( { "typedefs" : { resolvedFileName : "/types/typedefs/index.d.ts" , primary : true } } ) ) ;
392394 } ) ;
393395
396+ it ( "fetches imports after npm install" , ( ) => {
397+ const file1Ts = { name : "file1.ts" , text : SourceText . New ( "" , `import * as a from "a";` , "const myX: number = a.x;" ) } ;
398+ const file2Ts = { name : "file2.ts" , text : SourceText . New ( "" , "" , "" ) } ;
399+ const indexDTS = { name : "node_modules/a/index.d.ts" , text : SourceText . New ( "" , "export declare let x: number;" , "" ) } ;
400+ const options : CompilerOptions = { target : ScriptTarget . ES2015 , traceResolution : true , moduleResolution : ModuleResolutionKind . NodeJs } ;
401+ const rootFiles = [ file1Ts , file2Ts ] ;
402+ const filesAfterNpmInstall = [ file1Ts , file2Ts , indexDTS ] ;
403+
404+ const initialProgram = newProgram ( rootFiles , rootFiles . map ( f => f . name ) , options ) ;
405+ {
406+ assert . deepEqual ( initialProgram . host . getTrace ( ) ,
407+ [
408+ "======== Resolving module 'a' from 'file1.ts'. ========" ,
409+ "Explicitly specified module resolution kind: 'NodeJs'." ,
410+ "Loading module 'a' from 'node_modules' folder, target file type 'TypeScript'." ,
411+ "File 'node_modules/a.ts' does not exist." ,
412+ "File 'node_modules/a.tsx' does not exist." ,
413+ "File 'node_modules/a.d.ts' does not exist." ,
414+ "File 'node_modules/a/package.json' does not exist." ,
415+ "File 'node_modules/a/index.ts' does not exist." ,
416+ "File 'node_modules/a/index.tsx' does not exist." ,
417+ "File 'node_modules/a/index.d.ts' does not exist." ,
418+ "File 'node_modules/@types/a.d.ts' does not exist." ,
419+ "File 'node_modules/@types/a/package.json' does not exist." ,
420+ "File 'node_modules/@types/a/index.d.ts' does not exist." ,
421+ "Loading module 'a' from 'node_modules' folder, target file type 'JavaScript'." ,
422+ "File 'node_modules/a.js' does not exist." ,
423+ "File 'node_modules/a.jsx' does not exist." ,
424+ "File 'node_modules/a/package.json' does not exist." ,
425+ "File 'node_modules/a/index.js' does not exist." ,
426+ "File 'node_modules/a/index.jsx' does not exist." ,
427+ "======== Module name 'a' was not resolved. ========"
428+ ] ,
429+ "initialProgram: execute module resolution normally." ) ;
430+
431+ const initialProgramDiagnostics = initialProgram . getSemanticDiagnostics ( initialProgram . getSourceFile ( "file1.ts" ) ) ;
432+ assert ( initialProgramDiagnostics . length === 1 , `initialProgram: import should fail.` ) ;
433+ }
434+
435+ const afterNpmInstallProgram = updateProgram ( initialProgram , rootFiles . map ( f => f . name ) , options , f => {
436+ f [ 1 ] . text = f [ 1 ] . text . updateReferences ( `/// <reference no-default-lib="true"/>` ) ;
437+ } , filesAfterNpmInstall ) ;
438+ {
439+ assert . deepEqual ( afterNpmInstallProgram . host . getTrace ( ) ,
440+ [
441+ "======== Resolving module 'a' from 'file1.ts'. ========" ,
442+ "Explicitly specified module resolution kind: 'NodeJs'." ,
443+ "Loading module 'a' from 'node_modules' folder, target file type 'TypeScript'." ,
444+ "File 'node_modules/a.ts' does not exist." ,
445+ "File 'node_modules/a.tsx' does not exist." ,
446+ "File 'node_modules/a.d.ts' does not exist." ,
447+ "File 'node_modules/a/package.json' does not exist." ,
448+ "File 'node_modules/a/index.ts' does not exist." ,
449+ "File 'node_modules/a/index.tsx' does not exist." ,
450+ "File 'node_modules/a/index.d.ts' exist - use it as a name resolution result." ,
451+ "======== Module name 'a' was successfully resolved to 'node_modules/a/index.d.ts'. ========"
452+ ] ,
453+ "afterNpmInstallProgram: execute module resolution normally." ) ;
454+
455+ const afterNpmInstallProgramDiagnostics = afterNpmInstallProgram . getSemanticDiagnostics ( afterNpmInstallProgram . getSourceFile ( "file1.ts" ) ) ;
456+ assert ( afterNpmInstallProgramDiagnostics . length === 0 , `afterNpmInstallProgram: program is well-formed with import.` ) ;
457+ }
458+ } ) ;
459+
394460 it ( "can reuse ambient module declarations from non-modified files" , ( ) => {
395461 const files = [
396462 { name : "/a/b/app.ts" , text : SourceText . New ( "" , "import * as fs from 'fs'" , "" ) } ,
@@ -624,7 +690,7 @@ namespace ts {
624690 "Explicitly specified module resolution kind: 'Classic'." ,
625691 "File 'b1.ts' exist - use it as a name resolution result." ,
626692 "======== Module name './b1' was successfully resolved to 'b1.ts'. ========"
627- ] , "program_5: exports do not affect program structure, so f2's reoslutions are silently reused." ) ;
693+ ] , "program_5: exports do not affect program structure, so f2's resolutions are silently reused." ) ;
628694 }
629695
630696 const program_6 = updateProgram ( program_5 , program_5 . getRootFileNames ( ) , options , f => {
@@ -658,7 +724,7 @@ namespace ts {
658724
659725 {
660726 const program_7Diagnostics = program_7 . getSemanticDiagnostics ( program_7 . getSourceFile ( "f2.ts" ) ) ;
661- assert ( program_7Diagnostics . length === expectedErrors , `removing import is noop with respect to program, so no change in diangostics .` ) ;
727+ assert ( program_7Diagnostics . length === expectedErrors , `removing import is noop with respect to program, so no change in diagnostics .` ) ;
662728
663729 assert . deepEqual ( program_7 . host . getTrace ( ) , [
664730 "======== Resolving type reference directive 'typerefs2', containing file 'f2.ts', root directory 'node_modules/@types'. ========" ,
0 commit comments