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.
160 lines
5.5 KiB
JavaScript
160 lines
5.5 KiB
JavaScript
/**
|
|
* @fileoverview Rule to flag assignment in a conditional statement's test expression
|
|
* @author Stephen Murray <spmurrayzzz>
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Requirements
|
|
//------------------------------------------------------------------------------
|
|
|
|
const astUtils = require("./utils/ast-utils");
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Helpers
|
|
//------------------------------------------------------------------------------
|
|
|
|
const TEST_CONDITION_PARENT_TYPES = new Set(["IfStatement", "WhileStatement", "DoWhileStatement", "ForStatement", "ConditionalExpression"]);
|
|
|
|
const NODE_DESCRIPTIONS = {
|
|
DoWhileStatement: "a 'do...while' statement",
|
|
ForStatement: "a 'for' statement",
|
|
IfStatement: "an 'if' statement",
|
|
WhileStatement: "a 'while' statement"
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//------------------------------------------------------------------------------
|
|
|
|
/** @type {import('../shared/types').Rule} */
|
|
module.exports = {
|
|
meta: {
|
|
type: "problem",
|
|
|
|
docs: {
|
|
description: "Disallow assignment operators in conditional expressions",
|
|
recommended: true,
|
|
url: "https://eslint.org/docs/latest/rules/no-cond-assign"
|
|
},
|
|
|
|
schema: [
|
|
{
|
|
enum: ["except-parens", "always"]
|
|
}
|
|
],
|
|
|
|
messages: {
|
|
unexpected: "Unexpected assignment within {{type}}.",
|
|
|
|
// must match JSHint's error message
|
|
missing: "Expected a conditional expression and instead saw an assignment."
|
|
}
|
|
},
|
|
|
|
create(context) {
|
|
|
|
const prohibitAssign = (context.options[0] || "except-parens");
|
|
|
|
const sourceCode = context.sourceCode;
|
|
|
|
/**
|
|
* Check whether an AST node is the test expression for a conditional statement.
|
|
* @param {!Object} node The node to test.
|
|
* @returns {boolean} `true` if the node is the text expression for a conditional statement; otherwise, `false`.
|
|
*/
|
|
function isConditionalTestExpression(node) {
|
|
return node.parent &&
|
|
TEST_CONDITION_PARENT_TYPES.has(node.parent.type) &&
|
|
node === node.parent.test;
|
|
}
|
|
|
|
/**
|
|
* Given an AST node, perform a bottom-up search for the first ancestor that represents a conditional statement.
|
|
* @param {!Object} node The node to use at the start of the search.
|
|
* @returns {?Object} The closest ancestor node that represents a conditional statement.
|
|
*/
|
|
function findConditionalAncestor(node) {
|
|
let currentAncestor = node;
|
|
|
|
do {
|
|
if (isConditionalTestExpression(currentAncestor)) {
|
|
return currentAncestor.parent;
|
|
}
|
|
} while ((currentAncestor = currentAncestor.parent) && !astUtils.isFunction(currentAncestor));
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Check whether the code represented by an AST node is enclosed in two sets of parentheses.
|
|
* @param {!Object} node The node to test.
|
|
* @returns {boolean} `true` if the code is enclosed in two sets of parentheses; otherwise, `false`.
|
|
*/
|
|
function isParenthesisedTwice(node) {
|
|
const previousToken = sourceCode.getTokenBefore(node, 1),
|
|
nextToken = sourceCode.getTokenAfter(node, 1);
|
|
|
|
return astUtils.isParenthesised(sourceCode, node) &&
|
|
previousToken && astUtils.isOpeningParenToken(previousToken) && previousToken.range[1] <= node.range[0] &&
|
|
astUtils.isClosingParenToken(nextToken) && nextToken.range[0] >= node.range[1];
|
|
}
|
|
|
|
/**
|
|
* Check a conditional statement's test expression for top-level assignments that are not enclosed in parentheses.
|
|
* @param {!Object} node The node for the conditional statement.
|
|
* @returns {void}
|
|
*/
|
|
function testForAssign(node) {
|
|
if (node.test &&
|
|
(node.test.type === "AssignmentExpression") &&
|
|
(node.type === "ForStatement"
|
|
? !astUtils.isParenthesised(sourceCode, node.test)
|
|
: !isParenthesisedTwice(node.test)
|
|
)
|
|
) {
|
|
|
|
context.report({
|
|
node: node.test,
|
|
messageId: "missing"
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check whether an assignment expression is descended from a conditional statement's test expression.
|
|
* @param {!Object} node The node for the assignment expression.
|
|
* @returns {void}
|
|
*/
|
|
function testForConditionalAncestor(node) {
|
|
const ancestor = findConditionalAncestor(node);
|
|
|
|
if (ancestor) {
|
|
context.report({
|
|
node,
|
|
messageId: "unexpected",
|
|
data: {
|
|
type: NODE_DESCRIPTIONS[ancestor.type] || ancestor.type
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if (prohibitAssign === "always") {
|
|
return {
|
|
AssignmentExpression: testForConditionalAncestor
|
|
};
|
|
}
|
|
|
|
return {
|
|
DoWhileStatement: testForAssign,
|
|
ForStatement: testForAssign,
|
|
IfStatement: testForAssign,
|
|
WhileStatement: testForAssign,
|
|
ConditionalExpression: testForAssign
|
|
};
|
|
|
|
}
|
|
};
|