Speed up incremental parsing

This commit is contained in:
Cyrus Najmabadi 2014-11-02 19:31:31 -08:00
parent 4e55bcf2a0
commit 329d3d5f13
2 changed files with 27 additions and 29 deletions

View File

@ -184,8 +184,8 @@ module TypeScript.Syntax {
return <ISyntaxNode>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());

View File

@ -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 <ISyntaxToken>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 {