@@ -104,11 +104,13 @@ namespace ts {
104
104
} ;
105
105
}
106
106
107
- export function getPreEmitDiagnostics ( program : Program , sourceFile ?: SourceFile ) : Diagnostic [ ] {
108
- let diagnostics = program . getSyntacticDiagnostics ( sourceFile ) . concat ( program . getGlobalDiagnostics ( ) ) . concat ( program . getSemanticDiagnostics ( sourceFile ) ) ;
107
+ export function getPreEmitDiagnostics ( program : Program , sourceFile ?: SourceFile , cancellationToken ?: CancellationTokenObject ) : Diagnostic [ ] {
108
+ let diagnostics = program . getSyntacticDiagnostics ( sourceFile , cancellationToken ) . concat (
109
+ program . getGlobalDiagnostics ( cancellationToken ) ) . concat (
110
+ program . getSemanticDiagnostics ( sourceFile , cancellationToken ) ) ;
109
111
110
112
if ( program . getCompilerOptions ( ) . declaration ) {
111
- diagnostics . concat ( program . getDeclarationDiagnostics ( sourceFile ) ) ;
113
+ diagnostics . concat ( program . getDeclarationDiagnostics ( sourceFile , cancellationToken ) ) ;
112
114
}
113
115
114
116
return sortAndDeduplicateDiagnostics ( diagnostics ) ;
@@ -230,10 +232,15 @@ namespace ts {
230
232
return noDiagnosticsTypeChecker || ( noDiagnosticsTypeChecker = createTypeChecker ( program , /*produceDiagnostics:*/ false ) ) ;
231
233
}
232
234
233
- function emit ( sourceFile ?: SourceFile , writeFileCallback ?: WriteFileCallback ) : EmitResult {
235
+ function emit ( sourceFile ?: SourceFile , writeFileCallback ?: WriteFileCallback , cancellationToken ?: CancellationTokenObject ) : EmitResult {
236
+ return runWithCancellationToken ( ( ) => emitWorker ( this , sourceFile , writeFileCallback , cancellationToken ) ) ;
237
+ }
238
+
239
+ function emitWorker ( program : Program , sourceFile : SourceFile , writeFileCallback : WriteFileCallback , cancellationToken : CancellationTokenObject ) : EmitResult {
234
240
// If the noEmitOnError flag is set, then check if we have any errors so far. If so,
235
- // immediately bail out.
236
- if ( options . noEmitOnError && getPreEmitDiagnostics ( this ) . length > 0 ) {
241
+ // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
242
+ // get any preEmit diagnostics, not just the ones
243
+ if ( options . noEmitOnError && getPreEmitDiagnostics ( program , /*sourceFile:*/ undefined , cancellationToken ) . length > 0 ) {
237
244
return { diagnostics : [ ] , sourceMaps : undefined , emitSkipped : true } ;
238
245
}
239
246
@@ -262,53 +269,79 @@ namespace ts {
262
269
return filesByName . get ( fileName ) ;
263
270
}
264
271
265
- function getDiagnosticsHelper ( sourceFile : SourceFile , getDiagnostics : ( sourceFile : SourceFile ) => Diagnostic [ ] ) : Diagnostic [ ] {
272
+ function getDiagnosticsHelper (
273
+ sourceFile : SourceFile ,
274
+ getDiagnostics : ( sourceFile : SourceFile , cancellationToken : CancellationTokenObject ) => Diagnostic [ ] ,
275
+ cancellationToken : CancellationTokenObject ) : Diagnostic [ ] {
266
276
if ( sourceFile ) {
267
- return getDiagnostics ( sourceFile ) ;
277
+ return getDiagnostics ( sourceFile , cancellationToken ) ;
268
278
}
269
279
270
280
let allDiagnostics : Diagnostic [ ] = [ ] ;
271
281
forEach ( program . getSourceFiles ( ) , sourceFile => {
272
- addRange ( allDiagnostics , getDiagnostics ( sourceFile ) ) ;
282
+ if ( cancellationToken ) {
283
+ cancellationToken . throwIfCancellationRequested ( ) ;
284
+ }
285
+ addRange ( allDiagnostics , getDiagnostics ( sourceFile , cancellationToken ) ) ;
273
286
} ) ;
274
287
275
288
return sortAndDeduplicateDiagnostics ( allDiagnostics ) ;
276
289
}
277
290
278
- function getSyntacticDiagnostics ( sourceFile ? : SourceFile ) : Diagnostic [ ] {
279
- return getDiagnosticsHelper ( sourceFile , getSyntacticDiagnosticsForFile ) ;
291
+ function getSyntacticDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationTokenObject ) : Diagnostic [ ] {
292
+ return getDiagnosticsHelper ( sourceFile , getSyntacticDiagnosticsForFile , cancellationToken ) ;
280
293
}
281
294
282
- function getSemanticDiagnostics ( sourceFile ? : SourceFile ) : Diagnostic [ ] {
283
- return getDiagnosticsHelper ( sourceFile , getSemanticDiagnosticsForFile ) ;
295
+ function getSemanticDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationTokenObject ) : Diagnostic [ ] {
296
+ return getDiagnosticsHelper ( sourceFile , getSemanticDiagnosticsForFile , cancellationToken ) ;
284
297
}
285
298
286
- function getDeclarationDiagnostics ( sourceFile ? : SourceFile ) : Diagnostic [ ] {
287
- return getDiagnosticsHelper ( sourceFile , getDeclarationDiagnosticsForFile ) ;
299
+ function getDeclarationDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationTokenObject ) : Diagnostic [ ] {
300
+ return getDiagnosticsHelper ( sourceFile , getDeclarationDiagnosticsForFile , cancellationToken ) ;
288
301
}
289
302
290
- function getSyntacticDiagnosticsForFile ( sourceFile : SourceFile ) : Diagnostic [ ] {
303
+ function getSyntacticDiagnosticsForFile ( sourceFile : SourceFile , cancellationToken : CancellationTokenObject ) : Diagnostic [ ] {
291
304
return sourceFile . parseDiagnostics ;
292
305
}
293
306
294
- function getSemanticDiagnosticsForFile ( sourceFile : SourceFile ) : Diagnostic [ ] {
295
- let typeChecker = getDiagnosticsProducingTypeChecker ( ) ;
307
+ function runWithCancellationToken < T > ( func : ( ) => T ) : T {
308
+ try {
309
+ return func ( ) ;
310
+ }
311
+ catch ( e ) {
312
+ if ( e instanceof OperationCanceledException ) {
313
+ // We were canceled while performing the operation. Because our type checker
314
+ // might be a bad state, we need to throw it away.
315
+ noDiagnosticsTypeChecker = undefined ;
316
+ diagnosticsProducingTypeChecker = undefined ;
317
+ }
296
318
297
- Debug . assert ( ! ! sourceFile . bindDiagnostics ) ;
298
- let bindDiagnostics = sourceFile . bindDiagnostics ;
299
- let checkDiagnostics = typeChecker . getDiagnostics ( sourceFile ) ;
300
- let programDiagnostics = diagnostics . getDiagnostics ( sourceFile . fileName ) ;
319
+ throw e ;
320
+ }
321
+ }
322
+
323
+ function getSemanticDiagnosticsForFile ( sourceFile : SourceFile , cancellationToken : CancellationTokenObject ) : Diagnostic [ ] {
324
+ return runWithCancellationToken ( ( ) => {
325
+ let typeChecker = getDiagnosticsProducingTypeChecker ( ) ;
326
+
327
+ Debug . assert ( ! ! sourceFile . bindDiagnostics ) ;
328
+ let bindDiagnostics = sourceFile . bindDiagnostics ;
329
+ let checkDiagnostics = typeChecker . getDiagnostics ( sourceFile , cancellationToken ) ;
330
+ let programDiagnostics = diagnostics . getDiagnostics ( sourceFile . fileName ) ;
301
331
302
- return bindDiagnostics . concat ( checkDiagnostics ) . concat ( programDiagnostics ) ;
332
+ return bindDiagnostics . concat ( checkDiagnostics ) . concat ( programDiagnostics ) ;
333
+ } ) ;
303
334
}
304
335
305
- function getDeclarationDiagnosticsForFile ( sourceFile : SourceFile ) : Diagnostic [ ] {
306
- if ( ! isDeclarationFile ( sourceFile ) ) {
307
- let resolver = getDiagnosticsProducingTypeChecker ( ) . getEmitResolver ( sourceFile ) ;
308
- // Don't actually write any files since we're just getting diagnostics.
309
- var writeFile : WriteFileCallback = ( ) => { } ;
310
- return ts . getDeclarationDiagnostics ( getEmitHost ( writeFile ) , resolver , sourceFile ) ;
311
- }
336
+ function getDeclarationDiagnosticsForFile ( sourceFile : SourceFile , cancellationToken : CancellationTokenObject ) : Diagnostic [ ] {
337
+ return runWithCancellationToken ( ( ) => {
338
+ if ( ! isDeclarationFile ( sourceFile ) ) {
339
+ let resolver = getDiagnosticsProducingTypeChecker ( ) . getEmitResolver ( sourceFile , cancellationToken ) ;
340
+ // Don't actually write any files since we're just getting diagnostics.
341
+ var writeFile : WriteFileCallback = ( ) => { } ;
342
+ return ts . getDeclarationDiagnostics ( getEmitHost ( writeFile ) , resolver , sourceFile ) ;
343
+ }
344
+ } ) ;
312
345
}
313
346
314
347
function getCompilerOptionsDiagnostics ( ) : Diagnostic [ ] {
0 commit comments