Refactor simple member expressions etc (#15423)

This commit is contained in:
Alex Rattray authored and GitHub committed 2023-09-17 23:30:18 +09:00
1 parent 86d0d146e6
commit 77310c49ea
4 files changed
+154 -111

No files matched your search

+1 -44
View File
@@ -16,15 +16,12 @@ import {
isCallExpression,
isMemberExpression,
getCallArguments,
rawText,
hasComment,
isSignedNumericLiteral,
isLoneShortArgument,
isObjectProperty,
createTypeCheckFunction,
} from "../utils/index.js";
import { shouldInlineLogicalExpression } from "./binaryish.js";
import { printCallExpression } from "./call-expression.js";
import { isLiteral } from "./literal.js";
function printAssignment(
path,
@@ -369,46 +366,6 @@ function isPoorlyBreakableMemberOrCallChain(
return deep && (node.type === "Identifier" || node.type === "ThisExpression");
}
const LONE_SHORT_ARGUMENT_THRESHOLD_RATE = 0.25;
function isLoneShortArgument(node, { printWidth }) {
if (hasComment(node)) {
return false;
}
const threshold = printWidth * LONE_SHORT_ARGUMENT_THRESHOLD_RATE;
if (
node.type === "ThisExpression" ||
(node.type === "Identifier" && node.name.length <= threshold) ||
(isSignedNumericLiteral(node) && !hasComment(node.argument))
) {
return true;
}
const regexpPattern =
(node.type === "Literal" && "regex" in node && node.regex.pattern) ||
(node.type === "RegExpLiteral" && node.pattern);
if (regexpPattern) {
return regexpPattern.length <= threshold;
}
if (isStringLiteral(node)) {
return rawText(node).length <= threshold;
}
if (node.type === "TemplateLiteral") {
return (
node.expressions.length === 0 &&
node.quasis[0].value.raw.length <= threshold &&
!node.quasis[0].value.raw.includes("\n")
);
}
return isLiteral(node);
}
function isObjectPropertyWithShortKey(node, keyDoc, options) {
if (!isObjectProperty(node)) {
return false;
+2 -1
View File
@@ -19,6 +19,7 @@ import {
isCallExpression,
isMemberExpression,
isArrayOrTupleExpression,
isLiteral,
isObjectOrRecordExpression,
startsWithNoLookaheadToken,
} from "../utils/index.js";
@@ -67,7 +68,7 @@ import { printBinaryishExpression } from "./binaryish.js";
import { printStatementSequence } from "./statement.js";
import { printMemberExpression } from "./member.js";
import { printBlock, printBlockBody } from "./block.js";
import { printLiteral, isLiteral } from "./literal.js";
import { printLiteral } from "./literal.js";
import { printTypeAnnotationProperty } from "./type-annotation.js";
import { printExpressionStatement } from "./expression-statement.js";
import { printHtmlBinding } from "./html-binding.js";
+1 -19
View File
@@ -1,7 +1,6 @@
import printString from "../../utils/print-string.js";
import printNumber from "../../utils/print-number.js";
import { replaceEndOfLine } from "../../document/utils.js";
import { createTypeCheckFunction } from "../utils/index.js";
/**
* @typedef {import("../types/estree.js").Node} Node
@@ -92,21 +91,4 @@ function printDirective(rawText, options) {
return enclosingQuote + rawContent + enclosingQuote;
}
/**
* @param {Node} node
* @returns {boolean}
*/
const isLiteral = createTypeCheckFunction([
"Literal",
// Babel, flow uses `BigIntLiteral` too
"BigIntLiteral",
"BooleanLiteral",
"DecimalLiteral",
"DirectiveLiteral",
"NullLiteral",
"NumericLiteral",
"RegExpLiteral",
"StringLiteral",
]);
export { printLiteral, printBigInt, isLiteral };
export { printLiteral, printBigInt };
+150 -47
View File
@@ -189,6 +189,35 @@ function isRegExpLiteral(node) {
);
}
/**
* @param {Node} node
* @returns {boolean}
*/
const isLiteral = createTypeCheckFunction([
"Literal",
"BooleanLiteral",
"BigIntLiteral", // Babel, flow use `BigIntLiteral` too
"DecimalLiteral",
"DirectiveLiteral",
"NullLiteral",
"NumericLiteral",
"RegExpLiteral",
"StringLiteral",
]);
/**
* @param {Node} node
* @returns {boolean}
*/
const isSingleWordType = createTypeCheckFunction([
"Identifier",
"ThisExpression",
"Super",
"PrivateName",
"PrivateIdentifier",
"Import",
]);
/**
* @param {Node} node
* @returns {boolean}
@@ -442,47 +471,127 @@ function isSimpleTemplateLiteral(node) {
}
return expressions.every((expr) => {
// Disallow comments since printDocToString can't print them here
if (hasComment(expr)) {
return false;
}
// Allow `x` and `this`
if (expr.type === "Identifier" || expr.type === "ThisExpression") {
if (isSimpleAtomicExpression(expr) || isSimpleMemberExpression(expr)) {
return true;
}
});
}
if (expr.type === "ChainExpression") {
expr = expr.expression;
}
// Allow `a.b.c`, `a.b[c]`, and `this.x.y`
if (isMemberExpression(expr)) {
let head = expr;
while (isMemberExpression(head)) {
if (
head.property.type !== "Identifier" &&
head.property.type !== "Literal" &&
head.property.type !== "StringLiteral" &&
head.property.type !== "NumericLiteral"
) {
return false;
}
head = head.object;
if (hasComment(head)) {
return false;
}
}
if (head.type === "Identifier" || head.type === "ThisExpression") {
return true;
}
function isSimpleMemberExpression(
node,
{ maxDepth = Number.POSITIVE_INFINITY } = {},
) {
if (hasComment(node)) {
return false;
}
if (node.type === "ChainExpression") {
return isSimpleMemberExpression(node.expression, { maxDepth });
}
if (!isMemberExpression(node)) {
return false;
}
let head = node;
let depth = 0;
while (isMemberExpression(head) && depth++ <= maxDepth) {
if (!isSimpleAtomicExpression(head.property)) {
return false;
}
head = head.object;
if (hasComment(head)) {
return false;
}
}
return isSimpleAtomicExpression(head);
}
/**
* This is intended to return true for small expressions
* which cannot be broken.
*/
function isSimpleAtomicExpression(node) {
if (hasComment(node)) {
return false;
});
}
return isLiteral(node) || isSingleWordType(node);
}
/**
* Attempts to gauge the rough complexity of a node, for example
* to detect deeply-nested booleans, call expressions with lots of arguments, etc.
*/
function isSimpleExpressionByNodeCount(node, maxInnerNodeCount = 5) {
const count = getExpressionInnerNodeCount(node, maxInnerNodeCount);
return count <= maxInnerNodeCount;
}
function getExpressionInnerNodeCount(node, maxCount) {
let count = 0;
for (const k in node) {
const prop = node[k];
if (prop && typeof prop === "object" && typeof prop.type === "string") {
count++;
count += getExpressionInnerNodeCount(prop, maxCount - count);
}
// Bail early to protect against bad performance.
if (count > maxCount) {
return count;
}
}
return count;
}
const LONE_SHORT_ARGUMENT_THRESHOLD_RATE = 0.25;
function isLoneShortArgument(node, { printWidth }) {
if (hasComment(node)) {
return false;
}
const threshold = printWidth * LONE_SHORT_ARGUMENT_THRESHOLD_RATE;
if (
node.type === "ThisExpression" ||
(node.type === "Identifier" && node.name.length <= threshold) ||
(isSignedNumericLiteral(node) && !hasComment(node.argument))
) {
return true;
}
const regexpPattern =
(node.type === "Literal" && "regex" in node && node.regex.pattern) ||
(node.type === "RegExpLiteral" && node.pattern);
if (regexpPattern) {
return regexpPattern.length <= threshold;
}
if (isStringLiteral(node)) {
return rawText(node).length <= threshold;
}
if (node.type === "TemplateLiteral") {
return (
node.expressions.length === 0 &&
node.quasis[0].value.raw.length <= threshold &&
!node.quasis[0].value.raw.includes("\n")
);
}
if (node.type === "UnaryExpression") {
return isLoneShortArgument(node.argument, { printWidth });
}
if (
node.type === "CallExpression" &&
node.arguments.length === 0 &&
node.callee.type === "Identifier"
) {
return node.callee.name.length <= threshold - 2;
}
return isLiteral(node);
}
/**
@@ -654,20 +763,9 @@ function isSimpleCallArgument(node, depth = 2) {
}
if (
node.type === "Literal" ||
node.type === "BigIntLiteral" ||
node.type === "DecimalLiteral" ||
node.type === "BooleanLiteral" ||
node.type === "NullLiteral" ||
node.type === "NumericLiteral" ||
node.type === "StringLiteral" ||
node.type === "Identifier" ||
node.type === "ThisExpression" ||
node.type === "Super" ||
node.type === "PrivateName" ||
node.type === "PrivateIdentifier" ||
node.type === "ArgumentPlaceholder" ||
node.type === "Import"
isLiteral(node) ||
isSingleWordType(node) ||
node.type === "ArgumentPlaceholder"
) {
return true;
}
@@ -1151,8 +1249,13 @@ export {
isRegExpLiteral,
isSimpleType,
isSimpleNumber,
isSimpleAtomicExpression,
isSimpleMemberExpression,
isSimpleTemplateLiteral,
isSimpleExpressionByNodeCount,
isLoneShortArgument,
isStringLiteral,
isLiteral,
isStringPropSafeToUnquote,
isTemplateOnItsOwnLine,
isTestCall,