@@ -12,7 +12,8 @@ namespace ts.tscWatch {
12
12
file,
13
13
fileStamp : host . getModifiedTime ( file . path . replace ( ".ts" , ".js" ) ) ,
14
14
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" ) )
16
17
} ;
17
18
}
18
19
@@ -24,21 +25,36 @@ namespace ts.tscWatch {
24
25
return find ( stampsAndErrors , info => info . file === file ) ! ;
25
26
}
26
27
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 ) {
34
44
const beforeChange = findStampAndErrors ( beforeChangeFileStampsAndErrors , file ) ;
35
45
const afterChange = findStampAndErrors ( afterChangeFileStampsAndErrors , file ) ;
36
- if ( emitExpected ) {
46
+ if ( jsEmitExpected ) {
37
47
assert . notStrictEqual ( afterChange . fileStamp , beforeChange . fileStamp , `Expected emit for file ${ file . path } ` ) ;
38
48
}
39
49
else {
40
50
assert . strictEqual ( afterChange . fileStamp , beforeChange . fileStamp , `Did not expect new emit for file ${ file . path } ` ) ;
41
51
}
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
+ }
42
58
if ( errorRefershExpected ) {
43
59
if ( afterChange . errors !== emptyArray || beforeChange . errors !== emptyArray ) {
44
60
assert . notStrictEqual ( afterChange . errors , beforeChange . errors , `Expected new errors for file ${ file . path } ` ) ;
@@ -51,19 +67,22 @@ namespace ts.tscWatch {
51
67
}
52
68
}
53
69
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 ;
62
72
}
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 ) {
65
83
const nonLibFiles = [ ...filesWithNewEmit , ...filesWithOnlyErrorRefresh , ...filesNotTouched ] ;
66
84
const files = [ ...nonLibFiles , configFile , libFile ] ;
85
+ const compilerOptions = ( JSON . parse ( configFile . content ) . compilerOptions || { } ) as CompilerOptions ;
67
86
const host = createWatchedSystem ( files , { currentDirectory } ) ;
68
87
const watch = createWatchOfConfigFile ( "tsconfig.json" , host ) ;
69
88
checkProgramActualFiles ( watch ( ) , [ ...nonLibFiles . map ( f => f . path ) , libFile . path ] ) ;
@@ -73,9 +92,77 @@ namespace ts.tscWatch {
73
92
host . runQueuedTimeoutCallbacks ( ) ;
74
93
checkOutputErrorsIncremental ( host , getIncrementalErrors ( watch ) ) ;
75
94
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
+ } ) ;
79
166
}
80
167
81
168
describe ( "deep import changes" , ( ) => {
@@ -93,6 +180,7 @@ console.log(b.c.d);`
93
180
addImportedModule ( bFile ) ;
94
181
addImportedModule ( cFile ) ;
95
182
verifyEmitAndErrorUpdates ( {
183
+ fileWithChange : cFile ,
96
184
filesWithNewEmit,
97
185
filesWithOnlyErrorRefresh,
98
186
filesNotTouched : emptyArray ,
@@ -113,7 +201,7 @@ console.log(b.c.d);`
113
201
}
114
202
}
115
203
116
- it ( "updates errors when deep import file changes" , ( ) => {
204
+ describe ( "updates errors when deep import file changes" , ( ) => {
117
205
const bFile : File = {
118
206
path : `${ currentDirectory } /b.ts` ,
119
207
content : `import {C} from './c';
@@ -132,7 +220,7 @@ export class B
132
220
verifyDeepImportChange ( bFile , cFile ) ;
133
221
} ) ;
134
222
135
- it ( "updates errors when deep import through declaration file changes" , ( ) => {
223
+ describe ( "updates errors when deep import through declaration file changes" , ( ) => {
136
224
const bFile : File = {
137
225
path : `${ currentDirectory } /b.d.ts` ,
138
226
content : `import {C} from './c';
@@ -152,7 +240,7 @@ export class B
152
240
} ) ;
153
241
} ) ;
154
242
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" , ( ) => {
156
244
const aFile : File = {
157
245
path : `${ currentDirectory } /a.ts` ,
158
246
content : `export interface Point {
@@ -193,6 +281,7 @@ getPoint().c.x;`
193
281
content : `import "./d";`
194
282
} ;
195
283
verifyEmitAndErrorUpdates ( {
284
+ fileWithChange : aFile ,
196
285
filesWithNewEmit : [ aFile , bFile ] ,
197
286
filesWithOnlyErrorRefresh : [ cFile , dFile ] ,
198
287
filesNotTouched : [ eFile ] ,
@@ -265,6 +354,7 @@ export class Data {
265
354
filesWithOnlyErrorRefresh . push ( lib2Data2 ) ;
266
355
}
267
356
verifyEmitAndErrorUpdates ( {
357
+ fileWithChange : lib1ToolsInterface ,
268
358
filesWithNewEmit,
269
359
filesWithOnlyErrorRefresh,
270
360
filesNotTouched : emptyArray ,
@@ -276,11 +366,11 @@ export class Data {
276
366
]
277
367
} ) ;
278
368
}
279
- it ( "when there are no circular import and exports" , ( ) => {
369
+ describe ( "when there are no circular import and exports" , ( ) => {
280
370
verifyTransitiveExports ( lib2Data ) ;
281
371
} ) ;
282
372
283
- it ( "when there are circular import and exports" , ( ) => {
373
+ describe ( "when there are circular import and exports" , ( ) => {
284
374
const lib2Data : File = {
285
375
path : `${ currentDirectory } /lib2/data.ts` ,
286
376
content : `import { ITest } from "lib1/public"; import { Data2 } from "./data2";
0 commit comments