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:
+150
-213
@@ -15,236 +15,173 @@ const astUtils = require("./utils/ast-utils");
|
||||
// Rule Definition
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** @type {import('../types').Rule.RuleModule} */
|
||||
/** @type {import('../shared/types').Rule} */
|
||||
module.exports = {
|
||||
meta: {
|
||||
dialects: ["javascript", "typescript"],
|
||||
language: "javascript",
|
||||
type: "suggestion",
|
||||
meta: {
|
||||
type: "suggestion",
|
||||
|
||||
defaultOptions: [
|
||||
{
|
||||
enforceForClassFields: true,
|
||||
exceptMethods: [],
|
||||
ignoreOverrideMethods: false,
|
||||
},
|
||||
],
|
||||
docs: {
|
||||
description: "Enforce that class methods utilize `this`",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/class-methods-use-this"
|
||||
},
|
||||
|
||||
docs: {
|
||||
description: "Enforce that class methods utilize `this`",
|
||||
recommended: false,
|
||||
url: "https://eslint.org/docs/latest/rules/class-methods-use-this",
|
||||
},
|
||||
schema: [{
|
||||
type: "object",
|
||||
properties: {
|
||||
exceptMethods: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string"
|
||||
}
|
||||
},
|
||||
enforceForClassFields: {
|
||||
type: "boolean",
|
||||
default: true
|
||||
}
|
||||
},
|
||||
additionalProperties: false
|
||||
}],
|
||||
|
||||
schema: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
exceptMethods: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
enforceForClassFields: {
|
||||
type: "boolean",
|
||||
},
|
||||
ignoreOverrideMethods: {
|
||||
type: "boolean",
|
||||
},
|
||||
ignoreClassesWithImplements: {
|
||||
enum: ["all", "public-fields"],
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
messages: {
|
||||
missingThis: "Expected 'this' to be used by class {{name}}."
|
||||
}
|
||||
},
|
||||
create(context) {
|
||||
const config = Object.assign({}, context.options[0]);
|
||||
const enforceForClassFields = config.enforceForClassFields !== false;
|
||||
const exceptMethods = new Set(config.exceptMethods || []);
|
||||
|
||||
messages: {
|
||||
missingThis: "Expected 'this' to be used by class {{name}}.",
|
||||
},
|
||||
},
|
||||
create(context) {
|
||||
const [options] = context.options;
|
||||
const {
|
||||
enforceForClassFields,
|
||||
ignoreOverrideMethods,
|
||||
ignoreClassesWithImplements,
|
||||
} = options;
|
||||
const exceptMethods = new Set(options.exceptMethods);
|
||||
const stack = [];
|
||||
|
||||
const stack = [];
|
||||
/**
|
||||
* Push `this` used flag initialized with `false` onto the stack.
|
||||
* @returns {void}
|
||||
*/
|
||||
function pushContext() {
|
||||
stack.push(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push `this` used flag initialized with `false` onto the stack.
|
||||
* @returns {void}
|
||||
*/
|
||||
function pushContext() {
|
||||
stack.push(false);
|
||||
}
|
||||
/**
|
||||
* Pop `this` used flag from the stack.
|
||||
* @returns {boolean | undefined} `this` used flag
|
||||
*/
|
||||
function popContext() {
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop `this` used flag from the stack.
|
||||
* @returns {boolean | undefined} `this` used flag
|
||||
*/
|
||||
function popContext() {
|
||||
return stack.pop();
|
||||
}
|
||||
/**
|
||||
* Initializes the current context to false and pushes it onto the stack.
|
||||
* These booleans represent whether 'this' has been used in the context.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function enterFunction() {
|
||||
pushContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the current context to false and pushes it onto the stack.
|
||||
* These booleans represent whether 'this' has been used in the context.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function enterFunction() {
|
||||
pushContext();
|
||||
}
|
||||
/**
|
||||
* Check if the node is an instance method
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {boolean} True if its an instance method
|
||||
* @private
|
||||
*/
|
||||
function isInstanceMethod(node) {
|
||||
switch (node.type) {
|
||||
case "MethodDefinition":
|
||||
return !node.static && node.kind !== "constructor";
|
||||
case "PropertyDefinition":
|
||||
return !node.static && enforceForClassFields;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the node is an instance method
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {boolean} True if its an instance method
|
||||
* @private
|
||||
*/
|
||||
function isInstanceMethod(node) {
|
||||
switch (node.type) {
|
||||
case "MethodDefinition":
|
||||
return !node.static && node.kind !== "constructor";
|
||||
case "AccessorProperty":
|
||||
case "PropertyDefinition":
|
||||
return !node.static && enforceForClassFields;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Check if the node is an instance method not excluded by config
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {boolean} True if it is an instance method, and not excluded by config
|
||||
* @private
|
||||
*/
|
||||
function isIncludedInstanceMethod(node) {
|
||||
if (isInstanceMethod(node)) {
|
||||
if (node.computed) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the node's parent class implements any interfaces
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {boolean} True if parent class implements interfaces
|
||||
* @private
|
||||
*/
|
||||
function hasImplements(node) {
|
||||
const classNode = node.parent.parent;
|
||||
return (
|
||||
classNode?.type === "ClassDeclaration" &&
|
||||
classNode.implements?.length > 0
|
||||
);
|
||||
}
|
||||
const hashIfNeeded = node.key.type === "PrivateIdentifier" ? "#" : "";
|
||||
const name = node.key.type === "Literal"
|
||||
? astUtils.getStaticStringValue(node.key)
|
||||
: (node.key.name || "");
|
||||
|
||||
/**
|
||||
* Check if the node is an instance method not excluded by config
|
||||
* @param {ASTNode} node node to check
|
||||
* @returns {boolean} True if it is an instance method, and not excluded by config
|
||||
* @private
|
||||
*/
|
||||
function isIncludedInstanceMethod(node) {
|
||||
if (isInstanceMethod(node)) {
|
||||
if (node.computed) {
|
||||
return true;
|
||||
}
|
||||
return !exceptMethods.has(hashIfNeeded + name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ignoreOverrideMethods && node.override) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Checks if we are leaving a function that is a method, and reports if 'this' has not been used.
|
||||
* Static methods and the constructor are exempt.
|
||||
* Then pops the context off the stack.
|
||||
* @param {ASTNode} node A function node that was entered.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function exitFunction(node) {
|
||||
const methodUsesThis = popContext();
|
||||
|
||||
if (ignoreClassesWithImplements) {
|
||||
const implementsInterfaces = hasImplements(node);
|
||||
if (implementsInterfaces) {
|
||||
if (
|
||||
ignoreClassesWithImplements === "all" ||
|
||||
(ignoreClassesWithImplements === "public-fields" &&
|
||||
node.key.type !== "PrivateIdentifier" &&
|
||||
(!node.accessibility ||
|
||||
node.accessibility === "public"))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isIncludedInstanceMethod(node.parent) && !methodUsesThis) {
|
||||
context.report({
|
||||
node,
|
||||
loc: astUtils.getFunctionHeadLoc(node, context.sourceCode),
|
||||
messageId: "missingThis",
|
||||
data: {
|
||||
name: astUtils.getFunctionNameWithKind(node)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const hashIfNeeded =
|
||||
node.key.type === "PrivateIdentifier" ? "#" : "";
|
||||
const name =
|
||||
node.key.type === "Literal"
|
||||
? astUtils.getStaticStringValue(node.key)
|
||||
: node.key.name || "";
|
||||
/**
|
||||
* Mark the current context as having used 'this'.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function markThisUsed() {
|
||||
if (stack.length) {
|
||||
stack[stack.length - 1] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return !exceptMethods.has(hashIfNeeded + name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
FunctionDeclaration: enterFunction,
|
||||
"FunctionDeclaration:exit": exitFunction,
|
||||
FunctionExpression: enterFunction,
|
||||
"FunctionExpression:exit": exitFunction,
|
||||
|
||||
/**
|
||||
* Checks if we are leaving a function that is a method, and reports if 'this' has not been used.
|
||||
* Static methods and the constructor are exempt.
|
||||
* Then pops the context off the stack.
|
||||
* @param {ASTNode} node A function node that was entered.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function exitFunction(node) {
|
||||
const methodUsesThis = popContext();
|
||||
/*
|
||||
* Class field value are implicit functions.
|
||||
*/
|
||||
"PropertyDefinition > *.key:exit": pushContext,
|
||||
"PropertyDefinition:exit": popContext,
|
||||
|
||||
if (isIncludedInstanceMethod(node.parent) && !methodUsesThis) {
|
||||
context.report({
|
||||
node,
|
||||
loc: astUtils.getFunctionHeadLoc(node, context.sourceCode),
|
||||
messageId: "missingThis",
|
||||
data: {
|
||||
name: astUtils.getFunctionNameWithKind(node),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Class static blocks are implicit functions. They aren't required to use `this`,
|
||||
* but we have to push context so that it captures any use of `this` in the static block
|
||||
* separately from enclosing contexts, because static blocks have their own `this` and it
|
||||
* shouldn't count as used `this` in enclosing contexts.
|
||||
*/
|
||||
StaticBlock: pushContext,
|
||||
"StaticBlock:exit": popContext,
|
||||
|
||||
/**
|
||||
* Mark the current context as having used 'this'.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function markThisUsed() {
|
||||
if (stack.length) {
|
||||
stack[stack.length - 1] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
FunctionDeclaration: enterFunction,
|
||||
"FunctionDeclaration:exit": exitFunction,
|
||||
FunctionExpression: enterFunction,
|
||||
"FunctionExpression:exit": exitFunction,
|
||||
|
||||
/*
|
||||
* Class field value are implicit functions.
|
||||
*/
|
||||
"AccessorProperty > *.key:exit": pushContext,
|
||||
"AccessorProperty:exit": popContext,
|
||||
"PropertyDefinition > *.key:exit": pushContext,
|
||||
"PropertyDefinition:exit": popContext,
|
||||
|
||||
/*
|
||||
* Class static blocks are implicit functions. They aren't required to use `this`,
|
||||
* but we have to push context so that it captures any use of `this` in the static block
|
||||
* separately from enclosing contexts, because static blocks have their own `this` and it
|
||||
* shouldn't count as used `this` in enclosing contexts.
|
||||
*/
|
||||
StaticBlock: pushContext,
|
||||
"StaticBlock:exit": popContext,
|
||||
|
||||
ThisExpression: markThisUsed,
|
||||
Super: markThisUsed,
|
||||
...(enforceForClassFields && {
|
||||
"AccessorProperty > ArrowFunctionExpression.value":
|
||||
enterFunction,
|
||||
"AccessorProperty > ArrowFunctionExpression.value:exit":
|
||||
exitFunction,
|
||||
"PropertyDefinition > ArrowFunctionExpression.value":
|
||||
enterFunction,
|
||||
"PropertyDefinition > ArrowFunctionExpression.value:exit":
|
||||
exitFunction,
|
||||
}),
|
||||
};
|
||||
},
|
||||
ThisExpression: markThisUsed,
|
||||
Super: markThisUsed,
|
||||
...(
|
||||
enforceForClassFields && {
|
||||
"PropertyDefinition > ArrowFunctionExpression.value": enterFunction,
|
||||
"PropertyDefinition > ArrowFunctionExpression.value:exit": exitFunction
|
||||
}
|
||||
)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user