From 958a423142dad45c4e9f51e461d383f51cbe8ed5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 18 Jun 2015 08:56:48 -0700 Subject: [PATCH] Make classification cancellable. --- src/services/services.ts | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/services/services.ts b/src/services/services.ts index bab5b7707ef..188e711ed9f 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -5986,6 +5986,26 @@ namespace ts { return convertClassifications(getEncodedSemanticClassifications(fileName, span)); } + function checkForClassificationCancellation(kind: SyntaxKind) { + // We don't want to actually call back into our host on every node to find out if we've + // been canceled. That would be an enormous amount of chattyness, along with the all + // the overhead of marshalling the data to/from the host. So instead we pick a few + // reasonable node kinds to bother checking on. These node kinds represent high level + // constructs that we would expect to see commonly, but just at a far less frequent + // interval. + // + // For example, in checker.ts (around 750k) we only have around 600 of these constructs. + // That means we're calling back into the host around every 1.2k of the file we process. + // Lib.d.ts has similar numbers. + switch (kind) { + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.FunctionDeclaration: + cancellationToken.throwIfCancellationRequested(); + } + } + function getEncodedSemanticClassifications(fileName: string, span: TextSpan): Classifications { synchronizeHostData(); @@ -6053,7 +6073,10 @@ namespace ts { function processNode(node: Node) { // Only walk into nodes that intersect the requested span. if (node && textSpanIntersectsWith(span, node.getFullStart(), node.getFullWidth())) { - if (node.kind === SyntaxKind.Identifier && !nodeIsMissing(node)) { + let kind = node.kind; + checkForClassificationCancellation(kind); + + if (kind === SyntaxKind.Identifier && !nodeIsMissing(node)) { let identifier = node; // Only bother calling into the typechecker if this is an identifier that @@ -6405,6 +6428,8 @@ namespace ts { // Ignore nodes that don't intersect the original span to classify. if (textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) { + checkForClassificationCancellation(element.kind); + let children = element.getChildren(sourceFile); for (let child of children) { if (isToken(child)) {