Urara-Blog/node_modules/.pnpm-store/v3/files/ec/c75b8866558d6710e092cec3d72d5de95b4c8932cf8f1edcd16571fad5927a752ffb81cbf25540cac7db29b0d9ce52d2465fb878f3075e20b76c5b58e63562
2022-08-14 01:14:53 +08:00

140 lines
No EOL
5.5 KiB
Text

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getWrappingFixer = void 0;
const utils_1 = require("@typescript-eslint/utils");
/**
* Wraps node with some code. Adds parenthesis as necessary.
* @returns Fixer which adds the specified code and parens if necessary.
*/
function getWrappingFixer(params) {
const { sourceCode, node, innerNode = node, wrap } = params;
const innerNodes = Array.isArray(innerNode) ? innerNode : [innerNode];
return (fixer) => {
const innerCodes = innerNodes.map(innerNode => {
let code = sourceCode.getText(innerNode);
// check the inner expression's precedence
if (!isStrongPrecedenceNode(innerNode)) {
// the code we are adding might have stronger precedence than our wrapped node
// let's wrap our node in parens in case it has a weaker precedence than the code we are wrapping it in
code = `(${code})`;
}
return code;
});
// do the wrapping
let code = wrap(...innerCodes);
// check the outer expression's precedence
if (isWeakPrecedenceParent(node)) {
// we wrapped the node in some expression which very likely has a different precedence than original wrapped node
// let's wrap the whole expression in parens just in case
if (!utils_1.ASTUtils.isParenthesized(node, sourceCode)) {
code = `(${code})`;
}
}
// check if we need to insert semicolon
if (/^[`([]/.exec(code) && isMissingSemicolonBefore(node, sourceCode)) {
code = `;${code}`;
}
return fixer.replaceText(node, code);
};
}
exports.getWrappingFixer = getWrappingFixer;
/**
* Check if a node will always have the same precedence if it's parent changes.
*/
function isStrongPrecedenceNode(innerNode) {
return (innerNode.type === utils_1.AST_NODE_TYPES.Literal ||
innerNode.type === utils_1.AST_NODE_TYPES.Identifier ||
innerNode.type === utils_1.AST_NODE_TYPES.ArrayExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.ObjectExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.MemberExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.CallExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.NewExpression ||
innerNode.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression);
}
/**
* Check if a node's parent could have different precedence if the node changes.
*/
function isWeakPrecedenceParent(node) {
const parent = node.parent;
if (parent.type === utils_1.AST_NODE_TYPES.UpdateExpression ||
parent.type === utils_1.AST_NODE_TYPES.UnaryExpression ||
parent.type === utils_1.AST_NODE_TYPES.BinaryExpression ||
parent.type === utils_1.AST_NODE_TYPES.LogicalExpression ||
parent.type === utils_1.AST_NODE_TYPES.ConditionalExpression ||
parent.type === utils_1.AST_NODE_TYPES.AwaitExpression) {
return true;
}
if (parent.type === utils_1.AST_NODE_TYPES.MemberExpression &&
parent.object === node) {
return true;
}
if ((parent.type === utils_1.AST_NODE_TYPES.CallExpression ||
parent.type === utils_1.AST_NODE_TYPES.NewExpression) &&
parent.callee === node) {
return true;
}
if (parent.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression &&
parent.tag === node) {
return true;
}
return false;
}
/**
* Returns true if a node is at the beginning of expression statement and the statement above doesn't end with semicolon.
* Doesn't check if the node begins with `(`, `[` or `` ` ``.
*/
function isMissingSemicolonBefore(node, sourceCode) {
for (;;) {
const parent = node.parent;
if (parent.type === utils_1.AST_NODE_TYPES.ExpressionStatement) {
const block = parent.parent;
if (block.type === utils_1.AST_NODE_TYPES.Program ||
block.type === utils_1.AST_NODE_TYPES.BlockStatement) {
// parent is an expression statement in a block
const statementIndex = block.body.indexOf(parent);
const previousStatement = block.body[statementIndex - 1];
if (statementIndex > 0 &&
sourceCode.getLastToken(previousStatement).value !== ';') {
return true;
}
}
}
if (!isLeftHandSide(node)) {
return false;
}
node = parent;
}
}
/**
* Checks if a node is LHS of an operator.
*/
function isLeftHandSide(node) {
const parent = node.parent;
// a++
if (parent.type === utils_1.AST_NODE_TYPES.UpdateExpression) {
return true;
}
// a + b
if ((parent.type === utils_1.AST_NODE_TYPES.BinaryExpression ||
parent.type === utils_1.AST_NODE_TYPES.LogicalExpression ||
parent.type === utils_1.AST_NODE_TYPES.AssignmentExpression) &&
node === parent.left) {
return true;
}
// a ? b : c
if (parent.type === utils_1.AST_NODE_TYPES.ConditionalExpression &&
node === parent.test) {
return true;
}
// a(b)
if (parent.type === utils_1.AST_NODE_TYPES.CallExpression && node === parent.callee) {
return true;
}
// a`b`
if (parent.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression &&
node === parent.tag) {
return true;
}
return false;
}
//# sourceMappingURL=getWrappingFixer.js.map