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:
+250
-281
@@ -14,319 +14,288 @@ const astUtils = require("./utils/ast-utils");
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const PRECEDENCE_OF_ASSIGNMENT_EXPR = astUtils.getPrecedence({
|
||||
type: "AssignmentExpression",
|
||||
});
|
||||
const PRECEDENCE_OF_ASSIGNMENT_EXPR = astUtils.getPrecedence({ type: "AssignmentExpression" });
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
docs: {
|
||||
description: "Require destructuring from arrays and/or objects",
|
||||
recommended: false,
|
||||
frozen: true,
|
||||
url: "https://eslint.org/docs/latest/rules/prefer-destructuring",
|
||||
},
|
||||
docs: {
|
||||
description: "Require destructuring from arrays and/or objects",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/prefer-destructuring"
|
||||
},
|
||||
|
||||
fixable: "code",
|
||||
fixable: "code",
|
||||
|
||||
schema: [
|
||||
{
|
||||
/*
|
||||
* old support {array: Boolean, object: Boolean}
|
||||
* new support {VariableDeclarator: {}, AssignmentExpression: {}}
|
||||
*/
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
VariableDeclarator: {
|
||||
type: "object",
|
||||
properties: {
|
||||
array: {
|
||||
type: "boolean",
|
||||
},
|
||||
object: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
AssignmentExpression: {
|
||||
type: "object",
|
||||
properties: {
|
||||
array: {
|
||||
type: "boolean",
|
||||
},
|
||||
object: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
array: {
|
||||
type: "boolean",
|
||||
},
|
||||
object: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
enforceForRenamedProperties: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
schema: [
|
||||
{
|
||||
|
||||
messages: {
|
||||
preferDestructuring: "Use {{type}} destructuring.",
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
const enabledTypes = context.options[0];
|
||||
const enforceForRenamedProperties =
|
||||
context.options[1] &&
|
||||
context.options[1].enforceForRenamedProperties;
|
||||
let normalizedOptions = {
|
||||
VariableDeclarator: { array: true, object: true },
|
||||
AssignmentExpression: { array: true, object: true },
|
||||
};
|
||||
/*
|
||||
* old support {array: Boolean, object: Boolean}
|
||||
* new support {VariableDeclarator: {}, AssignmentExpression: {}}
|
||||
*/
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
VariableDeclarator: {
|
||||
type: "object",
|
||||
properties: {
|
||||
array: {
|
||||
type: "boolean"
|
||||
},
|
||||
object: {
|
||||
type: "boolean"
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
},
|
||||
AssignmentExpression: {
|
||||
type: "object",
|
||||
properties: {
|
||||
array: {
|
||||
type: "boolean"
|
||||
},
|
||||
object: {
|
||||
type: "boolean"
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
array: {
|
||||
type: "boolean"
|
||||
},
|
||||
object: {
|
||||
type: "boolean"
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
enforceForRenamedProperties: {
|
||||
type: "boolean"
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}
|
||||
],
|
||||
|
||||
if (enabledTypes) {
|
||||
normalizedOptions =
|
||||
typeof enabledTypes.array !== "undefined" ||
|
||||
typeof enabledTypes.object !== "undefined"
|
||||
? {
|
||||
VariableDeclarator: enabledTypes,
|
||||
AssignmentExpression: enabledTypes,
|
||||
}
|
||||
: enabledTypes;
|
||||
}
|
||||
messages: {
|
||||
preferDestructuring: "Use {{type}} destructuring."
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
const enabledTypes = context.options[0];
|
||||
const enforceForRenamedProperties = context.options[1] && context.options[1].enforceForRenamedProperties;
|
||||
let normalizedOptions = {
|
||||
VariableDeclarator: { array: true, object: true },
|
||||
AssignmentExpression: { array: true, object: true }
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if destructuring type should be checked.
|
||||
* @param {string} nodeType "AssignmentExpression" or "VariableDeclarator"
|
||||
* @param {string} destructuringType "array" or "object"
|
||||
* @returns {boolean} `true` if the destructuring type should be checked for the given node
|
||||
*/
|
||||
function shouldCheck(nodeType, destructuringType) {
|
||||
return (
|
||||
normalizedOptions &&
|
||||
normalizedOptions[nodeType] &&
|
||||
normalizedOptions[nodeType][destructuringType]
|
||||
);
|
||||
}
|
||||
if (enabledTypes) {
|
||||
normalizedOptions = typeof enabledTypes.array !== "undefined" || typeof enabledTypes.object !== "undefined"
|
||||
? { VariableDeclarator: enabledTypes, AssignmentExpression: enabledTypes }
|
||||
: enabledTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the given node is accessing an array index
|
||||
*
|
||||
* This is used to differentiate array index access from object property
|
||||
* access.
|
||||
* @param {ASTNode} node the node to evaluate
|
||||
* @returns {boolean} whether or not the node is an integer
|
||||
*/
|
||||
function isArrayIndexAccess(node) {
|
||||
return Number.isInteger(node.property.value);
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Report that the given node should use destructuring
|
||||
* @param {ASTNode} reportNode the node to report
|
||||
* @param {string} type the type of destructuring that should have been done
|
||||
* @param {Function|null} fix the fix function or null to pass to context.report
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(reportNode, type, fix) {
|
||||
context.report({
|
||||
node: reportNode,
|
||||
messageId: "preferDestructuring",
|
||||
data: { type },
|
||||
fix,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Checks if destructuring type should be checked.
|
||||
* @param {string} nodeType "AssignmentExpression" or "VariableDeclarator"
|
||||
* @param {string} destructuringType "array" or "object"
|
||||
* @returns {boolean} `true` if the destructuring type should be checked for the given node
|
||||
*/
|
||||
function shouldCheck(nodeType, destructuringType) {
|
||||
return normalizedOptions &&
|
||||
normalizedOptions[nodeType] &&
|
||||
normalizedOptions[nodeType][destructuringType];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a node should be fixed into object destructuring
|
||||
*
|
||||
* The fixer only fixes the simplest case of object destructuring,
|
||||
* like: `let x = a.x`;
|
||||
*
|
||||
* Assignment expression is not fixed.
|
||||
* Array destructuring is not fixed.
|
||||
* Renamed property is not fixed.
|
||||
* @param {ASTNode} node the node to evaluate
|
||||
* @returns {boolean} whether or not the node should be fixed
|
||||
*/
|
||||
function shouldFix(node) {
|
||||
return (
|
||||
node.type === "VariableDeclarator" &&
|
||||
node.id.type === "Identifier" &&
|
||||
node.init.type === "MemberExpression" &&
|
||||
!node.init.computed &&
|
||||
node.init.property.type === "Identifier" &&
|
||||
node.id.name === node.init.property.name
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Determines if the given node is accessing an array index
|
||||
*
|
||||
* This is used to differentiate array index access from object property
|
||||
* access.
|
||||
* @param {ASTNode} node the node to evaluate
|
||||
* @returns {boolean} whether or not the node is an integer
|
||||
*/
|
||||
function isArrayIndexAccess(node) {
|
||||
return Number.isInteger(node.property.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix a node into object destructuring.
|
||||
* This function only handles the simplest case of object destructuring,
|
||||
* see {@link shouldFix}.
|
||||
* @param {SourceCodeFixer} fixer the fixer object
|
||||
* @param {ASTNode} node the node to be fixed.
|
||||
* @returns {Object} a fix for the node
|
||||
*/
|
||||
function fixIntoObjectDestructuring(fixer, node) {
|
||||
const rightNode = node.init;
|
||||
const sourceCode = context.sourceCode;
|
||||
/**
|
||||
* Report that the given node should use destructuring
|
||||
* @param {ASTNode} reportNode the node to report
|
||||
* @param {string} type the type of destructuring that should have been done
|
||||
* @param {Function|null} fix the fix function or null to pass to context.report
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(reportNode, type, fix) {
|
||||
context.report({
|
||||
node: reportNode,
|
||||
messageId: "preferDestructuring",
|
||||
data: { type },
|
||||
fix
|
||||
});
|
||||
}
|
||||
|
||||
// Don't fix if that would remove any comments. Only comments inside `rightNode.object` can be preserved.
|
||||
if (
|
||||
sourceCode.getCommentsInside(node).length >
|
||||
sourceCode.getCommentsInside(rightNode.object).length
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Determines if a node should be fixed into object destructuring
|
||||
*
|
||||
* The fixer only fixes the simplest case of object destructuring,
|
||||
* like: `let x = a.x`;
|
||||
*
|
||||
* Assignment expression is not fixed.
|
||||
* Array destructuring is not fixed.
|
||||
* Renamed property is not fixed.
|
||||
* @param {ASTNode} node the node to evaluate
|
||||
* @returns {boolean} whether or not the node should be fixed
|
||||
*/
|
||||
function shouldFix(node) {
|
||||
return node.type === "VariableDeclarator" &&
|
||||
node.id.type === "Identifier" &&
|
||||
node.init.type === "MemberExpression" &&
|
||||
!node.init.computed &&
|
||||
node.init.property.type === "Identifier" &&
|
||||
node.id.name === node.init.property.name;
|
||||
}
|
||||
|
||||
let objectText = sourceCode.getText(rightNode.object);
|
||||
/**
|
||||
* Fix a node into object destructuring.
|
||||
* This function only handles the simplest case of object destructuring,
|
||||
* see {@link shouldFix}.
|
||||
* @param {SourceCodeFixer} fixer the fixer object
|
||||
* @param {ASTNode} node the node to be fixed.
|
||||
* @returns {Object} a fix for the node
|
||||
*/
|
||||
function fixIntoObjectDestructuring(fixer, node) {
|
||||
const rightNode = node.init;
|
||||
const sourceCode = context.sourceCode;
|
||||
|
||||
if (
|
||||
astUtils.getPrecedence(rightNode.object) <
|
||||
PRECEDENCE_OF_ASSIGNMENT_EXPR
|
||||
) {
|
||||
objectText = `(${objectText})`;
|
||||
}
|
||||
// Don't fix if that would remove any comments. Only comments inside `rightNode.object` can be preserved.
|
||||
if (sourceCode.getCommentsInside(node).length > sourceCode.getCommentsInside(rightNode.object).length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fixer.replaceText(
|
||||
node,
|
||||
`{${rightNode.property.name}} = ${objectText}`,
|
||||
);
|
||||
}
|
||||
let objectText = sourceCode.getText(rightNode.object);
|
||||
|
||||
/**
|
||||
* Check that the `prefer-destructuring` rules are followed based on the
|
||||
* given left- and right-hand side of the assignment.
|
||||
*
|
||||
* Pulled out into a separate method so that VariableDeclarators and
|
||||
* AssignmentExpressions can share the same verification logic.
|
||||
* @param {ASTNode} leftNode the left-hand side of the assignment
|
||||
* @param {ASTNode} rightNode the right-hand side of the assignment
|
||||
* @param {ASTNode} reportNode the node to report the error on
|
||||
* @returns {void}
|
||||
*/
|
||||
function performCheck(leftNode, rightNode, reportNode) {
|
||||
if (
|
||||
rightNode.type !== "MemberExpression" ||
|
||||
rightNode.object.type === "Super" ||
|
||||
rightNode.property.type === "PrivateIdentifier"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (astUtils.getPrecedence(rightNode.object) < PRECEDENCE_OF_ASSIGNMENT_EXPR) {
|
||||
objectText = `(${objectText})`;
|
||||
}
|
||||
|
||||
if (isArrayIndexAccess(rightNode)) {
|
||||
if (shouldCheck(reportNode.type, "array")) {
|
||||
report(reportNode, "array", null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return fixer.replaceText(
|
||||
node,
|
||||
`{${rightNode.property.name}} = ${objectText}`
|
||||
);
|
||||
}
|
||||
|
||||
const fix = shouldFix(reportNode)
|
||||
? fixer => fixIntoObjectDestructuring(fixer, reportNode)
|
||||
: null;
|
||||
/**
|
||||
* Check that the `prefer-destructuring` rules are followed based on the
|
||||
* given left- and right-hand side of the assignment.
|
||||
*
|
||||
* Pulled out into a separate method so that VariableDeclarators and
|
||||
* AssignmentExpressions can share the same verification logic.
|
||||
* @param {ASTNode} leftNode the left-hand side of the assignment
|
||||
* @param {ASTNode} rightNode the right-hand side of the assignment
|
||||
* @param {ASTNode} reportNode the node to report the error on
|
||||
* @returns {void}
|
||||
*/
|
||||
function performCheck(leftNode, rightNode, reportNode) {
|
||||
if (
|
||||
rightNode.type !== "MemberExpression" ||
|
||||
rightNode.object.type === "Super" ||
|
||||
rightNode.property.type === "PrivateIdentifier"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
shouldCheck(reportNode.type, "object") &&
|
||||
enforceForRenamedProperties
|
||||
) {
|
||||
report(reportNode, "object", fix);
|
||||
return;
|
||||
}
|
||||
if (isArrayIndexAccess(rightNode)) {
|
||||
if (shouldCheck(reportNode.type, "array")) {
|
||||
report(reportNode, "array", null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldCheck(reportNode.type, "object")) {
|
||||
const property = rightNode.property;
|
||||
const fix = shouldFix(reportNode)
|
||||
? fixer => fixIntoObjectDestructuring(fixer, reportNode)
|
||||
: null;
|
||||
|
||||
if (
|
||||
(property.type === "Literal" &&
|
||||
leftNode.name === property.value) ||
|
||||
(property.type === "Identifier" &&
|
||||
leftNode.name === property.name &&
|
||||
!rightNode.computed)
|
||||
) {
|
||||
report(reportNode, "object", fix);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldCheck(reportNode.type, "object") && enforceForRenamedProperties) {
|
||||
report(reportNode, "object", fix);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given variable declarator is coming from an property access
|
||||
* that should be using destructuring instead
|
||||
* @param {ASTNode} node the variable declarator to check
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkVariableDeclarator(node) {
|
||||
// Skip if variable is declared without assignment
|
||||
if (!node.init) {
|
||||
return;
|
||||
}
|
||||
if (shouldCheck(reportNode.type, "object")) {
|
||||
const property = rightNode.property;
|
||||
|
||||
// Variable declarations using explicit resource management cannot use destructuring (parse error)
|
||||
if (
|
||||
node.parent.kind === "using" ||
|
||||
node.parent.kind === "await using"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
(property.type === "Literal" && leftNode.name === property.value) ||
|
||||
(property.type === "Identifier" && leftNode.name === property.name && !rightNode.computed)
|
||||
) {
|
||||
report(reportNode, "object", fix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We only care about member expressions past this point
|
||||
if (node.init.type !== "MemberExpression") {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Check if a given variable declarator is coming from an property access
|
||||
* that should be using destructuring instead
|
||||
* @param {ASTNode} node the variable declarator to check
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkVariableDeclarator(node) {
|
||||
|
||||
performCheck(node.id, node.init, node);
|
||||
}
|
||||
// Skip if variable is declared without assignment
|
||||
if (!node.init) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the `prefer-destructuring` check on an AssignmentExpression
|
||||
* @param {ASTNode} node the AssignmentExpression node
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkAssignmentExpression(node) {
|
||||
if (node.operator === "=") {
|
||||
performCheck(node.left, node.right, node);
|
||||
}
|
||||
}
|
||||
// We only care about member expressions past this point
|
||||
if (node.init.type !== "MemberExpression") {
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
performCheck(node.id, node.init, node);
|
||||
}
|
||||
|
||||
return {
|
||||
VariableDeclarator: checkVariableDeclarator,
|
||||
AssignmentExpression: checkAssignmentExpression,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Run the `prefer-destructuring` check on an AssignmentExpression
|
||||
* @param {ASTNode} node the AssignmentExpression node
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkAssignmentExpression(node) {
|
||||
if (node.operator === "=") {
|
||||
performCheck(node.left, node.right, node);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
return {
|
||||
VariableDeclarator: checkVariableDeclarator,
|
||||
AssignmentExpression: checkAssignmentExpression
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user