This change modifies the build scripts to use --legacy-peer-deps flag when installing npm dependencies to resolve potential peer dependency conflicts during the build process. The change is applied to both bash (build.sh) and batch (build.bat) build scripts.
167 lines
6.8 KiB
JavaScript
167 lines
6.8 KiB
JavaScript
/**
|
|
* @fileoverview Rule to flag no-unneeded-ternary
|
|
* @author Gyandeep Singh
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
const astUtils = require("./utils/ast-utils");
|
|
|
|
// Operators that always result in a boolean value
|
|
const BOOLEAN_OPERATORS = new Set(["==", "===", "!=", "!==", ">", ">=", "<", "<=", "in", "instanceof"]);
|
|
const OPERATOR_INVERSES = {
|
|
"==": "!=",
|
|
"!=": "==",
|
|
"===": "!==",
|
|
"!==": "==="
|
|
|
|
// Operators like < and >= are not true inverses, since both will return false with NaN.
|
|
};
|
|
const OR_PRECEDENCE = astUtils.getPrecedence({ type: "LogicalExpression", operator: "||" });
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//------------------------------------------------------------------------------
|
|
|
|
/** @type {import('../shared/types').Rule} */
|
|
module.exports = {
|
|
meta: {
|
|
type: "suggestion",
|
|
|
|
docs: {
|
|
description: "Disallow ternary operators when simpler alternatives exist",
|
|
recommended: false,
|
|
url: "https://eslint.org/docs/latest/rules/no-unneeded-ternary"
|
|
},
|
|
|
|
schema: [
|
|
{
|
|
type: "object",
|
|
properties: {
|
|
defaultAssignment: {
|
|
type: "boolean",
|
|
default: true
|
|
}
|
|
},
|
|
additionalProperties: false
|
|
}
|
|
],
|
|
|
|
fixable: "code",
|
|
|
|
messages: {
|
|
unnecessaryConditionalExpression: "Unnecessary use of boolean literals in conditional expression.",
|
|
unnecessaryConditionalAssignment: "Unnecessary use of conditional expression for default assignment."
|
|
}
|
|
},
|
|
|
|
create(context) {
|
|
const options = context.options[0] || {};
|
|
const defaultAssignment = options.defaultAssignment !== false;
|
|
const sourceCode = context.sourceCode;
|
|
|
|
/**
|
|
* Test if the node is a boolean literal
|
|
* @param {ASTNode} node The node to report.
|
|
* @returns {boolean} True if the its a boolean literal
|
|
* @private
|
|
*/
|
|
function isBooleanLiteral(node) {
|
|
return node.type === "Literal" && typeof node.value === "boolean";
|
|
}
|
|
|
|
/**
|
|
* Creates an expression that represents the boolean inverse of the expression represented by the original node
|
|
* @param {ASTNode} node A node representing an expression
|
|
* @returns {string} A string representing an inverted expression
|
|
*/
|
|
function invertExpression(node) {
|
|
if (node.type === "BinaryExpression" && Object.prototype.hasOwnProperty.call(OPERATOR_INVERSES, node.operator)) {
|
|
const operatorToken = sourceCode.getFirstTokenBetween(
|
|
node.left,
|
|
node.right,
|
|
token => token.value === node.operator
|
|
);
|
|
const text = sourceCode.getText();
|
|
|
|
return text.slice(node.range[0],
|
|
operatorToken.range[0]) + OPERATOR_INVERSES[node.operator] + text.slice(operatorToken.range[1], node.range[1]);
|
|
}
|
|
|
|
if (astUtils.getPrecedence(node) < astUtils.getPrecedence({ type: "UnaryExpression" })) {
|
|
return `!(${astUtils.getParenthesisedText(sourceCode, node)})`;
|
|
}
|
|
return `!${astUtils.getParenthesisedText(sourceCode, node)}`;
|
|
}
|
|
|
|
/**
|
|
* Tests if a given node always evaluates to a boolean value
|
|
* @param {ASTNode} node An expression node
|
|
* @returns {boolean} True if it is determined that the node will always evaluate to a boolean value
|
|
*/
|
|
function isBooleanExpression(node) {
|
|
return node.type === "BinaryExpression" && BOOLEAN_OPERATORS.has(node.operator) ||
|
|
node.type === "UnaryExpression" && node.operator === "!";
|
|
}
|
|
|
|
/**
|
|
* Test if the node matches the pattern id ? id : expression
|
|
* @param {ASTNode} node The ConditionalExpression to check.
|
|
* @returns {boolean} True if the pattern is matched, and false otherwise
|
|
* @private
|
|
*/
|
|
function matchesDefaultAssignment(node) {
|
|
return node.test.type === "Identifier" &&
|
|
node.consequent.type === "Identifier" &&
|
|
node.test.name === node.consequent.name;
|
|
}
|
|
|
|
return {
|
|
|
|
ConditionalExpression(node) {
|
|
if (isBooleanLiteral(node.alternate) && isBooleanLiteral(node.consequent)) {
|
|
context.report({
|
|
node,
|
|
messageId: "unnecessaryConditionalExpression",
|
|
fix(fixer) {
|
|
if (node.consequent.value === node.alternate.value) {
|
|
|
|
// Replace `foo ? true : true` with just `true`, but don't replace `foo() ? true : true`
|
|
return node.test.type === "Identifier" ? fixer.replaceText(node, node.consequent.value.toString()) : null;
|
|
}
|
|
if (node.alternate.value) {
|
|
|
|
// Replace `foo() ? false : true` with `!(foo())`
|
|
return fixer.replaceText(node, invertExpression(node.test));
|
|
}
|
|
|
|
// Replace `foo ? true : false` with `foo` if `foo` is guaranteed to be a boolean, or `!!foo` otherwise.
|
|
|
|
return fixer.replaceText(node, isBooleanExpression(node.test) ? astUtils.getParenthesisedText(sourceCode, node.test) : `!${invertExpression(node.test)}`);
|
|
}
|
|
});
|
|
} else if (!defaultAssignment && matchesDefaultAssignment(node)) {
|
|
context.report({
|
|
node,
|
|
messageId: "unnecessaryConditionalAssignment",
|
|
fix(fixer) {
|
|
const shouldParenthesizeAlternate =
|
|
(
|
|
astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE ||
|
|
astUtils.isCoalesceExpression(node.alternate)
|
|
) &&
|
|
!astUtils.isParenthesised(sourceCode, node.alternate);
|
|
const alternateText = shouldParenthesizeAlternate
|
|
? `(${sourceCode.getText(node.alternate)})`
|
|
: astUtils.getParenthesisedText(sourceCode, node.alternate);
|
|
const testText = astUtils.getParenthesisedText(sourceCode, node.test);
|
|
|
|
return fixer.replaceText(node, `${testText} || ${alternateText}`);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|