From 646a09478249d1dd4d9a4afc15d7b95f7dd75388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Thu, 9 May 2024 17:27:39 +0200 Subject: [PATCH] tools: prepare custom rules for ESLint v9 Refs: https://eslint.org/docs/latest/use/migrate-to-9.0.0 PR-URL: https://github.com/nodejs/node/pull/52889 Reviewed-By: Moshe Atlow Reviewed-By: Luigi Pinca Reviewed-By: Mohammed Keyvanzadeh Reviewed-By: Antoine du Hamel Reviewed-By: Yagiz Nizipli --- tools/eslint-rules/no-array-destructuring.js | 2 +- tools/eslint-rules/no-duplicate-requires.js | 64 +++++------ tools/eslint-rules/no-unescaped-regexp-dot.js | 2 +- tools/eslint-rules/non-ascii-character.js | 42 +++---- tools/eslint-rules/prefer-assert-iferror.js | 2 +- tools/eslint-rules/prefer-assert-methods.js | 2 +- .../eslint-rules/prefer-common-mustsucceed.js | 104 +++++++++--------- tools/eslint-rules/prefer-primordials.js | 24 +++- tools/eslint-rules/prefer-proto.js | 8 +- .../set-proto-to-null-in-object.js | 2 +- 10 files changed, 138 insertions(+), 114 deletions(-) diff --git a/tools/eslint-rules/no-array-destructuring.js b/tools/eslint-rules/no-array-destructuring.js index b65849aa95f925..d50a8fa11b755f 100644 --- a/tools/eslint-rules/no-array-destructuring.js +++ b/tools/eslint-rules/no-array-destructuring.js @@ -56,7 +56,7 @@ module.exports = { schema: [], }, create(context) { - const sourceCode = context.getSourceCode(); + const sourceCode = context.sourceCode; return { ArrayPattern(node) { diff --git a/tools/eslint-rules/no-duplicate-requires.js b/tools/eslint-rules/no-duplicate-requires.js index 222e61898e5a82..0a73ccb44a0678 100644 --- a/tools/eslint-rules/no-duplicate-requires.js +++ b/tools/eslint-rules/no-duplicate-requires.js @@ -25,41 +25,43 @@ function isTopLevel(node) { return false; } -module.exports = (context) => { - if (context.parserOptions.sourceType === 'module') { - return {}; - } - - function getRequiredModuleNameFromCall(node) { - // Node has arguments and first argument is string - if (node.arguments.length && isString(node.arguments[0])) { - return node.arguments[0].value.trim(); +module.exports = { + create(context) { + if (context.parserOptions.sourceType === 'module') { + return {}; } - return undefined; - } + function getRequiredModuleNameFromCall(node) { + // Node has arguments and first argument is string + if (node.arguments.length && isString(node.arguments[0])) { + return node.arguments[0].value.trim(); + } - const required = new Set(); + return undefined; + } - const rules = { - CallExpression: (node) => { - if (isRequireCall(node) && isTopLevel(node)) { - const moduleName = getRequiredModuleNameFromCall(node); - if (moduleName === undefined) { - return; - } - if (required.has(moduleName)) { - context.report( - node, - '\'{{moduleName}}\' require is duplicated.', - { moduleName }, - ); - } else { - required.add(moduleName); + const required = new Set(); + + const rules = { + CallExpression: (node) => { + if (isRequireCall(node) && isTopLevel(node)) { + const moduleName = getRequiredModuleNameFromCall(node); + if (moduleName === undefined) { + return; + } + if (required.has(moduleName)) { + context.report( + node, + '\'{{moduleName}}\' require is duplicated.', + { moduleName }, + ); + } else { + required.add(moduleName); + } } - } - }, - }; + }, + }; - return rules; + return rules; + }, }; diff --git a/tools/eslint-rules/no-unescaped-regexp-dot.js b/tools/eslint-rules/no-unescaped-regexp-dot.js index 07100c20782605..6db23732c81fd5 100644 --- a/tools/eslint-rules/no-unescaped-regexp-dot.js +++ b/tools/eslint-rules/no-unescaped-regexp-dot.js @@ -10,7 +10,7 @@ module.exports = { create(context) { - const sourceCode = context.getSourceCode(); + const sourceCode = context.sourceCode; const regexpStack = []; let regexpBuffer = []; let inRegExp = false; diff --git a/tools/eslint-rules/non-ascii-character.js b/tools/eslint-rules/non-ascii-character.js index 1d401671d6cb84..b76126c93242da 100644 --- a/tools/eslint-rules/non-ascii-character.js +++ b/tools/eslint-rules/non-ascii-character.js @@ -24,32 +24,34 @@ const suggestions = { '—': '-', }; -module.exports = (context) => { +module.exports = { + create(context) { - const reportIfError = (node, sourceCode) => { + const reportIfError = (node, sourceCode) => { - const matches = sourceCode.text.match(nonAsciiRegexPattern); + const matches = sourceCode.text.match(nonAsciiRegexPattern); - if (!matches) return; + if (!matches) return; - const offendingCharacter = matches[0]; - const offendingCharacterPosition = matches.index; - const suggestion = suggestions[offendingCharacter]; + const offendingCharacter = matches[0]; + const offendingCharacterPosition = matches.index; + const suggestion = suggestions[offendingCharacter]; - let message = `Non-ASCII character '${offendingCharacter}' detected.`; + let message = `Non-ASCII character '${offendingCharacter}' detected.`; - message = suggestion ? - `${message} Consider replacing with: ${suggestion}` : - message; + message = suggestion ? + `${message} Consider replacing with: ${suggestion}` : + message; - context.report({ - node, - message, - loc: sourceCode.getLocFromIndex(offendingCharacterPosition), - }); - }; + context.report({ + node, + message, + loc: sourceCode.getLocFromIndex(offendingCharacterPosition), + }); + }; - return { - Program: (node) => reportIfError(node, context.getSourceCode()), - }; + return { + Program: (node) => reportIfError(node, context.sourceCode), + }; + }, }; diff --git a/tools/eslint-rules/prefer-assert-iferror.js b/tools/eslint-rules/prefer-assert-iferror.js index 25f881fc0c0cdf..2b1158d6b2c89c 100644 --- a/tools/eslint-rules/prefer-assert-iferror.js +++ b/tools/eslint-rules/prefer-assert-iferror.js @@ -12,7 +12,7 @@ module.exports = { fixable: 'code', }, create(context) { - const sourceCode = context.getSourceCode(); + const sourceCode = context.sourceCode; let assertImported = false; function hasSameTokens(nodeA, nodeB) { diff --git a/tools/eslint-rules/prefer-assert-methods.js b/tools/eslint-rules/prefer-assert-methods.js index 8204a0e791699d..44a035ea2e0818 100644 --- a/tools/eslint-rules/prefer-assert-methods.js +++ b/tools/eslint-rules/prefer-assert-methods.js @@ -31,7 +31,7 @@ module.exports = { node, message: parseError(assertMethod, arg.operator), fix: (fixer) => { - const sourceCode = context.getSourceCode(); + const sourceCode = context.sourceCode; const left = sourceCode.getText(arg.left); const right = sourceCode.getText(arg.right); return fixer.replaceText( diff --git a/tools/eslint-rules/prefer-common-mustsucceed.js b/tools/eslint-rules/prefer-common-mustsucceed.js index 49795f2559fb19..6cc198e17d2f01 100644 --- a/tools/eslint-rules/prefer-common-mustsucceed.js +++ b/tools/eslint-rules/prefer-common-mustsucceed.js @@ -3,64 +3,66 @@ const mustCall = 'CallExpression[callee.object.name="common"]' + '[callee.property.name="mustCall"]'; -module.exports = (context) => { - function isAssertIfError(node) { - return node.type === 'MemberExpression' && - node.object.type === 'Identifier' && - node.object.name === 'assert' && - node.property.type === 'Identifier' && - node.property.name === 'ifError'; - } +module.exports = { + create(context) { + function isAssertIfError(node) { + return node.type === 'MemberExpression' && + node.object.type === 'Identifier' && + node.object.name === 'assert' && + node.property.type === 'Identifier' && + node.property.name === 'ifError'; + } - function isCallToIfError(node, errName) { - return node.type === 'CallExpression' && - isAssertIfError(node.callee) && - node.arguments.length > 0 && - node.arguments[0].type === 'Identifier' && - node.arguments[0].name === errName; - } + function isCallToIfError(node, errName) { + return node.type === 'CallExpression' && + isAssertIfError(node.callee) && + node.arguments.length > 0 && + node.arguments[0].type === 'Identifier' && + node.arguments[0].name === errName; + } - function bodyStartsWithCallToIfError(body, errName) { - while (body.type === 'BlockStatement' && body.body.length > 0) - body = body.body[0]; + function bodyStartsWithCallToIfError(body, errName) { + while (body.type === 'BlockStatement' && body.body.length > 0) + body = body.body[0]; - let expr; - switch (body.type) { - case 'ReturnStatement': - expr = body.argument; - break; - case 'ExpressionStatement': - expr = body.expression; - break; - default: - expr = body; - } + let expr; + switch (body.type) { + case 'ReturnStatement': + expr = body.argument; + break; + case 'ExpressionStatement': + expr = body.expression; + break; + default: + expr = body; + } - return isCallToIfError(expr, errName); - } + return isCallToIfError(expr, errName); + } - return { - [`${mustCall}:exit`]: (mustCall) => { - if (mustCall.arguments.length > 0) { - const callback = mustCall.arguments[0]; - if (isAssertIfError(callback)) { - context.report(mustCall, 'Please use common.mustSucceed instead of ' + - 'common.mustCall(assert.ifError).'); - } + return { + [`${mustCall}:exit`]: (mustCall) => { + if (mustCall.arguments.length > 0) { + const callback = mustCall.arguments[0]; + if (isAssertIfError(callback)) { + context.report(mustCall, 'Please use common.mustSucceed instead of ' + + 'common.mustCall(assert.ifError).'); + } - if (callback.type === 'ArrowFunctionExpression' || - callback.type === 'FunctionExpression') { - if (callback.params.length > 0 && - callback.params[0].type === 'Identifier') { - const errName = callback.params[0].name; - if (bodyStartsWithCallToIfError(callback.body, errName)) { - context.report(mustCall, 'Please use common.mustSucceed instead' + - ' of common.mustCall with' + - ' assert.ifError.'); + if (callback.type === 'ArrowFunctionExpression' || + callback.type === 'FunctionExpression') { + if (callback.params.length > 0 && + callback.params[0].type === 'Identifier') { + const errName = callback.params[0].name; + if (bodyStartsWithCallToIfError(callback.body, errName)) { + context.report(mustCall, 'Please use common.mustSucceed instead' + + ' of common.mustCall with' + + ' assert.ifError.'); + } } } } - } - }, - }; + }, + }; + }, }; diff --git a/tools/eslint-rules/prefer-primordials.js b/tools/eslint-rules/prefer-primordials.js index f8f5cb60c36a63..48b351b46ae270 100644 --- a/tools/eslint-rules/prefer-primordials.js +++ b/tools/eslint-rules/prefer-primordials.js @@ -75,9 +75,27 @@ module.exports = { messages: { error: 'Use `const { {{name}} } = primordials;` instead of the global.', }, + schema: { + type: 'array', + items: [ + { + type: 'object', + required: ['name'], + properties: { + name: { type: 'string' }, + ignore: { + type: 'array', + items: { type: 'string' }, + }, + into: { type: 'string' }, + }, + additionalProperties: false, + }, + ], + }, }, create(context) { - const globalScope = context.getSourceCode().scopeManager.globalScope; + const globalScope = context.sourceCode.scopeManager.globalScope; const nameMap = new Map(); const renameMap = new Map(); @@ -110,7 +128,7 @@ module.exports = { } const name = node.name; const parent = getDestructuringAssignmentParent( - context.getScope(), + context.sourceCode.getScope(node), node, ); const parentName = parent?.name; @@ -155,7 +173,7 @@ module.exports = { } const variables = - context.getSourceCode().scopeManager.getDeclaredVariables(node); + context.sourceCode.scopeManager.getDeclaredVariables(node); if (variables.length === 0) { context.report({ node, diff --git a/tools/eslint-rules/prefer-proto.js b/tools/eslint-rules/prefer-proto.js index fd992cbec3bf98..4b313deb79006b 100644 --- a/tools/eslint-rules/prefer-proto.js +++ b/tools/eslint-rules/prefer-proto.js @@ -7,8 +7,8 @@ 'use strict'; // Cribbed from `eslint-module-utils/declaredScope` -function declaredScope(context, name) { - const references = context.getScope().references; +function declaredScope(context, node, name) { + const references = context.sourceCode.getScope(node).references; const reference = references.find((x) => x.identifier.name === name); if (!reference) return undefined; return reference.resolved.scope.type; @@ -33,12 +33,12 @@ module.exports = { [callee.type="MemberExpression"][callee.object.name="Object"][callee.property.name="create"]\ )'(node) { if (node.callee.type === 'MemberExpression') { - const scope = declaredScope(context, node.callee.object); + const scope = declaredScope(context, node, node.callee.object); if (scope && scope !== 'module' && scope !== 'global') { return; } } - const value = context.getSourceCode().getText(node.arguments[0]); + const value = context.sourceCode.getText(node.arguments[0]); context.report({ node, messageId: 'error', diff --git a/tools/eslint-rules/set-proto-to-null-in-object.js b/tools/eslint-rules/set-proto-to-null-in-object.js index e1a6af38c032dc..4e4cb9345e2471 100644 --- a/tools/eslint-rules/set-proto-to-null-in-object.js +++ b/tools/eslint-rules/set-proto-to-null-in-object.js @@ -46,7 +46,7 @@ module.exports = { message: 'Every object must have __proto__: null', fix: function(fixer) { // Generate the fix suggestion to add __proto__: null - const sourceCode = context.getSourceCode(); + const sourceCode = context.sourceCode; const firstProperty = properties[0]; const firstPropertyToken = sourceCode.getFirstToken(firstProperty);