tools: update ESLint custom rules to not use the deprecated format

Refs: https://eslint.org/docs/latest/extend/custom-rules-deprecated
PR-URL: https://github.com/nodejs/node/pull/46460
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Antoine du Hamel
2023-02-03 10:55:29 +01:00
committed by GitHub
parent 9fafb0a090
commit 75dca44c60
5 changed files with 211 additions and 210 deletions

View File

@@ -14,46 +14,45 @@ const astSelector = 'NewExpression[callee.property.name="TypeError"]' +
const primitives = [ 'number', 'string', 'boolean', 'null', 'undefined' ];
module.exports = function(context) {
function checkNamesArgument(node) {
const names = node.arguments[2];
module.exports = {
meta: { fixable: 'code' },
create(context) {
function checkNamesArgument(node) {
const names = node.arguments[2];
switch (names.type) {
case 'Literal':
checkName(names);
break;
case 'ArrayExpression':
names.elements.forEach((name) => {
checkName(name);
switch (names.type) {
case 'Literal':
checkName(names);
break;
case 'ArrayExpression':
names.elements.forEach((name) => {
checkName(name);
});
break;
}
}
function checkName(node) {
const name = node.value;
const lowercaseName = name.toLowerCase();
if (name !== lowercaseName && primitives.includes(lowercaseName)) {
const msg = `primitive should use lowercase: ${name}`;
context.report({
node,
message: msg,
fix: (fixer) => {
return fixer.replaceText(
node,
`'${lowercaseName}'`,
);
},
});
break;
}
}
}
function checkName(node) {
const name = node.value;
const lowercaseName = name.toLowerCase();
if (name !== lowercaseName && primitives.includes(lowercaseName)) {
const msg = `primitive should use lowercase: ${name}`;
context.report({
node,
message: msg,
fix: (fixer) => {
return fixer.replaceText(
node,
`'${lowercaseName}'`,
);
},
});
}
}
return {
[astSelector]: (node) => checkNamesArgument(node),
};
};
module.exports.meta = {
fixable: 'code',
return {
[astSelector]: (node) => checkNamesArgument(node),
};
},
};

View File

@@ -19,30 +19,29 @@ const preferredAssertMethod = {
'!=': 'notEqual',
};
module.exports = function(context) {
return {
[astSelector]: function(node) {
const arg = node.expression.arguments[0];
const assertMethod = preferredAssertMethod[arg.operator];
if (assertMethod) {
context.report({
node,
message: parseError(assertMethod, arg.operator),
fix: (fixer) => {
const sourceCode = context.getSourceCode();
const left = sourceCode.getText(arg.left);
const right = sourceCode.getText(arg.right);
return fixer.replaceText(
node,
`assert.${assertMethod}(${left}, ${right});`,
);
},
});
}
},
};
};
module.exports.meta = {
fixable: 'code',
module.exports = {
meta: { fixable: 'code' },
create(context) {
return {
[astSelector]: function(node) {
const arg = node.expression.arguments[0];
const assertMethod = preferredAssertMethod[arg.operator];
if (assertMethod) {
context.report({
node,
message: parseError(assertMethod, arg.operator),
fix: (fixer) => {
const sourceCode = context.getSourceCode();
const left = sourceCode.getText(arg.left);
const right = sourceCode.getText(arg.right);
return fixer.replaceText(
node,
`assert.${assertMethod}(${left}, ${right});`,
);
},
});
}
},
};
},
};

View File

@@ -15,16 +15,18 @@ const mustCallSelector = 'CallExpression[callee.object.name="common"]' +
const arg0Selector = `${mustCallSelector}[arguments.0.value=0]`;
const arg1Selector = `${mustCallSelector}[arguments.1.value=0]`;
module.exports = function(context) {
function report(node) {
context.report(node, msg);
}
module.exports = {
create(context) {
function report(node) {
context.report(node, msg);
}
return {
return {
// Catch common.mustCall(0)
[arg0Selector]: report,
[arg0Selector]: report,
// Catch common.mustCall(fn, 0)
[arg1Selector]: report,
};
// Catch common.mustCall(fn, 0)
[arg1Selector]: report,
};
},
};

View File

@@ -10,72 +10,74 @@ const { isRequireCall, isString } = require('./rules-utils.js');
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
const requiredModule = 'common';
const isESM = context.parserOptions.sourceType === 'module';
const foundModules = [];
module.exports = {
create(context) {
const requiredModule = 'common';
const isESM = context.parserOptions.sourceType === 'module';
const foundModules = [];
/**
* Function to check if the path is a module and return its name.
* @param {string} str The path to check
* @returns {string} module name
*/
function getModuleName(str) {
if (str === '../common/index.mjs') {
return 'common';
/**
* Function to check if the path is a module and return its name.
* @param {string} str The path to check
* @returns {string} module name
*/
function getModuleName(str) {
if (str === '../common/index.mjs') {
return 'common';
}
return path.basename(str);
}
return path.basename(str);
}
/**
* Function to check if a node has an argument that is a module and
* return its name.
* @param {ASTNode} node The node to check
* @returns {undefined | string} module name or undefined
*/
function getModuleNameFromCall(node) {
/**
* Function to check if a node has an argument that is a module and
* return its name.
* @param {ASTNode} node The node to check
* @returns {undefined | string} module name or undefined
*/
function getModuleNameFromCall(node) {
// Node has arguments and first argument is string
if (node.arguments.length && isString(node.arguments[0])) {
return getModuleName(node.arguments[0].value.trim());
if (node.arguments.length && isString(node.arguments[0])) {
return getModuleName(node.arguments[0].value.trim());
}
return undefined;
}
return undefined;
}
const rules = {
'Program:exit'(node) {
const rules = {
'Program:exit'(node) {
// The common module should be loaded in the first place.
const notLoadedFirst = foundModules.indexOf(requiredModule) !== 0;
if (notLoadedFirst) {
context.report(
node,
'Mandatory module "{{moduleName}}" must be loaded ' +
const notLoadedFirst = foundModules.indexOf(requiredModule) !== 0;
if (notLoadedFirst) {
context.report(
node,
'Mandatory module "{{moduleName}}" must be loaded ' +
'before any other modules.',
{ moduleName: requiredModule },
);
}
},
};
if (isESM) {
rules.ImportDeclaration = (node) => {
const moduleName = getModuleName(node.source.value);
if (moduleName) {
foundModules.push(moduleName);
}
{ moduleName: requiredModule },
);
}
},
};
} else {
rules.CallExpression = (node) => {
if (isRequireCall(node)) {
const moduleName = getModuleNameFromCall(node);
if (isESM) {
rules.ImportDeclaration = (node) => {
const moduleName = getModuleName(node.source.value);
if (moduleName) {
foundModules.push(moduleName);
}
}
};
}
};
} else {
rules.CallExpression = (node) => {
if (isRequireCall(node)) {
const moduleName = getModuleNameFromCall(node);
return rules;
if (moduleName) {
foundModules.push(moduleName);
}
}
};
}
return rules;
},
};

View File

@@ -10,92 +10,91 @@ const { isRequireCall, isString } = require('./rules-utils.js');
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
// Trim required module names
const options = context.options[0];
const requiredModules = options ? Object.keys(options).map((x) => {
return [ x, new RegExp(options[x]) ];
}) : [];
const isESM = context.parserOptions.sourceType === 'module';
const foundModules = [];
// If no modules are required we don't need to check the CallExpressions
if (requiredModules.length === 0) {
return {};
}
/**
* Function to check if the path is a required module and return its name.
* @param {string} str The path to check
* @returns {undefined | string} required module name or undefined
*/
function getRequiredModuleName(str) {
const match = requiredModules.find(([, test]) => {
return test.test(str);
});
return match ? match[0] : undefined;
}
/**
* Function to check if a node has an argument that is a required module and
* return its name.
* @param {ASTNode} node The node to check
* @returns {undefined | string} required module name or undefined
*/
function getRequiredModuleNameFromCall(node) {
// Node has arguments and first argument is string
if (node.arguments.length && isString(node.arguments[0])) {
return getRequiredModuleName(node.arguments[0].value.trim());
}
return undefined;
}
const rules = {
'Program:exit'(node) {
if (foundModules.length < requiredModules.length) {
const missingModules = requiredModules.filter(
([module]) => foundModules.indexOf(module) === -1,
);
missingModules.forEach(([moduleName]) => {
context.report(
node,
'Mandatory module "{{moduleName}}" must be loaded.',
{ moduleName: moduleName },
);
});
}
},
};
if (isESM) {
rules.ImportDeclaration = (node) => {
const requiredModuleName = getRequiredModuleName(node.source.value);
if (requiredModuleName) {
foundModules.push(requiredModuleName);
}
};
} else {
rules.CallExpression = (node) => {
if (isRequireCall(node)) {
const requiredModuleName = getRequiredModuleNameFromCall(node);
if (requiredModuleName) {
foundModules.push(requiredModuleName);
}
}
};
}
return rules;
};
module.exports.meta = {
schema: [{
module.exports = {
meta: { schema: [{
'type': 'object',
'additionalProperties': {
'type': 'string',
},
}],
}] },
create(context) {
// Trim required module names
const options = context.options[0];
const requiredModules = options ? Object.keys(options).map((x) => {
return [ x, new RegExp(options[x]) ];
}) : [];
const isESM = context.parserOptions.sourceType === 'module';
const foundModules = [];
// If no modules are required we don't need to check the CallExpressions
if (requiredModules.length === 0) {
return {};
}
/**
* Function to check if the path is a required module and return its name.
* @param {string} str The path to check
* @returns {undefined | string} required module name or undefined
*/
function getRequiredModuleName(str) {
const match = requiredModules.find(([, test]) => {
return test.test(str);
});
return match ? match[0] : undefined;
}
/**
* Function to check if a node has an argument that is a required module and
* return its name.
* @param {ASTNode} node The node to check
* @returns {undefined | string} required module name or undefined
*/
function getRequiredModuleNameFromCall(node) {
// Node has arguments and first argument is string
if (node.arguments.length && isString(node.arguments[0])) {
return getRequiredModuleName(node.arguments[0].value.trim());
}
return undefined;
}
const rules = {
'Program:exit'(node) {
if (foundModules.length < requiredModules.length) {
const missingModules = requiredModules.filter(
([module]) => foundModules.indexOf(module) === -1,
);
missingModules.forEach(([moduleName]) => {
context.report(
node,
'Mandatory module "{{moduleName}}" must be loaded.',
{ moduleName: moduleName },
);
});
}
},
};
if (isESM) {
rules.ImportDeclaration = (node) => {
const requiredModuleName = getRequiredModuleName(node.source.value);
if (requiredModuleName) {
foundModules.push(requiredModuleName);
}
};
} else {
rules.CallExpression = (node) => {
if (isRequireCall(node)) {
const requiredModuleName = getRequiredModuleNameFromCall(node);
if (requiredModuleName) {
foundModules.push(requiredModuleName);
}
}
};
}
return rules;
},
};