@@ -12,7 +12,8 @@ namespace ts.tscWatch {
1212 file,
1313 fileStamp : host . getModifiedTime ( file . path . replace ( ".ts" , ".js" ) ) ,
1414 errors : builderProgram . getSemanticDiagnostics ( watch ( ) . getSourceFileByPath ( file . path as Path ) ) ,
15- errorsFromOldState : ! ! state . semanticDiagnosticsFromOldState && state . semanticDiagnosticsFromOldState . has ( file . path )
15+ errorsFromOldState : ! ! state . semanticDiagnosticsFromOldState && state . semanticDiagnosticsFromOldState . has ( file . path ) ,
16+ dtsStamp : host . getModifiedTime ( file . path . replace ( ".ts" , ".d.ts" ) )
1617 } ;
1718 }
1819
@@ -24,21 +25,36 @@ namespace ts.tscWatch {
2425 return find ( stampsAndErrors , info => info . file === file ) ! ;
2526 }
2627
27- function verifyOutputFileStampsAndErrors (
28- file : File ,
29- emitExpected : boolean ,
30- errorRefershExpected : boolean ,
31- beforeChangeFileStampsAndErrors : readonly ReturnType < typeof getOutputFileStampAndError > [ ] ,
32- afterChangeFileStampsAndErrors : readonly ReturnType < typeof getOutputFileStampAndError > [ ]
33- ) {
28+ interface VerifyOutputFileStampAndErrors {
29+ file : File ;
30+ jsEmitExpected : boolean ;
31+ dtsEmitExpected : boolean ;
32+ errorRefershExpected : boolean ;
33+ beforeChangeFileStampsAndErrors : readonly ReturnType < typeof getOutputFileStampAndError > [ ] ;
34+ afterChangeFileStampsAndErrors : readonly ReturnType < typeof getOutputFileStampAndError > [ ] ;
35+ }
36+ function verifyOutputFileStampsAndErrors ( {
37+ file,
38+ jsEmitExpected,
39+ dtsEmitExpected,
40+ errorRefershExpected,
41+ beforeChangeFileStampsAndErrors,
42+ afterChangeFileStampsAndErrors
43+ } : VerifyOutputFileStampAndErrors ) {
3444 const beforeChange = findStampAndErrors ( beforeChangeFileStampsAndErrors , file ) ;
3545 const afterChange = findStampAndErrors ( afterChangeFileStampsAndErrors , file ) ;
36- if ( emitExpected ) {
46+ if ( jsEmitExpected ) {
3747 assert . notStrictEqual ( afterChange . fileStamp , beforeChange . fileStamp , `Expected emit for file ${ file . path } ` ) ;
3848 }
3949 else {
4050 assert . strictEqual ( afterChange . fileStamp , beforeChange . fileStamp , `Did not expect new emit for file ${ file . path } ` ) ;
4151 }
52+ if ( dtsEmitExpected ) {
53+ assert . notStrictEqual ( afterChange . dtsStamp , beforeChange . dtsStamp , `Expected emit for file ${ file . path } ` ) ;
54+ }
55+ else {
56+ assert . strictEqual ( afterChange . dtsStamp , beforeChange . dtsStamp , `Did not expect new emit for file ${ file . path } ` ) ;
57+ }
4258 if ( errorRefershExpected ) {
4359 if ( afterChange . errors !== emptyArray || beforeChange . errors !== emptyArray ) {
4460 assert . notStrictEqual ( afterChange . errors , beforeChange . errors , `Expected new errors for file ${ file . path } ` ) ;
@@ -51,19 +67,22 @@ namespace ts.tscWatch {
5167 }
5268 }
5369
54- interface VerifyEmitAndErrorUpdates {
55- change : ( host : WatchedSystem ) => void ;
56- getInitialErrors : ( watch : Watch ) => readonly Diagnostic [ ] | readonly string [ ] ;
57- getIncrementalErrors : ( watch : Watch ) => readonly Diagnostic [ ] | readonly string [ ] ;
58- filesWithNewEmit : readonly File [ ] ;
59- filesWithOnlyErrorRefresh : readonly File [ ] ;
60- filesNotTouched : readonly File [ ] ;
61- configFile ?: File ;
70+ interface VerifyEmitAndErrorUpdatesWorker extends VerifyEmitAndErrorUpdates {
71+ configFile : File ;
6272 }
63-
64- function verifyEmitAndErrorUpdates ( { filesWithNewEmit, filesWithOnlyErrorRefresh, filesNotTouched, configFile = config , change, getInitialErrors, getIncrementalErrors } : VerifyEmitAndErrorUpdates ) {
73+ function verifyEmitAndErrorUpdatesWorker ( {
74+ fileWithChange,
75+ filesWithNewEmit,
76+ filesWithOnlyErrorRefresh,
77+ filesNotTouched,
78+ configFile,
79+ change,
80+ getInitialErrors,
81+ getIncrementalErrors
82+ } : VerifyEmitAndErrorUpdatesWorker ) {
6583 const nonLibFiles = [ ...filesWithNewEmit , ...filesWithOnlyErrorRefresh , ...filesNotTouched ] ;
6684 const files = [ ...nonLibFiles , configFile , libFile ] ;
85+ const compilerOptions = ( JSON . parse ( configFile . content ) . compilerOptions || { } ) as CompilerOptions ;
6786 const host = createWatchedSystem ( files , { currentDirectory } ) ;
6887 const watch = createWatchOfConfigFile ( "tsconfig.json" , host ) ;
6988 checkProgramActualFiles ( watch ( ) , [ ...nonLibFiles . map ( f => f . path ) , libFile . path ] ) ;
@@ -73,9 +92,77 @@ namespace ts.tscWatch {
7392 host . runQueuedTimeoutCallbacks ( ) ;
7493 checkOutputErrorsIncremental ( host , getIncrementalErrors ( watch ) ) ;
7594 const afterChange = getOutputFileStampsAndErrors ( host , watch , nonLibFiles ) ;
76- filesWithNewEmit . forEach ( file => verifyOutputFileStampsAndErrors ( file , /*emitExpected*/ true , /*errorRefershExpected*/ true , beforeChange , afterChange ) ) ;
77- filesWithOnlyErrorRefresh . forEach ( file => verifyOutputFileStampsAndErrors ( file , /*emitExpected*/ false , /*errorRefershExpected*/ true , beforeChange , afterChange ) ) ;
78- filesNotTouched . forEach ( file => verifyOutputFileStampsAndErrors ( file , /*emitExpected*/ false , /*errorRefershExpected*/ false , beforeChange , afterChange ) ) ;
95+ filesWithNewEmit . forEach ( file => verifyOutputFileStampsAndErrors ( {
96+ file,
97+ jsEmitExpected : ! compilerOptions . isolatedModules || fileWithChange === file ,
98+ dtsEmitExpected : getEmitDeclarations ( compilerOptions ) ,
99+ errorRefershExpected : true ,
100+ beforeChangeFileStampsAndErrors : beforeChange ,
101+ afterChangeFileStampsAndErrors : afterChange
102+ } ) ) ;
103+ filesWithOnlyErrorRefresh . forEach ( file => verifyOutputFileStampsAndErrors ( {
104+ file,
105+ jsEmitExpected : false ,
106+ dtsEmitExpected : getEmitDeclarations ( compilerOptions ) && ! file . path . endsWith ( ".d.ts" ) ,
107+ errorRefershExpected : true ,
108+ beforeChangeFileStampsAndErrors : beforeChange ,
109+ afterChangeFileStampsAndErrors : afterChange
110+ } ) ) ;
111+ filesNotTouched . forEach ( file => verifyOutputFileStampsAndErrors ( {
112+ file,
113+ jsEmitExpected : false ,
114+ dtsEmitExpected : false ,
115+ errorRefershExpected : false ,
116+ beforeChangeFileStampsAndErrors : beforeChange ,
117+ afterChangeFileStampsAndErrors : afterChange
118+ } ) ) ;
119+ }
120+
121+ function changeCompilerOptions ( input : VerifyEmitAndErrorUpdates , additionalOptions : CompilerOptions ) : File {
122+ const configFile = input . configFile || config ;
123+ const content = JSON . parse ( configFile . content ) ;
124+ content . compilerOptions = { ...content . compilerOptions , ...additionalOptions } ;
125+ return { path : configFile . path , content : JSON . stringify ( content ) } ;
126+ }
127+
128+ interface VerifyEmitAndErrorUpdates {
129+ change : ( host : WatchedSystem ) => void ;
130+ getInitialErrors : ( watch : Watch ) => readonly Diagnostic [ ] | readonly string [ ] ;
131+ getIncrementalErrors : ( watch : Watch ) => readonly Diagnostic [ ] | readonly string [ ] ;
132+ fileWithChange : File ;
133+ filesWithNewEmit : readonly File [ ] ;
134+ filesWithOnlyErrorRefresh : readonly File [ ] ;
135+ filesNotTouched : readonly File [ ] ;
136+ configFile ?: File ;
137+ }
138+ function verifyEmitAndErrorUpdates ( input : VerifyEmitAndErrorUpdates ) {
139+ it ( "with default config" , ( ) => {
140+ verifyEmitAndErrorUpdatesWorker ( {
141+ ...input ,
142+ configFile : input . configFile || config
143+ } ) ;
144+ } ) ;
145+
146+ it ( "with default config and --declaration" , ( ) => {
147+ verifyEmitAndErrorUpdatesWorker ( {
148+ ...input ,
149+ configFile : changeCompilerOptions ( input , { declaration : true } )
150+ } ) ;
151+ } ) ;
152+
153+ it ( "config with --isolatedModules" , ( ) => {
154+ verifyEmitAndErrorUpdatesWorker ( {
155+ ...input ,
156+ configFile : changeCompilerOptions ( input , { isolatedModules : true } )
157+ } ) ;
158+ } ) ;
159+
160+ it ( "config with --isolatedModules and --declaration" , ( ) => {
161+ verifyEmitAndErrorUpdatesWorker ( {
162+ ...input ,
163+ configFile : changeCompilerOptions ( input , { isolatedModules : true , declaration : true } )
164+ } ) ;
165+ } ) ;
79166 }
80167
81168 describe ( "deep import changes" , ( ) => {
@@ -93,6 +180,7 @@ console.log(b.c.d);`
93180 addImportedModule ( bFile ) ;
94181 addImportedModule ( cFile ) ;
95182 verifyEmitAndErrorUpdates ( {
183+ fileWithChange : cFile ,
96184 filesWithNewEmit,
97185 filesWithOnlyErrorRefresh,
98186 filesNotTouched : emptyArray ,
@@ -113,7 +201,7 @@ console.log(b.c.d);`
113201 }
114202 }
115203
116- it ( "updates errors when deep import file changes" , ( ) => {
204+ describe ( "updates errors when deep import file changes" , ( ) => {
117205 const bFile : File = {
118206 path : `${ currentDirectory } /b.ts` ,
119207 content : `import {C} from './c';
@@ -132,7 +220,7 @@ export class B
132220 verifyDeepImportChange ( bFile , cFile ) ;
133221 } ) ;
134222
135- it ( "updates errors when deep import through declaration file changes" , ( ) => {
223+ describe ( "updates errors when deep import through declaration file changes" , ( ) => {
136224 const bFile : File = {
137225 path : `${ currentDirectory } /b.d.ts` ,
138226 content : `import {C} from './c';
@@ -152,7 +240,7 @@ export class B
152240 } ) ;
153241 } ) ;
154242
155- it ( "updates errors in file not exporting a deep multilevel import that changes" , ( ) => {
243+ describe ( "updates errors in file not exporting a deep multilevel import that changes" , ( ) => {
156244 const aFile : File = {
157245 path : `${ currentDirectory } /a.ts` ,
158246 content : `export interface Point {
@@ -193,6 +281,7 @@ getPoint().c.x;`
193281 content : `import "./d";`
194282 } ;
195283 verifyEmitAndErrorUpdates ( {
284+ fileWithChange : aFile ,
196285 filesWithNewEmit : [ aFile , bFile ] ,
197286 filesWithOnlyErrorRefresh : [ cFile , dFile ] ,
198287 filesNotTouched : [ eFile ] ,
@@ -265,6 +354,7 @@ export class Data {
265354 filesWithOnlyErrorRefresh . push ( lib2Data2 ) ;
266355 }
267356 verifyEmitAndErrorUpdates ( {
357+ fileWithChange : lib1ToolsInterface ,
268358 filesWithNewEmit,
269359 filesWithOnlyErrorRefresh,
270360 filesNotTouched : emptyArray ,
@@ -276,11 +366,11 @@ export class Data {
276366 ]
277367 } ) ;
278368 }
279- it ( "when there are no circular import and exports" , ( ) => {
369+ describe ( "when there are no circular import and exports" , ( ) => {
280370 verifyTransitiveExports ( lib2Data ) ;
281371 } ) ;
282372
283- it ( "when there are circular import and exports" , ( ) => {
373+ describe ( "when there are circular import and exports" , ( ) => {
284374 const lib2Data : File = {
285375 path : `${ currentDirectory } /lib2/data.ts` ,
286376 content : `import { ITest } from "lib1/public"; import { Data2 } from "./data2";
0 commit comments