From 000f7a5acfd355a1f0cd87d5c9757d62a3008442 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Mon, 6 Mar 2023 15:37:18 -0800 Subject: [PATCH 1/3] Don't slice whitespace in jsdoc parser unless needed It's only needed when there's an indentation relative to the margin, which is rare. The common case is to skip the whitespace. --- src/compiler/parser.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index be81d789c57d0..d501f6c1d6117 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -8636,14 +8636,14 @@ namespace Parser { break; case SyntaxKind.WhitespaceTrivia: // only collect whitespace if we're already saving comments or have just crossed the comment indent margin - const whitespace = scanner.getTokenText(); + const whitespaceLength = scanner.getTextPos() - scanner.getTokenPos(); if (state === JSDocState.SavingComments) { - comments.push(whitespace); + comments.push(scanner.getTokenText()); } - else if (margin !== undefined && indent + whitespace.length > margin) { - comments.push(whitespace.slice(margin - indent)); + else if (margin !== undefined && indent + whitespaceLength > margin) { + comments.push(scanner.getTokenText().slice(margin - indent)); } - indent += whitespace.length; + indent += whitespaceLength; break; case SyntaxKind.EndOfFileToken: break loop; @@ -8888,12 +8888,12 @@ namespace Parser { pushComment(scanner.getTokenText()); } else { - const whitespace = scanner.getTokenText(); + const whitespaceLength = scanner.getTextPos() - scanner.getTokenPos(); // if the whitespace crosses the margin, take only the whitespace that passes the margin - if (margin !== undefined && indent + whitespace.length > margin) { - comments.push(whitespace.slice(margin - indent)); + if (margin !== undefined && indent + whitespaceLength > margin) { + comments.push(scanner.getTokenText().slice(margin - indent)); } - indent += whitespace.length; + indent += whitespaceLength; } break; case SyntaxKind.OpenBraceToken: From 794b0f39fbcbd4a5df69f617c86310504cee2d25 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Mar 2023 09:26:34 -0800 Subject: [PATCH 2/3] Only slice once, and tokenise leading ` * ` as whitespace From my other experiment. Maybe together they'll be fast! --- src/compiler/parser.ts | 21 +++++++++++++++++---- src/compiler/scanner.ts | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index d501f6c1d6117..c71d56880833d 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2161,6 +2161,9 @@ namespace Parser { return nextTokenWithoutCheck(); } + function nextTokenJSDocInitialIndent(): JSDocSyntaxKind { + return currentToken = scanner.scanJSDocInitialIndent(); + } function nextTokenJSDoc(): JSDocSyntaxKind { return currentToken = scanner.scanJsDocToken(); } @@ -8641,7 +8644,7 @@ namespace Parser { comments.push(scanner.getTokenText()); } else if (margin !== undefined && indent + whitespaceLength > margin) { - comments.push(scanner.getTokenText().slice(margin - indent)); + comments.push(scanner.getText().slice(scanner.getTokenPos() + margin - indent, scanner.getTextPos())); } indent += whitespaceLength; break; @@ -8671,7 +8674,12 @@ namespace Parser { pushComment(scanner.getTokenText()); break; } - nextTokenJSDoc(); + if (state === JSDocState.BeginningOfLine) { + nextTokenJSDocInitialIndent(); + } + else { + nextTokenJSDoc(); + } } removeTrailingWhitespace(comments); if (parts.length && comments.length) { @@ -8891,7 +8899,7 @@ namespace Parser { const whitespaceLength = scanner.getTextPos() - scanner.getTokenPos(); // if the whitespace crosses the margin, take only the whitespace that passes the margin if (margin !== undefined && indent + whitespaceLength > margin) { - comments.push(scanner.getTokenText().slice(margin - indent)); + comments.push(scanner.getText().slice(scanner.getTokenPos() + margin - indent, scanner.getTextPos())); } indent += whitespaceLength; } @@ -8937,7 +8945,12 @@ namespace Parser { break; } previousWhitespace = token() === SyntaxKind.WhitespaceTrivia; - tok = nextTokenJSDoc(); + if (state === JSDocState.BeginningOfLine) { + tok = nextTokenJSDocInitialIndent(); + } + else { + tok = nextTokenJSDoc(); + } } removeLeadingNewlines(comments); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index e517b18e685f8..af054f5f91e4e 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -74,6 +74,8 @@ export interface Scanner { reScanQuestionToken(): SyntaxKind; reScanInvalidIdentifier(): SyntaxKind; scanJsxToken(): JsxTokenSyntaxKind; + /** @internal */ + scanJSDocInitialIndent(): JSDocSyntaxKind; scanJsDocToken(): JSDocSyntaxKind; scan(): SyntaxKind; @@ -1019,6 +1021,7 @@ export function createScanner(languageVersion: ScriptTarget, reScanQuestionToken, reScanInvalidIdentifier, scanJsxToken, + scanJSDocInitialIndent, scanJsDocToken, scan, getText, @@ -2455,6 +2458,22 @@ export function createScanner(languageVersion: ScriptTarget, return scanJsxAttributeValue(); } + function scanJSDocInitialIndent(): JSDocSyntaxKind { + startPos = tokenPos = pos; + tokenFlags = TokenFlags.None; + if (pos >= end) { + return token = SyntaxKind.EndOfFileToken; + } + for (let ch = codePointAt(text, pos); // TODO: Only allow 1 (one) asterisk! + pos < end && (isWhiteSpaceSingleLine(ch) || ch === CharacterCodes.asterisk); + ch = codePointAt(text, pos += charSize(ch))) { + } + if (pos === tokenPos) { + return scanJsDocToken(); + } + return token = SyntaxKind.WhitespaceTrivia; + } + function scanJsDocToken(): JSDocSyntaxKind { startPos = tokenPos = pos; tokenFlags = TokenFlags.None; From ae16f5e24c4fb16b417a59916cd6e5927813fbd2 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 7 Mar 2023 10:12:45 -0800 Subject: [PATCH 3/3] use lint-preferred empty-for formatting --- src/compiler/scanner.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index af054f5f91e4e..8f516fb037ddf 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -2466,8 +2466,7 @@ export function createScanner(languageVersion: ScriptTarget, } for (let ch = codePointAt(text, pos); // TODO: Only allow 1 (one) asterisk! pos < end && (isWhiteSpaceSingleLine(ch) || ch === CharacterCodes.asterisk); - ch = codePointAt(text, pos += charSize(ch))) { - } + ch = codePointAt(text, pos += charSize(ch))); if (pos === tokenPos) { return scanJsDocToken(); }