Switch js parse postprocess to onEnter (#18382)

This commit is contained in:
fisker Cheung authored and GitHub committed 2025-12-01 19:36:05 +08:00
1 parent d3eb2b2d08
commit 706aa4ef90
7 files changed
+70 -49

No files matched your search

+2 -1
View File
@@ -1,4 +1,5 @@
import PostcssValuesParser from "postcss-values-parser/lib/parser.js";
import isObject from "../../utilities/is-object.js";
import getFunctionArgumentsText from "../utilities/get-function-arguments-text.js";
import getValueRoot from "../utilities/get-value-root.js";
import hasSCSSInterpolation from "../utilities/has-scss-interpolation.js";
@@ -156,7 +157,7 @@ function flattenGroups(node) {
}
function parseNestedValue(node, options) {
if (node && typeof node === "object") {
if (isObject(node)) {
for (const key in node) {
if (key !== "parent") {
parseNestedValue(node[key], options);
+4 -2
View File
@@ -1,5 +1,7 @@
import isObject from "../../utilities/is-object.js";
function addTypePrefix(node, prefix, skipPrefix) {
if (node && typeof node === "object") {
if (isObject(node)) {
delete node.parent;
for (const key in node) {
addTypePrefix(node[key], prefix, skipPrefix);
@@ -17,7 +19,7 @@ function addTypePrefix(node, prefix, skipPrefix) {
}
function addMissingType(node) {
if (node && typeof node === "object") {
if (isObject(node)) {
delete node.parent;
for (const key in node) {
addMissingType(node[key]);
+2 -1
View File
@@ -3,6 +3,7 @@ import postcssLess from "postcss-less";
import postcssScssParse from "postcss-scss/lib/scss-parse";
import createError from "../common/parser-create-error.js";
import { parseFrontMatter } from "../main/front-matter/index.js";
import isObject from "../utilities/is-object.js";
import {
calculateLoc,
locEnd,
@@ -21,7 +22,7 @@ const DEFAULT_SCSS_DIRECTIVE = /(\s*)(!default).*$/u;
const GLOBAL_SCSS_DIRECTIVE = /(\s*)(!global).*$/u;
function parseNestedCSS(node, options) {
if (node && typeof node === "object") {
if (isObject(node)) {
delete node.parent;
for (const key in node) {
+44 -39
View File
@@ -43,10 +43,31 @@ function postprocess(ast, options) {
mergeNestledJsdocComments(comments);
// `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;
if (program.interpreter) {
comments.unshift(program.interpreter);
delete program.interpreter;
}
if (isOxcTs && ast.hashbang) {
comments.unshift(ast.hashbang);
delete ast.hashbang;
}
// In `typescript` and `flow`, `Program` doesn't count whitespace and comments
// See https://github.com/typescript-eslint/typescript-eslint/issues/11026
// See https://github.com/facebook/flow/issues/8537
if (ast.type === "Program") {
ast.range = [0, text.length];
}
let typeCastCommentsEnds;
ast = visitNode(ast, {
onLeave(node) {
onEnter(node) {
switch (node.type) {
case "ParenthesizedExpression": {
const { expression } = node;
@@ -58,7 +79,7 @@ function postprocess(ast, options) {
return expression;
}
let keepTypeCast = false;
let shouldKeepParenthesizedExpression = false;
if (!isOxcTs) {
if (!typeCastCommentsEnds) {
typeCastCommentsEnds = [];
@@ -74,27 +95,21 @@ function postprocess(ast, options) {
const previousCommentEnd = typeCastCommentsEnds.findLast(
(end) => end <= start,
);
keepTypeCast =
shouldKeepParenthesizedExpression =
previousCommentEnd &&
// check that there are only white spaces between the comment and the parenthesis
text.slice(previousCommentEnd, start).trim().length === 0;
}
if (!keepTypeCast) {
expression.extra = { ...expression.extra, parenthesized: true };
return expression;
if (shouldKeepParenthesizedExpression) {
return;
}
break;
expression.extra = { ...expression.extra, parenthesized: true };
return expression;
}
case "LogicalExpression":
// We remove unneeded parens around same-operator LogicalExpressions
if (isUnbalancedLogicalTree(node)) {
return rebalanceLogicalTree(node);
}
break;
// This happens when use `oxc-parser` to parse `` `${foo satisfies bar}`; ``
// This happened when use `oxc-parser` to parse `` `${foo satisfies bar}`; ``
// https://github.com/oxc-project/oxc/issues/11313
case "TemplateLiteral":
/* c8 ignore next 3 */
@@ -128,6 +143,7 @@ function postprocess(ast, options) {
}
break;
}
// remove redundant TypeScript nodes
case "TSParenthesizedType":
return node.typeAnnotation;
@@ -135,9 +151,7 @@ function postprocess(ast, options) {
// For hack-style pipeline
case "TopicReference":
ast.extra = { ...ast.extra, __isUsingHackPipeline: true };
break;
// In Flow parser, it doesn't generate union/intersection types for single type
break; // In Flow parser, it doesn't generate union/intersection types for single type
case "TSUnionType":
case "TSIntersectionType":
if (node.types.length === 1) {
@@ -151,9 +165,21 @@ function postprocess(ast, options) {
node.options = node.attributes;
}
break;
}
},
onLeave(node) {
switch (node.type) {
// Children can be parenthesized, need do this in `onLeave`
case "LogicalExpression":
// We remove unneeded parens around same-operator LogicalExpressions
if (isUnbalancedLogicalTree(node)) {
return rebalanceLogicalTree(node);
}
break;
// https://github.com/babel/babel/issues/17506
// https://github.com/oxc-project/oxc/issues/16074
// It's possible to have parenthesized `argument`, need do this in `onLeave`
case "TSImportType":
if (!node.source && node.argument.type === "TSLiteralType") {
node.source = node.argument.literal;
@@ -169,31 +195,10 @@ function postprocess(ast, options) {
},
});
// `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;
if (program.interpreter) {
comments.unshift(program.interpreter);
delete program.interpreter;
}
if (isOxcTs && ast.hashbang) {
comments.unshift(ast.hashbang);
delete ast.hashbang;
}
/* c8 ignore next 3 */
if (process.env.NODE_ENV !== "production") {
assertComments(comments, text);
}
// In `typescript` and `flow`, `Program` doesn't count whitespace and comments
// See https://github.com/typescript-eslint/typescript-eslint/issues/11026
// See https://github.com/facebook/flow/issues/8537
if (ast.type === "Program") {
ast.range = [0, text.length];
}
return ast;
}
@@ -1,7 +1,8 @@
import isObject from "../../../utilities/is-object.js";
import getVisitorKeys from "../../traverse/get-visitor-keys.js";
function visitNode(node, options) {
if (!(node !== null && typeof node === "object")) {
if (!isObject(node)) {
return node;
}
@@ -16,7 +17,13 @@ function visitNode(node, options) {
}
if (options.onEnter) {
node = options.onEnter(node) || node;
const result = options.onEnter(node) ?? node;
// If node is replaced, re-enter
if (result !== node) {
return visitNode(result, options);
}
node = result;
}
const keys = getVisitorKeys(node);
@@ -24,7 +31,11 @@ function visitNode(node, options) {
node[keys[i]] = visitNode(node[keys[i]], options);
}
return options.onLeave(node) || node;
if (options.onLeave) {
node = options.onLeave(node) || node;
}
return node;
}
export default visitNode;
+2 -1
View File
@@ -3,6 +3,7 @@ import getStringWidth from "../../utilities/get-string-width.js";
import hasNewline from "../../utilities/has-newline.js";
import isNextLineEmptyAfterIndex from "../../utilities/is-next-line-empty.js";
import isNonEmptyArray from "../../utilities/is-non-empty-array.js";
import isObject from "../../utilities/is-object.js";
import printString from "../../utilities/print-string.js";
import { hasSameLocStart, locEnd, locStart } from "../loc.js";
import getVisitorKeys from "../traverse/get-visitor-keys.js";
@@ -417,7 +418,7 @@ function getExpressionInnerNodeCount(node, maxCount) {
for (const k in node) {
const prop = node[k];
if (prop && typeof prop === "object" && typeof prop.type === "string") {
if (isObject(prop) && typeof prop.type === "string") {
count++;
count += getExpressionInnerNodeCount(prop, maxCount - count);
}
+2 -2
View File
@@ -1,5 +1,6 @@
import AstPath from "../common/ast-path.js";
import { cursor, inheritLabel } from "../document/index.js";
import isObject from "../utilities/is-object.js";
import { attachComments } from "./comments/attach.js";
import { ensureAllCommentsPrinted, printComments } from "./comments/print.js";
import createPrintPreCheckFunction from "./create-print-pre-check-function.js";
@@ -82,8 +83,7 @@ async function printAstToDoc(ast, options) {
return "";
}
const shouldCache =
value && typeof value === "object" && args === undefined;
const shouldCache = isObject(value) && args === undefined;
if (shouldCache && cache.has(value)) {
return cache.get(value);