Squueze perf in syntactic classification.

This commit is contained in:
Cyrus Najmabadi 2015-06-16 17:55:36 -07:00
parent 3bb7be96fa
commit d206f62adb
3 changed files with 62 additions and 27 deletions

View file

@ -376,8 +376,31 @@ namespace ts {
return ch >= CharacterCodes._0 && ch <= CharacterCodes._7;
}
export function couldStartTrivia(text: string, pos: number): boolean {
// Keep in sync with skipTrivia
let ch = text.charCodeAt(pos);
switch (ch) {
case CharacterCodes.carriageReturn:
case CharacterCodes.lineFeed:
case CharacterCodes.tab:
case CharacterCodes.verticalTab:
case CharacterCodes.formFeed:
case CharacterCodes.space:
case CharacterCodes.slash:
// starts of normal trivia
case CharacterCodes.lessThan:
case CharacterCodes.equals:
case CharacterCodes.greaterThan:
// Starts of conflict marker trivia
return true;
default:
return ch > CharacterCodes.maxAsciiCharacter;
}
}
/* @internal */
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
// Keep in sync with couldStartTrivia
while (true) {
let ch = text.charCodeAt(pos);
switch (ch) {

View file

@ -2083,6 +2083,12 @@ namespace ts {
return start <= textSpanEnd(span) && end >= span.start;
}
export function textSpanIntersectsWith2(start1: number, length1: number, start2: number, length2: number) {
let end1 = start1 + length1;
let end2 = start2 + length2;
return start2 <= end1 && end2 >= start1;
}
export function textSpanIntersectsWithPosition(span: TextSpan, position: number) {
return position <= textSpanEnd(span) && position >= span.start;
}

View file

@ -167,7 +167,7 @@ namespace ts {
}
public getFullWidth(): number {
return this.end - this.getFullStart();
return this.end - this.pos;
}
public getLeadingTriviaWidth(sourceFile?: SourceFile): number {
@ -6116,6 +6116,8 @@ namespace ts {
function getEncodedSyntacticClassifications(fileName: string, span: TextSpan): Classifications {
// doesn't use compiler - no need to synchronize with host
let sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
let spanStart = span.start;
let spanLength = span.length;
// Make a scanner we can get trivia from.
let triviaScanner = createScanner(ScriptTarget.Latest, /*skipTrivia:*/ false, sourceFile.text);
@ -6136,6 +6138,11 @@ namespace ts {
triviaScanner.setTextPos(token.pos);
while (true) {
let start = triviaScanner.getTextPos();
// only bother scanning if we have something that could be trivia.
if (!couldStartTrivia(sourceFile.text, start)) {
return start;
}
let kind = triviaScanner.scan();
let end = triviaScanner.getTextPos();
let width = end - start;
@ -6151,33 +6158,31 @@ namespace ts {
}
// Only bother with the trivia if it at least intersects the span of interest.
if (textSpanIntersectsWith(span, start, width)) {
if (isComment(kind)) {
classifyComment(token, kind, start, width);
if (isComment(kind)) {
classifyComment(token, kind, start, width);
// Classifying a comment might cause us to reuse the trivia scanner
// (because of jsdoc comments). So after we classify the comment make
// sure we set the scanner position back to where it needs to be.
triviaScanner.setTextPos(end);
// Classifying a comment might cause us to reuse the trivia scanner
// (because of jsdoc comments). So after we classify the comment make
// sure we set the scanner position back to where it needs to be.
triviaScanner.setTextPos(end);
continue;
}
if (kind === SyntaxKind.ConflictMarkerTrivia) {
let text = sourceFile.text;
let ch = text.charCodeAt(start);
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
// in the classification stream.
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
pushClassification(start, width, ClassificationType.comment);
continue;
}
if (kind === SyntaxKind.ConflictMarkerTrivia) {
let text = sourceFile.text;
let ch = text.charCodeAt(start);
// for the <<<<<<< and >>>>>>> markers, we just add them in as comments
// in the classification stream.
if (ch === CharacterCodes.lessThan || ch === CharacterCodes.greaterThan) {
pushClassification(start, width, ClassificationType.comment);
continue;
}
// for the ======== add a comment for the first line, and then lex all
// subsequent lines up until the end of the conflict marker.
Debug.assert(ch === CharacterCodes.equals);
classifyDisabledMergeCode(text, start, end);
}
// for the ======== add a comment for the first line, and then lex all
// subsequent lines up until the end of the conflict marker.
Debug.assert(ch === CharacterCodes.equals);
classifyDisabledMergeCode(text, start, end);
}
}
}
@ -6298,7 +6303,7 @@ namespace ts {
function classifyToken(token: Node): void {
let tokenStart = classifyLeadingTriviaAndGetTokenStart(token);
let tokenWidth = token.getEnd() - tokenStart;
let tokenWidth = token.end - tokenStart;
Debug.assert(tokenWidth >= 0);
if (tokenWidth > 0) {
let type = classifyTokenType(token.kind, token);
@ -6408,9 +6413,10 @@ namespace ts {
}
// Ignore nodes that don't intersect the original span to classify.
if (textSpanIntersectsWith(span, element.getFullStart(), element.getFullWidth())) {
if (textSpanIntersectsWith2(spanStart, spanLength, element.pos, element.getFullWidth())) {
let children = element.getChildren(sourceFile);
for (let child of children) {
for (let i = 0, n = children.length; i < n; i++) {
let child = children[i];
if (isToken(child)) {
classifyToken(child);
}