@@ -1618,7 +1618,6 @@ namespace ts {
1618
1618
export class OperationCanceledException { }
1619
1619
1620
1620
export class CancellationTokenObject {
1621
-
1622
1621
public static None : CancellationTokenObject = new CancellationTokenObject ( null )
1623
1622
1624
1623
constructor ( private cancellationToken : CancellationToken ) {
@@ -6064,6 +6063,26 @@ namespace ts {
6064
6063
return convertClassifications ( getEncodedSemanticClassifications ( fileName , span ) ) ;
6065
6064
}
6066
6065
6066
+ function checkForClassificationCancellation ( kind : SyntaxKind ) {
6067
+ // We don't want to actually call back into our host on every node to find out if we've
6068
+ // been canceled. That would be an enormous amount of chattyness, along with the all
6069
+ // the overhead of marshalling the data to/from the host. So instead we pick a few
6070
+ // reasonable node kinds to bother checking on. These node kinds represent high level
6071
+ // constructs that we would expect to see commonly, but just at a far less frequent
6072
+ // interval.
6073
+ //
6074
+ // For example, in checker.ts (around 750k) we only have around 600 of these constructs.
6075
+ // That means we're calling back into the host around every 1.2k of the file we process.
6076
+ // Lib.d.ts has similar numbers.
6077
+ switch ( kind ) {
6078
+ case SyntaxKind . ModuleDeclaration :
6079
+ case SyntaxKind . ClassDeclaration :
6080
+ case SyntaxKind . InterfaceDeclaration :
6081
+ case SyntaxKind . FunctionDeclaration :
6082
+ cancellationToken . throwIfCancellationRequested ( ) ;
6083
+ }
6084
+ }
6085
+
6067
6086
function getEncodedSemanticClassifications ( fileName : string , span : TextSpan ) : Classifications {
6068
6087
synchronizeHostData ( ) ;
6069
6088
@@ -6131,7 +6150,10 @@ namespace ts {
6131
6150
function processNode ( node : Node ) {
6132
6151
// Only walk into nodes that intersect the requested span.
6133
6152
if ( node && textSpanIntersectsWith ( span , node . getFullStart ( ) , node . getFullWidth ( ) ) ) {
6134
- if ( node . kind === SyntaxKind . Identifier && ! nodeIsMissing ( node ) ) {
6153
+ let kind = node . kind ;
6154
+ checkForClassificationCancellation ( kind ) ;
6155
+
6156
+ if ( kind === SyntaxKind . Identifier && ! nodeIsMissing ( node ) ) {
6135
6157
let identifier = < Identifier > node ;
6136
6158
6137
6159
// Only bother calling into the typechecker if this is an identifier that
@@ -6498,6 +6520,8 @@ namespace ts {
6498
6520
6499
6521
// Ignore nodes that don't intersect the original span to classify.
6500
6522
if ( decodedTextSpanIntersectsWith ( spanStart , spanLength , element . pos , element . getFullWidth ( ) ) ) {
6523
+ checkForClassificationCancellation ( element . kind ) ;
6524
+
6501
6525
let children = element . getChildren ( sourceFile ) ;
6502
6526
for ( let i = 0 , n = children . length ; i < n ; i ++ ) {
6503
6527
let child = children [ i ] ;
0 commit comments