From 329d3d5f13049daef4f2e10240a739ec2ae63696 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Sun, 2 Nov 2014 19:31:31 -0800 Subject: [PATCH] Speed up incremental parsing --- src/services/syntax/syntax.ts | 8 ++--- src/services/syntax/syntaxElement.ts | 48 +++++++++++++--------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/services/syntax/syntax.ts b/src/services/syntax/syntax.ts index 2f0b5853bd8..f1081f49021 100644 --- a/src/services/syntax/syntax.ts +++ b/src/services/syntax/syntax.ts @@ -184,8 +184,8 @@ module TypeScript.Syntax { return current; } - export function findTokenOnLeft(element: ISyntaxElement, position: number): ISyntaxToken { - var positionedToken = findToken(element, position); + export function findTokenOnLeft(sourceUnit: SourceUnitSyntax, position: number): ISyntaxToken { + var positionedToken = findToken(sourceUnit, position); var _start = start(positionedToken); // Position better fall within this token. @@ -206,8 +206,8 @@ module TypeScript.Syntax { return previousToken(positionedToken); } - export function findCompleteTokenOnLeft(element: ISyntaxElement, position: number): ISyntaxToken { - var positionedToken = findToken(element, position); + export function findCompleteTokenOnLeft(sourceUnit: SourceUnitSyntax, position: number): ISyntaxToken { + var positionedToken = findToken(sourceUnit, position); // Position better fall within this token. // Debug.assert(position >= positionedToken.fullStart()); diff --git a/src/services/syntax/syntaxElement.ts b/src/services/syntax/syntaxElement.ts index d6d7b374e7d..11f46ba1b54 100644 --- a/src/services/syntax/syntaxElement.ts +++ b/src/services/syntax/syntaxElement.ts @@ -58,18 +58,26 @@ module TypeScript { * Note: findToken will always return a non-missing token with width greater than or equal to * 1 (except for EOF). Empty tokens synthesized by the parser are never returned. */ - export function findToken(element: ISyntaxElement, position: number): ISyntaxToken { - var endOfFileToken = tryGetEndOfFileAt(element, position); - if (endOfFileToken) { - return endOfFileToken; - } - - if (position < 0 || position >= fullWidth(element)) { + export function findToken(sourceUnit: SourceUnitSyntax, position: number): ISyntaxToken { + if (position < 0) { throw Errors.argumentOutOfRange("position"); } - var positionedToken = findTokenWorker(element, 0, position); - return positionedToken; + var token = findTokenWorker(sourceUnit, 0, position); + if (token) { + Debug.assert(token.fullWidth() > 0); + return token; + } + + if (position === fullWidth(sourceUnit)) { + return sourceUnit.endOfFileToken; + } + + if (position > fullWidth(sourceUnit)) { + throw Errors.argumentOutOfRange("position"); + } + + throw Errors.invalidOperation(); } export function findSkippedTokenInPositionedToken(positionedToken: ISyntaxToken, position: number): ISyntaxToken { @@ -115,37 +123,27 @@ module TypeScript { } function findTokenWorker(element: ISyntaxElement, elementPosition: number, position: number): ISyntaxToken { - // Debug.assert(position >= 0 && position < this.fullWidth()); if (isToken(element)) { - Debug.assert(fullWidth(element) > 0); return element; } - if (isShared(element)) { - // This should never have been called on this element. It has a 0 width, so the client - // should have skipped over this. - throw Errors.invalidOperation(); - } - // Consider: we could use a binary search here to find the child more quickly. for (var i = 0, n = element.childCount(); i < n; i++) { var child = element.childAt(i); if (child) { var childFullWidth = fullWidth(child); - if (childFullWidth > 0) { - var elementEndPosition = elementPosition + childFullWidth; + var elementEndPosition = elementPosition + childFullWidth; - if (position < elementEndPosition) { - return findTokenWorker(child, elementPosition, position); - } - - elementPosition = elementEndPosition; + if (position < elementEndPosition) { + return findTokenWorker(child, elementPosition, position); } + + elementPosition = elementEndPosition; } } - throw Errors.invalidOperation(); + return undefined; } function tryGetEndOfFileAt(element: ISyntaxElement, position: number): ISyntaxToken {