Improve postprocess perf for type cast comments (#17566)
Co-authored-by: fisker <lionkay@gmail.com>
This commit is contained in:
1 parent
dde5a389e1
commit
eaa40aa266
5 files changed
+47
-28
No files matched your search
@@ -80,7 +80,7 @@ function parse(text, options) {
|
||||
throw createParseError(error);
|
||||
}
|
||||
|
||||
return postprocess(ast, { text });
|
||||
return postprocess(ast, { text, supportTypeCastComments: true });
|
||||
}
|
||||
|
||||
export const acorn = createParser(parse);
|
||||
@@ -163,7 +163,7 @@ function createParse({ isExpression = false, optionsCombinations }) {
|
||||
ast = wrapBabelExpression(ast, { text, rootMarker: options.rootMarker });
|
||||
}
|
||||
|
||||
return postprocess(ast, { text });
|
||||
return postprocess(ast, { text, supportTypeCastComments: true });
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,11 @@ async function parseJs(text, options) {
|
||||
// @ts-expect-error -- expected
|
||||
ast.comments = comments;
|
||||
|
||||
return postprocess(ast, { text, parser: "oxc" });
|
||||
return postprocess(ast, {
|
||||
text,
|
||||
parser: "oxc",
|
||||
supportTypeCastComments: true,
|
||||
});
|
||||
}
|
||||
|
||||
async function parseTs(text, options) {
|
||||
|
||||
@@ -34,32 +34,32 @@ const isNodeWithRaw = createTypeCheckFunction([
|
||||
* @param {{
|
||||
* text: string,
|
||||
* parser?: string,
|
||||
* supportTypeCastComments?: boolean,
|
||||
* oxcAstType?: string,
|
||||
* }} options
|
||||
*/
|
||||
function postprocess(ast, options) {
|
||||
const { parser, text } = options;
|
||||
const { parser, text, supportTypeCastComments } = options;
|
||||
const { comments } = ast;
|
||||
|
||||
// `InterpreterDirective` from babel parser and flow parser
|
||||
// Other parsers parse it as comment, babel treat it as comment too
|
||||
// https://github.com/babel/babel/issues/15116
|
||||
const program = ast.type === "File" ? ast.program : ast;
|
||||
const { interpreter } = program;
|
||||
if (interpreter) {
|
||||
ast.comments.unshift(interpreter);
|
||||
if (program.interpreter) {
|
||||
comments.unshift(program.interpreter);
|
||||
delete program.interpreter;
|
||||
}
|
||||
|
||||
if (parser === "oxc" && options.oxcAstType === "ts" && ast.hashbang) {
|
||||
const { comments, hashbang } = ast;
|
||||
comments.unshift(hashbang);
|
||||
delete program.hashbang;
|
||||
comments.unshift(ast.hashbang);
|
||||
delete ast.hashbang;
|
||||
}
|
||||
|
||||
if (ast.comments.length > 0) {
|
||||
if (comments.length > 0) {
|
||||
let followingComment;
|
||||
for (let i = ast.comments.length - 1; i >= 0; i--) {
|
||||
const comment = ast.comments[i];
|
||||
for (let i = comments.length - 1; i >= 0; i--) {
|
||||
const comment = comments[i];
|
||||
|
||||
if (
|
||||
followingComment &&
|
||||
@@ -69,7 +69,7 @@ function postprocess(ast, options) {
|
||||
isIndentableBlockComment(comment) &&
|
||||
isIndentableBlockComment(followingComment)
|
||||
) {
|
||||
ast.comments.splice(i + 1, 1);
|
||||
comments.splice(i + 1, 1);
|
||||
comment.value += "*//*" + followingComment.value;
|
||||
comment.range = [locStart(comment), locEnd(followingComment)];
|
||||
}
|
||||
@@ -88,6 +88,15 @@ function postprocess(ast, options) {
|
||||
}
|
||||
}
|
||||
|
||||
const typeCastCommentsEnds = [];
|
||||
if (supportTypeCastComments) {
|
||||
for (const comment of comments) {
|
||||
if (isTypeCastComment(comment)) {
|
||||
typeCastCommentsEnds.push(locEnd(comment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast = visitNode(ast, (node) => {
|
||||
switch (node.type) {
|
||||
case "ParenthesizedExpression": {
|
||||
@@ -101,14 +110,13 @@ function postprocess(ast, options) {
|
||||
}
|
||||
|
||||
// Keep ParenthesizedExpression nodes only if they have Closure-style type cast comments.
|
||||
const previousComment = ast.comments.findLast(
|
||||
(comment) => locEnd(comment) <= start,
|
||||
const previousCommentEnd = typeCastCommentsEnds.findLast(
|
||||
(end) => end <= start,
|
||||
);
|
||||
const keepTypeCast =
|
||||
previousComment &&
|
||||
isTypeCastComment(previousComment) &&
|
||||
previousCommentEnd &&
|
||||
// check that there are only white spaces between the comment and the parenthesis
|
||||
text.slice(locEnd(previousComment), start).trim().length === 0;
|
||||
text.slice(previousCommentEnd, start).trim().length === 0;
|
||||
|
||||
if (!keepTypeCast) {
|
||||
expression.extra = { ...expression.extra, parenthesized: true };
|
||||
@@ -202,7 +210,7 @@ function postprocess(ast, options) {
|
||||
const textWithoutComments = getTextWithoutComments(
|
||||
{
|
||||
originalText: text,
|
||||
[Symbol.for("comments")]: ast.comments,
|
||||
[Symbol.for("comments")]: comments,
|
||||
},
|
||||
idEnd,
|
||||
members[0] ? locStart(members[0]) : locEnd(node),
|
||||
|
||||
@@ -4,19 +4,26 @@ import isBlockComment from "./is-block-comment.js";
|
||||
* @import {Comment} from "../types/estree.js"
|
||||
*/
|
||||
|
||||
const cache = new WeakMap();
|
||||
|
||||
/**
|
||||
* @param {Comment} comment
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isTypeCastComment(comment) {
|
||||
return (
|
||||
isBlockComment(comment) &&
|
||||
comment.value[0] === "*" &&
|
||||
// TypeScript expects the type to be enclosed in curly brackets, however
|
||||
// Closure Compiler accepts types in parens and even without any delimiters at all.
|
||||
// That's why we just search for "@type" and "@satisfies".
|
||||
/@(?:type|satisfies)\b/u.test(comment.value)
|
||||
);
|
||||
if (!cache.has(comment)) {
|
||||
cache.set(
|
||||
comment,
|
||||
isBlockComment(comment) &&
|
||||
comment.value[0] === "*" &&
|
||||
// TypeScript expects the type to be enclosed in curly brackets, however
|
||||
// Closure Compiler accepts types in parens and even without any delimiters at all.
|
||||
// That's why we just search for "@type" and "@satisfies".
|
||||
/@(?:type|satisfies)\b/u.test(comment.value),
|
||||
);
|
||||
}
|
||||
|
||||
return cache.get(comment);
|
||||
}
|
||||
|
||||
export default isTypeCastComment;
|
||||
Reference in new issue
Block a user