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:
+219
-219
@@ -10,14 +10,13 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const Traverser = require("../shared/traverser"),
|
||||
astUtils = require("./utils/ast-utils");
|
||||
astUtils = require("./utils/ast-utils");
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const SENTINEL_PATTERN =
|
||||
/(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/u;
|
||||
const SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/u;
|
||||
const LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/u; // for-in/of statements don't have `test` property.
|
||||
const GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/u;
|
||||
const SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/u;
|
||||
@@ -40,14 +39,14 @@ const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/u;
|
||||
* @returns {boolean} `true` if the reference is a write reference.
|
||||
*/
|
||||
function isWriteReference(reference) {
|
||||
if (reference.init) {
|
||||
const def = reference.resolved && reference.resolved.defs[0];
|
||||
if (reference.init) {
|
||||
const def = reference.resolved && reference.resolved.defs[0];
|
||||
|
||||
if (!def || def.type !== "Variable" || def.parent.kind !== "var") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return reference.isWrite();
|
||||
if (!def || def.type !== "Variable" || def.parent.kind !== "var") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return reference.isWrite();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +56,7 @@ function isWriteReference(reference) {
|
||||
* @returns {boolean} `true` if the loop condition info is "unmodified".
|
||||
*/
|
||||
function isUnmodified(condition) {
|
||||
return !condition.modified;
|
||||
return !condition.modified;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,7 +66,7 @@ function isUnmodified(condition) {
|
||||
* @returns {boolean} `true` if the loop condition info is "unmodified".
|
||||
*/
|
||||
function isUnmodifiedAndNotBelongToGroup(condition) {
|
||||
return !(condition.modified || condition.group);
|
||||
return !(condition.modified || condition.group);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,10 +76,10 @@ function isUnmodifiedAndNotBelongToGroup(condition) {
|
||||
* @returns {boolean} `true` if the reference is inside of the node.
|
||||
*/
|
||||
function isInRange(node, reference) {
|
||||
const or = node.range;
|
||||
const ir = reference.identifier.range;
|
||||
const or = node.range;
|
||||
const ir = reference.identifier.range;
|
||||
|
||||
return or[0] <= ir[0] && ir[1] <= or[1];
|
||||
return or[0] <= ir[0] && ir[1] <= or[1];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,14 +90,14 @@ function isInRange(node, reference) {
|
||||
* condition.
|
||||
*/
|
||||
const isInLoop = {
|
||||
WhileStatement: isInRange,
|
||||
DoWhileStatement: isInRange,
|
||||
ForStatement(node, reference) {
|
||||
return (
|
||||
isInRange(node, reference) &&
|
||||
!(node.init && isInRange(node.init, reference))
|
||||
);
|
||||
},
|
||||
WhileStatement: isInRange,
|
||||
DoWhileStatement: isInRange,
|
||||
ForStatement(node, reference) {
|
||||
return (
|
||||
isInRange(node, reference) &&
|
||||
!(node.init && isInRange(node.init, reference))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -108,17 +107,17 @@ const isInLoop = {
|
||||
* @returns {ASTNode|null} The function node or null.
|
||||
*/
|
||||
function getEncloseFunctionDeclaration(reference) {
|
||||
let node = reference.identifier;
|
||||
let node = reference.identifier;
|
||||
|
||||
while (node) {
|
||||
if (node.type === "FunctionDeclaration") {
|
||||
return node.id ? node : null;
|
||||
}
|
||||
while (node) {
|
||||
if (node.type === "FunctionDeclaration") {
|
||||
return node.id ? node : null;
|
||||
}
|
||||
|
||||
node = node.parent;
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,233 +127,234 @@ function getEncloseFunctionDeclaration(reference) {
|
||||
* @returns {void}
|
||||
*/
|
||||
function updateModifiedFlag(conditions, modifiers) {
|
||||
for (let i = 0; i < conditions.length; ++i) {
|
||||
const condition = conditions[i];
|
||||
|
||||
for (let j = 0; !condition.modified && j < modifiers.length; ++j) {
|
||||
const modifier = modifiers[j];
|
||||
let funcNode, funcVar;
|
||||
for (let i = 0; i < conditions.length; ++i) {
|
||||
const condition = conditions[i];
|
||||
|
||||
/*
|
||||
* Besides checking for the condition being in the loop, we want to
|
||||
* check the function that this modifier is belonging to is called
|
||||
* in the loop.
|
||||
* FIXME: This should probably be extracted to a function.
|
||||
*/
|
||||
const inLoop =
|
||||
condition.isInLoop(modifier) ||
|
||||
Boolean(
|
||||
(funcNode = getEncloseFunctionDeclaration(modifier)) &&
|
||||
(funcVar = astUtils.getVariableByName(
|
||||
modifier.from.upper,
|
||||
funcNode.id.name,
|
||||
)) &&
|
||||
funcVar.references.some(condition.isInLoop),
|
||||
);
|
||||
for (let j = 0; !condition.modified && j < modifiers.length; ++j) {
|
||||
const modifier = modifiers[j];
|
||||
let funcNode, funcVar;
|
||||
|
||||
condition.modified = inLoop;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Besides checking for the condition being in the loop, we want to
|
||||
* check the function that this modifier is belonging to is called
|
||||
* in the loop.
|
||||
* FIXME: This should probably be extracted to a function.
|
||||
*/
|
||||
const inLoop = condition.isInLoop(modifier) || Boolean(
|
||||
(funcNode = getEncloseFunctionDeclaration(modifier)) &&
|
||||
(funcVar = astUtils.getVariableByName(modifier.from.upper, funcNode.id.name)) &&
|
||||
funcVar.references.some(condition.isInLoop)
|
||||
);
|
||||
|
||||
condition.modified = inLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: "problem",
|
||||
meta: {
|
||||
type: "problem",
|
||||
|
||||
docs: {
|
||||
description: "Disallow unmodified loop conditions",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-unmodified-loop-condition",
|
||||
},
|
||||
docs: {
|
||||
description: "Disallow unmodified loop conditions",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/no-unmodified-loop-condition"
|
||||
},
|
||||
|
||||
schema: [],
|
||||
schema: [],
|
||||
|
||||
messages: {
|
||||
loopConditionNotModified:
|
||||
"'{{name}}' is not modified in this loop.",
|
||||
},
|
||||
},
|
||||
messages: {
|
||||
loopConditionNotModified: "'{{name}}' is not modified in this loop."
|
||||
}
|
||||
},
|
||||
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
let groupMap = null;
|
||||
create(context) {
|
||||
const sourceCode = context.sourceCode;
|
||||
let groupMap = null;
|
||||
|
||||
/**
|
||||
* Reports a given condition info.
|
||||
* @param {LoopConditionInfo} condition A loop condition info to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(condition) {
|
||||
const node = condition.reference.identifier;
|
||||
/**
|
||||
* Reports a given condition info.
|
||||
* @param {LoopConditionInfo} condition A loop condition info to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function report(condition) {
|
||||
const node = condition.reference.identifier;
|
||||
|
||||
context.report({
|
||||
node,
|
||||
messageId: "loopConditionNotModified",
|
||||
data: node,
|
||||
});
|
||||
}
|
||||
context.report({
|
||||
node,
|
||||
messageId: "loopConditionNotModified",
|
||||
data: node
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers given conditions to the group the condition belongs to.
|
||||
* @param {LoopConditionInfo[]} conditions A loop condition info to
|
||||
* register.
|
||||
* @returns {void}
|
||||
*/
|
||||
function registerConditionsToGroup(conditions) {
|
||||
for (let i = 0; i < conditions.length; ++i) {
|
||||
const condition = conditions[i];
|
||||
/**
|
||||
* Registers given conditions to the group the condition belongs to.
|
||||
* @param {LoopConditionInfo[]} conditions A loop condition info to
|
||||
* register.
|
||||
* @returns {void}
|
||||
*/
|
||||
function registerConditionsToGroup(conditions) {
|
||||
for (let i = 0; i < conditions.length; ++i) {
|
||||
const condition = conditions[i];
|
||||
|
||||
if (condition.group) {
|
||||
let group = groupMap.get(condition.group);
|
||||
if (condition.group) {
|
||||
let group = groupMap.get(condition.group);
|
||||
|
||||
if (!group) {
|
||||
group = [];
|
||||
groupMap.set(condition.group, group);
|
||||
}
|
||||
group.push(condition);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!group) {
|
||||
group = [];
|
||||
groupMap.set(condition.group, group);
|
||||
}
|
||||
group.push(condition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports references which are inside of unmodified groups.
|
||||
* @param {LoopConditionInfo[]} conditions A loop condition info to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkConditionsInGroup(conditions) {
|
||||
if (conditions.every(isUnmodified)) {
|
||||
conditions.forEach(report);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Reports references which are inside of unmodified groups.
|
||||
* @param {LoopConditionInfo[]} conditions A loop condition info to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkConditionsInGroup(conditions) {
|
||||
if (conditions.every(isUnmodified)) {
|
||||
conditions.forEach(report);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not a given group node has any dynamic elements.
|
||||
* @param {ASTNode} root A node to check.
|
||||
* This node is one of BinaryExpression or ConditionalExpression.
|
||||
* @returns {boolean} `true` if the node is dynamic.
|
||||
*/
|
||||
function hasDynamicExpressions(root) {
|
||||
let retv = false;
|
||||
/**
|
||||
* Checks whether or not a given group node has any dynamic elements.
|
||||
* @param {ASTNode} root A node to check.
|
||||
* This node is one of BinaryExpression or ConditionalExpression.
|
||||
* @returns {boolean} `true` if the node is dynamic.
|
||||
*/
|
||||
function hasDynamicExpressions(root) {
|
||||
let retv = false;
|
||||
|
||||
Traverser.traverse(root, {
|
||||
visitorKeys: sourceCode.visitorKeys,
|
||||
enter(node) {
|
||||
if (DYNAMIC_PATTERN.test(node.type)) {
|
||||
retv = true;
|
||||
this.break();
|
||||
} else if (SKIP_PATTERN.test(node.type)) {
|
||||
this.skip();
|
||||
}
|
||||
},
|
||||
});
|
||||
Traverser.traverse(root, {
|
||||
visitorKeys: sourceCode.visitorKeys,
|
||||
enter(node) {
|
||||
if (DYNAMIC_PATTERN.test(node.type)) {
|
||||
retv = true;
|
||||
this.break();
|
||||
} else if (SKIP_PATTERN.test(node.type)) {
|
||||
this.skip();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return retv;
|
||||
}
|
||||
return retv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the loop condition information from a given reference.
|
||||
* @param {eslint-scope.Reference} reference A reference to create.
|
||||
* @returns {LoopConditionInfo|null} Created loop condition info, or null.
|
||||
*/
|
||||
function toLoopCondition(reference) {
|
||||
if (reference.init) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Creates the loop condition information from a given reference.
|
||||
* @param {eslint-scope.Reference} reference A reference to create.
|
||||
* @returns {LoopConditionInfo|null} Created loop condition info, or null.
|
||||
*/
|
||||
function toLoopCondition(reference) {
|
||||
if (reference.init) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let group = null;
|
||||
let child = reference.identifier;
|
||||
let node = child.parent;
|
||||
let group = null;
|
||||
let child = reference.identifier;
|
||||
let node = child.parent;
|
||||
|
||||
while (node) {
|
||||
if (SENTINEL_PATTERN.test(node.type)) {
|
||||
if (LOOP_PATTERN.test(node.type) && node.test === child) {
|
||||
// This reference is inside of a loop condition.
|
||||
return {
|
||||
reference,
|
||||
group,
|
||||
isInLoop: isInLoop[node.type].bind(null, node),
|
||||
modified: false,
|
||||
};
|
||||
}
|
||||
while (node) {
|
||||
if (SENTINEL_PATTERN.test(node.type)) {
|
||||
if (LOOP_PATTERN.test(node.type) && node.test === child) {
|
||||
|
||||
// This reference is outside of a loop condition.
|
||||
break;
|
||||
}
|
||||
// This reference is inside of a loop condition.
|
||||
return {
|
||||
reference,
|
||||
group,
|
||||
isInLoop: isInLoop[node.type].bind(null, node),
|
||||
modified: false
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's inside of a group, OK if either operand is modified.
|
||||
* So stores the group this reference belongs to.
|
||||
*/
|
||||
if (GROUP_PATTERN.test(node.type)) {
|
||||
// If this expression is dynamic, no need to check.
|
||||
if (hasDynamicExpressions(node)) {
|
||||
break;
|
||||
} else {
|
||||
group = node;
|
||||
}
|
||||
}
|
||||
// This reference is outside of a loop condition.
|
||||
break;
|
||||
}
|
||||
|
||||
child = node;
|
||||
node = node.parent;
|
||||
}
|
||||
/*
|
||||
* If it's inside of a group, OK if either operand is modified.
|
||||
* So stores the group this reference belongs to.
|
||||
*/
|
||||
if (GROUP_PATTERN.test(node.type)) {
|
||||
|
||||
return null;
|
||||
}
|
||||
// If this expression is dynamic, no need to check.
|
||||
if (hasDynamicExpressions(node)) {
|
||||
break;
|
||||
} else {
|
||||
group = node;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds unmodified references which are inside of a loop condition.
|
||||
* Then reports the references which are outside of groups.
|
||||
* @param {eslint-scope.Variable} variable A variable to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkReferences(variable) {
|
||||
// Gets references that exist in loop conditions.
|
||||
const conditions = variable.references
|
||||
.map(toLoopCondition)
|
||||
.filter(Boolean);
|
||||
child = node;
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (conditions.length === 0) {
|
||||
return;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Registers the conditions to belonging groups.
|
||||
registerConditionsToGroup(conditions);
|
||||
/**
|
||||
* Finds unmodified references which are inside of a loop condition.
|
||||
* Then reports the references which are outside of groups.
|
||||
* @param {eslint-scope.Variable} variable A variable to report.
|
||||
* @returns {void}
|
||||
*/
|
||||
function checkReferences(variable) {
|
||||
|
||||
// Check the conditions are modified.
|
||||
const modifiers = variable.references.filter(isWriteReference);
|
||||
// Gets references that exist in loop conditions.
|
||||
const conditions = variable
|
||||
.references
|
||||
.map(toLoopCondition)
|
||||
.filter(Boolean);
|
||||
|
||||
if (modifiers.length > 0) {
|
||||
updateModifiedFlag(conditions, modifiers);
|
||||
}
|
||||
if (conditions.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reports the conditions which are not belonging to groups.
|
||||
* Others will be reported after all variables are done.
|
||||
*/
|
||||
conditions.filter(isUnmodifiedAndNotBelongToGroup).forEach(report);
|
||||
}
|
||||
// Registers the conditions to belonging groups.
|
||||
registerConditionsToGroup(conditions);
|
||||
|
||||
return {
|
||||
"Program:exit"(node) {
|
||||
const queue = [sourceCode.getScope(node)];
|
||||
// Check the conditions are modified.
|
||||
const modifiers = variable.references.filter(isWriteReference);
|
||||
|
||||
groupMap = new Map();
|
||||
if (modifiers.length > 0) {
|
||||
updateModifiedFlag(conditions, modifiers);
|
||||
}
|
||||
|
||||
let scope;
|
||||
/*
|
||||
* Reports the conditions which are not belonging to groups.
|
||||
* Others will be reported after all variables are done.
|
||||
*/
|
||||
conditions
|
||||
.filter(isUnmodifiedAndNotBelongToGroup)
|
||||
.forEach(report);
|
||||
}
|
||||
|
||||
while ((scope = queue.pop())) {
|
||||
queue.push(...scope.childScopes);
|
||||
scope.variables.forEach(checkReferences);
|
||||
}
|
||||
return {
|
||||
"Program:exit"(node) {
|
||||
const queue = [sourceCode.getScope(node)];
|
||||
|
||||
groupMap.forEach(checkConditionsInGroup);
|
||||
groupMap = null;
|
||||
},
|
||||
};
|
||||
},
|
||||
groupMap = new Map();
|
||||
|
||||
let scope;
|
||||
|
||||
while ((scope = queue.pop())) {
|
||||
queue.push(...scope.childScopes);
|
||||
scope.variables.forEach(checkReferences);
|
||||
}
|
||||
|
||||
groupMap.forEach(checkConditionsInGroup);
|
||||
groupMap = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user