build: update npm install command to use --legacy-peer-deps
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.
This commit is contained in:
+95
-222
@@ -21,248 +21,121 @@ const astUtils = require("./utils/ast-utils");
|
||||
* @returns {boolean} `true` if the node is 'NaN' identifier.
|
||||
*/
|
||||
function isNaNIdentifier(node) {
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nodeToCheck =
|
||||
node.type === "SequenceExpression" ? node.expressions.at(-1) : node;
|
||||
|
||||
return (
|
||||
astUtils.isSpecificId(nodeToCheck, "NaN") ||
|
||||
astUtils.isSpecificMemberAccess(nodeToCheck, "Number", "NaN")
|
||||
);
|
||||
return Boolean(node) && (
|
||||
astUtils.isSpecificId(node, "NaN") ||
|
||||
astUtils.isSpecificMemberAccess(node, "Number", "NaN")
|
||||
);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
hasSuggestions: true,
|
||||
type: "problem",
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "Require calls to `isNaN()` when checking for `NaN`",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/use-isnan",
|
||||
},
|
||||
docs: {
|
||||
description: "Require calls to `isNaN()` when checking for `NaN`",
|
||||
recommended: true,
|
||||
url: "https://eslint.org/docs/latest/rules/use-isnan"
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
enforceForSwitchCase: {
|
||||
type: "boolean",
|
||||
},
|
||||
enforceForIndexOf: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
enforceForSwitchCase: {
|
||||
type: "boolean",
|
||||
default: true
|
||||
},
|
||||
enforceForIndexOf: {
|
||||
type: "boolean",
|
||||
default: false
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
],
|
||||
|
||||
defaultOptions: [
|
||||
{
|
||||
enforceForIndexOf: false,
|
||||
enforceForSwitchCase: true,
|
||||
},
|
||||
],
|
||||
messages: {
|
||||
comparisonWithNaN: "Use the isNaN function to compare with NaN.",
|
||||
switchNaN: "'switch(NaN)' can never match a case clause. Use Number.isNaN instead of the switch.",
|
||||
caseNaN: "'case NaN' can never match. Use Number.isNaN before the switch.",
|
||||
indexOfNaN: "Array prototype method '{{ methodName }}' cannot find NaN."
|
||||
}
|
||||
},
|
||||
|
||||
messages: {
|
||||
comparisonWithNaN: "Use the isNaN function to compare with NaN.",
|
||||
switchNaN:
|
||||
"'switch(NaN)' can never match a case clause. Use Number.isNaN instead of the switch.",
|
||||
caseNaN:
|
||||
"'case NaN' can never match. Use Number.isNaN before the switch.",
|
||||
indexOfNaN:
|
||||
"Array prototype method '{{ methodName }}' cannot find NaN.",
|
||||
replaceWithIsNaN: "Replace with Number.isNaN.",
|
||||
replaceWithCastingAndIsNaN:
|
||||
"Replace with Number.isNaN and cast to a Number.",
|
||||
replaceWithFindIndex:
|
||||
"Replace with Array.prototype.{{ methodName }}.",
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
|
||||
create(context) {
|
||||
const [{ enforceForIndexOf, enforceForSwitchCase }] = context.options;
|
||||
const sourceCode = context.sourceCode;
|
||||
const enforceForSwitchCase = !context.options[0] || context.options[0].enforceForSwitchCase;
|
||||
const enforceForIndexOf = context.options[0] && context.options[0].enforceForIndexOf;
|
||||
|
||||
const fixableOperators = new Set(["==", "===", "!=", "!=="]);
|
||||
const castableOperators = new Set(["==", "!="]);
|
||||
/**
|
||||
* Checks the given `BinaryExpression` node for `foo === NaN` and other comparisons.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkBinaryExpression(node) {
|
||||
if (
|
||||
/^(?:[<>]|[!=]=)=?$/u.test(node.operator) &&
|
||||
(isNaNIdentifier(node.left) || isNaNIdentifier(node.right))
|
||||
) {
|
||||
context.report({ node, messageId: "comparisonWithNaN" });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fixer for a binary expression that compares to NaN.
|
||||
* @param {ASTNode} node The node to fix.
|
||||
* @param {function(string): string} wrapValue A function that wraps the compared value with a fix.
|
||||
* @returns {function(Fixer): Fix} The fixer function.
|
||||
*/
|
||||
function getBinaryExpressionFixer(node, wrapValue) {
|
||||
return fixer => {
|
||||
const comparedValue = isNaNIdentifier(node.left)
|
||||
? node.right
|
||||
: node.left;
|
||||
const shouldWrap = comparedValue.type === "SequenceExpression";
|
||||
const shouldNegate = node.operator[0] === "!";
|
||||
/**
|
||||
* Checks the discriminant and all case clauses of the given `SwitchStatement` node for `switch(NaN)` and `case NaN:`
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkSwitchStatement(node) {
|
||||
if (isNaNIdentifier(node.discriminant)) {
|
||||
context.report({ node, messageId: "switchNaN" });
|
||||
}
|
||||
|
||||
const negation = shouldNegate ? "!" : "";
|
||||
let comparedValueText = sourceCode.getText(comparedValue);
|
||||
for (const switchCase of node.cases) {
|
||||
if (isNaNIdentifier(switchCase.test)) {
|
||||
context.report({ node: switchCase, messageId: "caseNaN" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldWrap) {
|
||||
comparedValueText = `(${comparedValueText})`;
|
||||
}
|
||||
/**
|
||||
* Checks the given `CallExpression` node for `.indexOf(NaN)` and `.lastIndexOf(NaN)`.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkCallExpression(node) {
|
||||
const callee = astUtils.skipChainExpression(node.callee);
|
||||
|
||||
const fixedValue = wrapValue(comparedValueText);
|
||||
if (callee.type === "MemberExpression") {
|
||||
const methodName = astUtils.getStaticPropertyName(callee);
|
||||
|
||||
return fixer.replaceText(node, `${negation}${fixedValue}`);
|
||||
};
|
||||
}
|
||||
if (
|
||||
(methodName === "indexOf" || methodName === "lastIndexOf") &&
|
||||
node.arguments.length === 1 &&
|
||||
isNaNIdentifier(node.arguments[0])
|
||||
) {
|
||||
context.report({ node, messageId: "indexOfNaN", data: { methodName } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given `BinaryExpression` node for `foo === NaN` and other comparisons.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkBinaryExpression(node) {
|
||||
if (
|
||||
/^(?:[<>]|[!=]=)=?$/u.test(node.operator) &&
|
||||
(isNaNIdentifier(node.left) || isNaNIdentifier(node.right))
|
||||
) {
|
||||
const suggestedFixes = [];
|
||||
const NaNNode = isNaNIdentifier(node.left)
|
||||
? node.left
|
||||
: node.right;
|
||||
const listeners = {
|
||||
BinaryExpression: checkBinaryExpression
|
||||
};
|
||||
|
||||
const isSequenceExpression =
|
||||
NaNNode.type === "SequenceExpression";
|
||||
const isSuggestable =
|
||||
fixableOperators.has(node.operator) &&
|
||||
!isSequenceExpression;
|
||||
const isCastable = castableOperators.has(node.operator);
|
||||
if (enforceForSwitchCase) {
|
||||
listeners.SwitchStatement = checkSwitchStatement;
|
||||
}
|
||||
|
||||
if (isSuggestable) {
|
||||
suggestedFixes.push({
|
||||
messageId: "replaceWithIsNaN",
|
||||
fix: getBinaryExpressionFixer(
|
||||
node,
|
||||
value => `Number.isNaN(${value})`,
|
||||
),
|
||||
});
|
||||
if (enforceForIndexOf) {
|
||||
listeners.CallExpression = checkCallExpression;
|
||||
}
|
||||
|
||||
if (isCastable) {
|
||||
suggestedFixes.push({
|
||||
messageId: "replaceWithCastingAndIsNaN",
|
||||
fix: getBinaryExpressionFixer(
|
||||
node,
|
||||
value => `Number.isNaN(Number(${value}))`,
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "comparisonWithNaN",
|
||||
suggest: suggestedFixes,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the discriminant and all case clauses of the given `SwitchStatement` node for `switch(NaN)` and `case NaN:`
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkSwitchStatement(node) {
|
||||
if (isNaNIdentifier(node.discriminant)) {
|
||||
context.report({ node, messageId: "switchNaN" });
|
||||
}
|
||||
|
||||
for (const switchCase of node.cases) {
|
||||
if (isNaNIdentifier(switchCase.test)) {
|
||||
context.report({ node: switchCase, messageId: "caseNaN" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given `CallExpression` node for `.indexOf(NaN)` and `.lastIndexOf(NaN)`.
|
||||
* @param {ASTNode} node The node to check.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkCallExpression(node) {
|
||||
const callee = astUtils.skipChainExpression(node.callee);
|
||||
|
||||
if (callee.type === "MemberExpression") {
|
||||
const methodName = astUtils.getStaticPropertyName(callee);
|
||||
|
||||
if (
|
||||
(methodName === "indexOf" ||
|
||||
methodName === "lastIndexOf") &&
|
||||
node.arguments.length <= 2 &&
|
||||
isNaNIdentifier(node.arguments[0])
|
||||
) {
|
||||
/*
|
||||
* To retain side effects, it's essential to address `NaN` beforehand, which
|
||||
* is not possible with fixes like `arr.findIndex(Number.isNaN)`.
|
||||
*/
|
||||
const isSuggestable =
|
||||
node.arguments[0].type !== "SequenceExpression" &&
|
||||
!node.arguments[1];
|
||||
const suggestedFixes = [];
|
||||
|
||||
if (isSuggestable) {
|
||||
const shouldWrap = callee.computed;
|
||||
const findIndexMethod =
|
||||
methodName === "indexOf"
|
||||
? "findIndex"
|
||||
: "findLastIndex";
|
||||
const propertyName = shouldWrap
|
||||
? `"${findIndexMethod}"`
|
||||
: findIndexMethod;
|
||||
|
||||
suggestedFixes.push({
|
||||
messageId: "replaceWithFindIndex",
|
||||
data: { methodName: findIndexMethod },
|
||||
fix: fixer => [
|
||||
fixer.replaceText(
|
||||
callee.property,
|
||||
propertyName,
|
||||
),
|
||||
fixer.replaceText(
|
||||
node.arguments[0],
|
||||
"Number.isNaN",
|
||||
),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "indexOfNaN",
|
||||
data: { methodName },
|
||||
suggest: suggestedFixes,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const listeners = {
|
||||
BinaryExpression: checkBinaryExpression,
|
||||
};
|
||||
|
||||
if (enforceForSwitchCase) {
|
||||
listeners.SwitchStatement = checkSwitchStatement;
|
||||
}
|
||||
|
||||
if (enforceForIndexOf) {
|
||||
listeners.CallExpression = checkCallExpression;
|
||||
}
|
||||
|
||||
return listeners;
|
||||
},
|
||||
return listeners;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user