From c53b4eb9ba5f14fa5281222cd2ceed26b4a5c5d5 Mon Sep 17 00:00:00 2001 From: weiren Date: Wed, 18 Dec 2024 17:44:33 +0800 Subject: [PATCH 1/6] refactor: add utils.getSourceCode(), utils.getScope(), utils.getparserServices(), utils.getFilename() --- lib/rules/fixer-return.js | 7 +++---- lib/rules/meta-property-ordering.js | 5 +++-- lib/rules/no-deprecated-context-methods.js | 2 +- lib/rules/no-deprecated-report-api.js | 2 +- lib/rules/no-identical-tests.js | 2 +- lib/rules/no-meta-schema-default.js | 2 +- lib/rules/no-missing-message-ids.js | 4 ++-- lib/rules/no-missing-placeholders.js | 4 ++-- lib/rules/no-only-tests.js | 3 +-- lib/rules/no-property-in-node.js | 4 +++- lib/rules/no-unused-message-ids.js | 6 +++--- lib/rules/no-unused-placeholders.js | 4 ++-- lib/rules/no-useless-token-range.js | 2 +- lib/rules/prefer-message-ids.js | 4 ++-- lib/rules/prefer-object-rule.js | 2 +- lib/rules/prefer-output-null.js | 2 +- lib/rules/prefer-placeholders.js | 2 +- lib/rules/prefer-replace-text.js | 2 +- lib/rules/report-message-format.js | 6 +++--- lib/rules/require-meta-default-options.js | 2 +- lib/rules/require-meta-docs-description.js | 6 +++--- lib/rules/require-meta-docs-recommended.js | 2 +- lib/rules/require-meta-docs-url.js | 8 ++++---- lib/rules/require-meta-fixable.js | 6 +++--- lib/rules/require-meta-has-suggestions.js | 8 ++++---- lib/rules/require-meta-schema-description.js | 2 +- lib/rules/require-meta-schema.js | 2 +- lib/rules/require-meta-type.js | 6 +++--- lib/rules/test-case-property-ordering.js | 2 +- lib/rules/test-case-shorthand-strings.js | 2 +- lib/utils.js | 21 ++++++++++++++++++++ package.json | 2 +- 32 files changed, 78 insertions(+), 56 deletions(-) diff --git a/lib/rules/fixer-return.js b/lib/rules/fixer-return.js index 0ea7c857..11e7d57f 100644 --- a/lib/rules/fixer-return.js +++ b/lib/rules/fixer-return.js @@ -76,12 +76,11 @@ module.exports = { * @returns {boolean} */ function isFix(node) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: use context.sourceCode when dropping eslint < v9 if (node.type === 'ArrayExpression' && node.elements.length === 0) { // An empty array is not a fix. return false; } - const scope = sourceCode.getScope?.(node) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < 9.0.0 + const scope = utils.getScope(context); const staticValue = getStaticValue(node, scope); if (!staticValue) { // If we can't find a static value, assume it's a real fix value. @@ -99,7 +98,7 @@ module.exports = { return { Program(ast) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); contextIdentifiers = utils.getContextIdentifiers( sourceCode.scopeManager, ast, @@ -149,7 +148,7 @@ module.exports = { // Ensure the current (arrow) fixer function returned a fix. 'ArrowFunctionExpression:exit'(node) { if (funcInfo.shouldCheck) { - const sourceCode = context.sourceCode || context.getSourceCode(); + const sourceCode = utils.getSourceCode(context); const loc = sourceCode.getTokenBefore(node.body).loc; // Show violation on arrow (=>). if (node.expression) { // When the return is implied (no curly braces around the body), we have to check the single body node directly. diff --git a/lib/rules/meta-property-ordering.js b/lib/rules/meta-property-ordering.js index 04142237..27e29218 100644 --- a/lib/rules/meta-property-ordering.js +++ b/lib/rules/meta-property-ordering.js @@ -4,7 +4,8 @@ 'use strict'; -const { getKeyName, getRuleInfo } = require('../utils'); +const utils = require('../utils'); +const { getKeyName, getRuleInfo } = utils; const defaultOrder = [ 'type', @@ -48,7 +49,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const ruleInfo = getRuleInfo(sourceCode); if (!ruleInfo) { return {}; diff --git a/lib/rules/no-deprecated-context-methods.js b/lib/rules/no-deprecated-context-methods.js index e72580ca..c4f6134b 100644 --- a/lib/rules/no-deprecated-context-methods.js +++ b/lib/rules/no-deprecated-context-methods.js @@ -54,7 +54,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); // ---------------------------------------------------------------------- // Public diff --git a/lib/rules/no-deprecated-report-api.js b/lib/rules/no-deprecated-report-api.js index 266cb71d..eb0c07c2 100644 --- a/lib/rules/no-deprecated-report-api.js +++ b/lib/rules/no-deprecated-report-api.js @@ -30,7 +30,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); let contextIdentifiers; // ---------------------------------------------------------------------- diff --git a/lib/rules/no-identical-tests.js b/lib/rules/no-identical-tests.js index c0744fad..c7c5867f 100644 --- a/lib/rules/no-identical-tests.js +++ b/lib/rules/no-identical-tests.js @@ -32,7 +32,7 @@ module.exports = { // ---------------------------------------------------------------------- // Public // ---------------------------------------------------------------------- - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); // ---------------------------------------------------------------------- // Helpers diff --git a/lib/rules/no-meta-schema-default.js b/lib/rules/no-meta-schema-default.js index 171d55e6..ccba978a 100644 --- a/lib/rules/no-meta-schema-default.js +++ b/lib/rules/no-meta-schema-default.js @@ -25,7 +25,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { diff --git a/lib/rules/no-missing-message-ids.js b/lib/rules/no-missing-message-ids.js index 1066b855..0bc2d9ed 100644 --- a/lib/rules/no-missing-message-ids.js +++ b/lib/rules/no-missing-message-ids.js @@ -26,7 +26,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { @@ -48,7 +48,7 @@ module.exports = { }, CallExpression(node) { - const scope = sourceCode.getScope?.(node) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < 9.0.0 + const scope = utils.getScope(context); // Check for messageId properties used in known calls to context.report(); if ( node.callee.type === 'MemberExpression' && diff --git a/lib/rules/no-missing-placeholders.js b/lib/rules/no-missing-placeholders.js index 364c340f..996e8004 100644 --- a/lib/rules/no-missing-placeholders.js +++ b/lib/rules/no-missing-placeholders.js @@ -31,7 +31,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; let contextIdentifiers; @@ -48,7 +48,7 @@ module.exports = { contextIdentifiers = utils.getContextIdentifiers(scopeManager, ast); }, CallExpression(node) { - const scope = sourceCode.getScope?.(node) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < 9.0.0 + const scope = utils.getScope(context); if ( node.callee.type === 'MemberExpression' && contextIdentifiers.has(node.callee.object) && diff --git a/lib/rules/no-only-tests.js b/lib/rules/no-only-tests.js index 816fedd1..3aa267d2 100644 --- a/lib/rules/no-only-tests.js +++ b/lib/rules/no-only-tests.js @@ -51,8 +51,7 @@ module.exports = { { messageId: 'removeOnly', *fix(fixer) { - const sourceCode = - context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const tokenBefore = sourceCode.getTokenBefore(onlyProperty); diff --git a/lib/rules/no-property-in-node.js b/lib/rules/no-property-in-node.js index ace20884..f21e0060 100644 --- a/lib/rules/no-property-in-node.js +++ b/lib/rules/no-property-in-node.js @@ -1,5 +1,7 @@ 'use strict'; +const utils = require('../utils'); + const defaultTypedNodeSourceFileTesters = [ /@types[/\\]estree[/\\]index\.d\.ts/, /@typescript-eslint[/\\]types[/\\]dist[/\\]generated[/\\]ast-spec\.d\.ts/, @@ -88,7 +90,7 @@ module.exports = { 'BinaryExpression[operator=in]'(node) { // TODO: Switch this to ESLintUtils.getParserServices with typescript-eslint@>=6 // https://github.com/eslint-community/eslint-plugin-eslint-plugin/issues/269 - const services = (context.sourceCode || context).parserServices; + const services = utils.getparserServices(context); if (!services.program) { throw new Error( 'You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.', diff --git a/lib/rules/no-unused-message-ids.js b/lib/rules/no-unused-message-ids.js index 978fad10..69036140 100644 --- a/lib/rules/no-unused-message-ids.js +++ b/lib/rules/no-unused-message-ids.js @@ -24,7 +24,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { @@ -47,7 +47,7 @@ module.exports = { contextIdentifiers = utils.getContextIdentifiers(scopeManager, ast); }, - 'Program:exit'(ast) { + 'Program:exit'() { if (hasSeenUnknownMessageId || !hasSeenViolationReport) { /* Bail out when the rule is likely to have false positives. @@ -57,7 +57,7 @@ module.exports = { return; } - const scope = sourceCode.getScope?.(ast) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < 9.0.0 + const scope = utils.getScope(context); const messageIdNodesUnused = messageIdNodes.filter( (node) => !messageIdsUsed.has(utils.getKeyName(node, scope)), diff --git a/lib/rules/no-unused-placeholders.js b/lib/rules/no-unused-placeholders.js index ca95c952..d7169c9a 100644 --- a/lib/rules/no-unused-placeholders.js +++ b/lib/rules/no-unused-placeholders.js @@ -31,7 +31,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; let contextIdentifiers; @@ -47,7 +47,7 @@ module.exports = { contextIdentifiers = utils.getContextIdentifiers(scopeManager, ast); }, CallExpression(node) { - const scope = sourceCode.getScope?.(node) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < 9.0.0 + const scope = utils.getScope(context); if ( node.callee.type === 'MemberExpression' && contextIdentifiers.has(node.callee.object) && diff --git a/lib/rules/no-useless-token-range.js b/lib/rules/no-useless-token-range.js index 998c0059..6c6d6214 100644 --- a/lib/rules/no-useless-token-range.js +++ b/lib/rules/no-useless-token-range.js @@ -30,7 +30,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); // ---------------------------------------------------------------------- // Helpers diff --git a/lib/rules/prefer-message-ids.js b/lib/rules/prefer-message-ids.js index 1d932748..cdf66642 100644 --- a/lib/rules/prefer-message-ids.js +++ b/lib/rules/prefer-message-ids.js @@ -29,7 +29,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { return {}; @@ -43,7 +43,7 @@ module.exports = { return { Program(ast) { - const scope = sourceCode.getScope?.(ast) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + const scope = utils.getScope(context); contextIdentifiers = utils.getContextIdentifiers( sourceCode.scopeManager, ast, diff --git a/lib/rules/prefer-object-rule.js b/lib/rules/prefer-object-rule.js index 4a9351bf..1b0e98f1 100644 --- a/lib/rules/prefer-object-rule.js +++ b/lib/rules/prefer-object-rule.js @@ -32,7 +32,7 @@ module.exports = { // Public // ---------------------------------------------------------------------- - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { return {}; diff --git a/lib/rules/prefer-output-null.js b/lib/rules/prefer-output-null.js index d9be111b..4d9e90e5 100644 --- a/lib/rules/prefer-output-null.js +++ b/lib/rules/prefer-output-null.js @@ -35,7 +35,7 @@ module.exports = { // Public // ---------------------------------------------------------------------- - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); return { Program(ast) { diff --git a/lib/rules/prefer-placeholders.js b/lib/rules/prefer-placeholders.js index a1555945..f5c88fc1 100644 --- a/lib/rules/prefer-placeholders.js +++ b/lib/rules/prefer-placeholders.js @@ -33,7 +33,7 @@ module.exports = { create(context) { let contextIdentifiers; - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; // ---------------------------------------------------------------------- diff --git a/lib/rules/prefer-replace-text.js b/lib/rules/prefer-replace-text.js index 100c618c..173cc509 100644 --- a/lib/rules/prefer-replace-text.js +++ b/lib/rules/prefer-replace-text.js @@ -30,7 +30,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); let funcInfo = { upper: null, codePath: null, diff --git a/lib/rules/report-message-format.js b/lib/rules/report-message-format.js index d6d308f5..4fce24b8 100644 --- a/lib/rules/report-message-format.js +++ b/lib/rules/report-message-format.js @@ -63,7 +63,7 @@ module.exports = { } } - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { return {}; @@ -75,7 +75,7 @@ module.exports = { return { Program(ast) { - const scope = sourceCode.getScope?.(ast) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + const scope = utils.getScope(context); contextIdentifiers = utils.getContextIdentifiers( sourceCode.scopeManager, ast, @@ -103,7 +103,7 @@ module.exports = { .forEach((it) => processMessageNode(it, scope)); }, CallExpression(node) { - const scope = sourceCode.getScope?.(node) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + const scope = utils.getScope(context); if ( node.callee.type === 'MemberExpression' && contextIdentifiers.has(node.callee.object) && diff --git a/lib/rules/require-meta-default-options.js b/lib/rules/require-meta-default-options.js index e1166b08..9ac37575 100644 --- a/lib/rules/require-meta-default-options.js +++ b/lib/rules/require-meta-default-options.js @@ -26,7 +26,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { diff --git a/lib/rules/require-meta-docs-description.js b/lib/rules/require-meta-docs-description.js index 0ff4ac38..b3cf5272 100644 --- a/lib/rules/require-meta-docs-description.js +++ b/lib/rules/require-meta-docs-description.js @@ -46,15 +46,15 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { return {}; } return { - Program(ast) { - const scope = sourceCode.getScope?.(ast) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + Program() { + const scope = utils.getScope(context); const { scopeManager } = sourceCode; const { diff --git a/lib/rules/require-meta-docs-recommended.js b/lib/rules/require-meta-docs-recommended.js index b4ae768b..67851ffc 100644 --- a/lib/rules/require-meta-docs-recommended.js +++ b/lib/rules/require-meta-docs-recommended.js @@ -57,7 +57,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { return {}; diff --git a/lib/rules/require-meta-docs-url.js b/lib/rules/require-meta-docs-url.js index 90650626..cb3e35d3 100644 --- a/lib/rules/require-meta-docs-url.js +++ b/lib/rules/require-meta-docs-url.js @@ -55,7 +55,7 @@ module.exports = { */ create(context) { const options = context.options[0] || {}; - const filename = context.filename || context.getFilename(); // TODO: just use context.filename when dropping eslint < v9 + const filename = utils.getFilename(context); const ruleName = filename === '' ? undefined @@ -77,15 +77,15 @@ module.exports = { ); } - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { return {}; } return { - Program(ast) { - const scope = sourceCode.getScope?.(ast) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + Program() { + const scope = utils.getScope(context); const { scopeManager } = sourceCode; const { diff --git a/lib/rules/require-meta-fixable.js b/lib/rules/require-meta-fixable.js index 76ab6032..e69ca4fc 100644 --- a/lib/rules/require-meta-fixable.js +++ b/lib/rules/require-meta-fixable.js @@ -50,7 +50,7 @@ module.exports = { const catchNoFixerButFixableProperty = context.options[0] && context.options[0].catchNoFixerButFixableProperty; - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; const ruleInfo = utils.getRuleInfo(sourceCode); let contextIdentifiers; @@ -79,8 +79,8 @@ module.exports = { usesFixFunctions = true; } }, - 'Program:exit'(ast) { - const scope = sourceCode.getScope?.(ast) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + 'Program:exit'() { + const scope = utils.getScope(context); const metaFixableProp = ruleInfo && utils diff --git a/lib/rules/require-meta-has-suggestions.js b/lib/rules/require-meta-has-suggestions.js index 1759eecf..c8f75b3f 100644 --- a/lib/rules/require-meta-has-suggestions.js +++ b/lib/rules/require-meta-has-suggestions.js @@ -29,7 +29,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { @@ -44,7 +44,7 @@ module.exports = { * @returns {boolean} whether this property should be considered to contain suggestions */ function doesPropertyContainSuggestions(node) { - const scope = sourceCode.getScope?.(node) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + const scope = utils.getScope(context); const staticValue = getStaticValue(node.value, scope); if ( !staticValue || @@ -95,8 +95,8 @@ module.exports = { ruleReportsSuggestions = true; } }, - 'Program:exit'(node) { - const scope = sourceCode.getScope?.(node) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + 'Program:exit'() { + const scope = utils.getScope(context); const metaNode = ruleInfo && ruleInfo.meta; const hasSuggestionsProperty = utils .evaluateObjectProperties(metaNode, scopeManager) diff --git a/lib/rules/require-meta-schema-description.js b/lib/rules/require-meta-schema-description.js index 4606a489..842d576f 100644 --- a/lib/rules/require-meta-schema-description.js +++ b/lib/rules/require-meta-schema-description.js @@ -25,7 +25,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { diff --git a/lib/rules/require-meta-schema.js b/lib/rules/require-meta-schema.js index f885aa4b..59cf4575 100644 --- a/lib/rules/require-meta-schema.js +++ b/lib/rules/require-meta-schema.js @@ -43,7 +43,7 @@ module.exports = { }, create(context) { - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const { scopeManager } = sourceCode; const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { diff --git a/lib/rules/require-meta-type.js b/lib/rules/require-meta-type.js index 24036071..a6aec027 100644 --- a/lib/rules/require-meta-type.js +++ b/lib/rules/require-meta-type.js @@ -38,15 +38,15 @@ module.exports = { // Public // ---------------------------------------------------------------------- - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); const ruleInfo = utils.getRuleInfo(sourceCode); if (!ruleInfo) { return {}; } return { - Program(node) { - const scope = sourceCode.getScope?.(node) || context.getScope(); // TODO: just use sourceCode.getScope() when we drop support for ESLint < v9.0.0 + Program() { + const scope = utils.getScope(context); const { scopeManager } = sourceCode; const metaNode = ruleInfo.meta; diff --git a/lib/rules/test-case-property-ordering.js b/lib/rules/test-case-property-ordering.js index 6bf7a4a0..f6b4dd2f 100644 --- a/lib/rules/test-case-property-ordering.js +++ b/lib/rules/test-case-property-ordering.js @@ -55,7 +55,7 @@ module.exports = { // Public // ---------------------------------------------------------------------- const order = context.options[0] || defaultOrder; - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); return { Program(ast) { diff --git a/lib/rules/test-case-shorthand-strings.js b/lib/rules/test-case-shorthand-strings.js index 68e813e3..0cf22333 100644 --- a/lib/rules/test-case-shorthand-strings.js +++ b/lib/rules/test-case-shorthand-strings.js @@ -39,7 +39,7 @@ module.exports = { create(context) { const shorthandOption = context.options[0] || 'as-needed'; - const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 + const sourceCode = utils.getSourceCode(context); // ---------------------------------------------------------------------- // Helpers diff --git a/lib/utils.js b/lib/utils.js index b049eacb..bc15d2c0 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1003,4 +1003,25 @@ module.exports = { return variable?.defs[0]?.type === 'Parameter'; }, + + getSourceCode(context) { + // TODO: remove contet.getSourceCode() when dropping eslint < v9 + return context.sourceCode || context.getSourceCode(); + }, + + getScope(context) { + // TODO: remove contet.getScope() when dropping eslint < v9 + const sourceCode = context.sourceCode || context.getSourceCode(); + return sourceCode.getScope?.(sourceCode.ast) || context.getScope(); + }, + + getparserServices(context) { + // TODO: remove context.parserServices when dropping eslint < v9 + return (context.sourceCode || context).parserServices; + }, + + getFilename(context) { + // TODO: just use context.filename when dropping eslint < v9 + return context.filename || context.getFilename(); + }, }; diff --git a/package.json b/package.json index c29b6e39..5f259b41 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "estraverse": "^5.3.0" }, "nyc": { - "branches": 90, + "branches": 95, "functions": 99, "lines": 99, "statements": 99 From e90946190ce941f6e20ab90ed6dbec1ddc0ad670 Mon Sep 17 00:00:00 2001 From: weiren Date: Wed, 18 Dec 2024 18:11:53 +0800 Subject: [PATCH 2/6] build: add node v23 --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 470964ab..f4f9204f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,6 +12,7 @@ jobs: fail-fast: false matrix: node-version: + - 23 - 22 - 21 - 20 From ba1217b2251a37f866ecd1722a017b50b461064e Mon Sep 17 00:00:00 2001 From: Daniel Rentz Date: Fri, 20 Dec 2024 06:59:09 +0100 Subject: [PATCH 3/6] docs: small typo in [prefer-replace-text] (#512) --- docs/rules/prefer-replace-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/prefer-replace-text.md b/docs/rules/prefer-replace-text.md index 076665cf..881d544c 100644 --- a/docs/rules/prefer-replace-text.md +++ b/docs/rules/prefer-replace-text.md @@ -15,7 +15,7 @@ module.exports = { create(context) { context.report({ fix(fixer) { - // error, can be written: return fixer.replaceText([node, '']); + // error, can be written: return fixer.replaceText(node, ''); return fixer.replaceTextRange([node.range[0], node.range[1]], ''); }, }); From 735b983d5a2d56d3731b6261809bbc04413ed2ff Mon Sep 17 00:00:00 2001 From: Zwyx <29386932+Zwyx@users.noreply.github.com> Date: Mon, 5 May 2025 19:22:28 +0800 Subject: [PATCH 4/6] docs: Remove mention of `sourceType` in the recommended config (#515) The recommended configuration doesn't set `sourceType` to `script` anymore. See https://github.com/eslint-community/eslint-plugin-eslint-plugin/issues/514 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e9553dfc..32f86899 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,11 @@ npm install eslint-plugin-eslint-plugin --save-dev Here's an example ESLint configuration that: -- Sets `sourceType` to `script` for CJS plugins (most users) (use `module` for ESM/TypeScript) - Enables the `recommended` configuration - Enables an optional/non-recommended rule +Note: you might need to set `sourceType` to `script` (most users) (use `module` for ESM/TypeScript). + ### **[.eslintrc.json](https://eslint.org/docs/latest/use/configure/configuration-files)** ```json From 105f05d73ebed88d2c78ae75cb6f3c6ab8c21aa9 Mon Sep 17 00:00:00 2001 From: Jens B Date: Wed, 18 Jun 2025 17:14:46 +0200 Subject: [PATCH 5/6] Add new rule `no-meta-replaced-by` (#518) * feat: add `no-meta-replaced-by` rule * test: add `no-meta-replaced-by` tests * docs: add `no-meta-replaced-by` docs * docs: add `When Not To Use It` * fix: update description and recommendation status for rule * test: add valid test case * docs: clarify description of rule and update examples * fix: cleanup jsdoc * docs: update examples of correct code * docs: remove `When not to use it` Co-authored-by: Bryan Mishkin <698306+bmish@users.noreply.github.com> * Update docs/rules/no-meta-replaced-by.md --------- Co-authored-by: Bryan Mishkin <698306+bmish@users.noreply.github.com> --- README.md | 1 + docs/rules/no-meta-replaced-by.md | 62 +++++++++++ lib/rules/no-meta-replaced-by.js | 63 +++++++++++ tests/lib/rules/no-meta-replaced-by.js | 139 +++++++++++++++++++++++++ 4 files changed, 265 insertions(+) create mode 100644 docs/rules/no-meta-replaced-by.md create mode 100644 lib/rules/no-meta-replaced-by.js create mode 100644 tests/lib/rules/no-meta-replaced-by.js diff --git a/README.md b/README.md index 32f86899..f6eeb235 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ module.exports = [ | [meta-property-ordering](docs/rules/meta-property-ordering.md) | enforce the order of meta properties | | 🔧 | | | | [no-deprecated-context-methods](docs/rules/no-deprecated-context-methods.md) | disallow usage of deprecated methods on rule context objects | ✅ | 🔧 | | | | [no-deprecated-report-api](docs/rules/no-deprecated-report-api.md) | disallow the version of `context.report()` with multiple arguments | ✅ | 🔧 | | | +| [no-meta-replaced-by](docs/rules/no-meta-replaced-by.md) | disallow using the `meta.replacedBy` rule property | | | | | | [no-meta-schema-default](docs/rules/no-meta-schema-default.md) | disallow rules `meta.schema` properties to include defaults | | | | | | [no-missing-message-ids](docs/rules/no-missing-message-ids.md) | disallow `messageId`s that are missing from `meta.messages` | ✅ | | | | | [no-missing-placeholders](docs/rules/no-missing-placeholders.md) | disallow missing placeholders in rule report messages | ✅ | | | | diff --git a/docs/rules/no-meta-replaced-by.md b/docs/rules/no-meta-replaced-by.md new file mode 100644 index 00000000..070fa5ef --- /dev/null +++ b/docs/rules/no-meta-replaced-by.md @@ -0,0 +1,62 @@ +# Disallow using the `meta.replacedBy` rule property (`eslint-plugin/no-meta-replaced-by`) + + + +As of ESLint v9.21.0, the rule property `meta.deprecated` can be either a boolean or an object of type `DeprecatedInfo`. The `DeprecatedInfo` type includes an optional `replacedBy` array that replaces the now-deprecated `meta.replacedBy` property. + +Examples of correct usage: + +- [array-bracket-newline](https://github.com/eslint/eslint/blob/4112fd09531092e9651e9981205bcd603dc56acf/lib/rules/array-bracket-newline.js#L18-L38) +- [typescript-eslint/no-empty-interface](https://github.com/typescript-eslint/typescript-eslint/blob/af94f163a1d6447a84c5571fff5e38e4c700edb9/packages/eslint-plugin/src/rules/no-empty-interface.ts#L19-L30) + +## Rule Details + +This rule disallows the `meta.replacedBy` property in a rule. + +Examples of **incorrect** code for this rule: + +```js +/* eslint eslint-plugin/no-meta-replaced-by: error */ + +module.exports = { + meta: { + deprecated: true, + replacedBy: ['the-new-rule'], + }, + create() {}, +}; +``` + +Examples of **correct** code for this rule: + +```js +/* eslint eslint-plugin/no-meta-replaced-by: error */ + +module.exports = { + meta: { + deprecated: { + message: 'The new rule adds more functionality', + replacedBy: [ + { + rule: { + name: 'the-new-rule', + }, + }, + ], + }, + }, + create() {}, +}; + +module.exports = { + meta: { + deprecated: true, + }, + create() {}, +}; +``` + +## Further Reading + +- [ESLint docs: `DeprecatedInfo`](https://eslint.org/docs/latest/extend/rule-deprecation#-deprecatedinfo-type) +- [RFC introducing `DeprecatedInfo` type](https://github.com/eslint/rfcs/tree/main/designs/2024-deprecated-rule-metadata) diff --git a/lib/rules/no-meta-replaced-by.js b/lib/rules/no-meta-replaced-by.js new file mode 100644 index 00000000..36aa1297 --- /dev/null +++ b/lib/rules/no-meta-replaced-by.js @@ -0,0 +1,63 @@ +/** + * @fileoverview Disallows the usage of `meta.replacedBy` property + */ + +'use strict'; + +const utils = require('../utils'); + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'disallow using the `meta.replacedBy` rule property', + category: 'Rules', + recommended: false, + url: 'https://github.com/eslint-community/eslint-plugin-eslint-plugin/tree/HEAD/docs/rules/no-meta-replaced-by.md', + }, + schema: [], + messages: { + useNewFormat: + 'Use `meta.deprecated.replacedBy` instead of `meta.replacedBy`', + }, + }, + create(context) { + const sourceCode = utils.getSourceCode(context); + const ruleInfo = utils.getRuleInfo(sourceCode); + + if (!ruleInfo) { + return {}; + } + + return { + Program() { + const metaNode = ruleInfo.meta; + + if (!metaNode) { + return; + } + + const replacedByNode = utils + .evaluateObjectProperties(metaNode, sourceCode.scopeManager) + .find( + (p) => + p.type === 'Property' && utils.getKeyName(p) === 'replacedBy', + ); + + if (!replacedByNode) { + return; + } + + context.report({ + node: replacedByNode, + messageId: 'useNewFormat', + }); + }, + }; + }, +}; diff --git a/tests/lib/rules/no-meta-replaced-by.js b/tests/lib/rules/no-meta-replaced-by.js new file mode 100644 index 00000000..d72f41ac --- /dev/null +++ b/tests/lib/rules/no-meta-replaced-by.js @@ -0,0 +1,139 @@ +/** + * @fileoverview Disallows the usage of `meta.replacedBy` property + */ + +'use strict'; + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/no-meta-replaced-by'); +const RuleTester = require('../eslint-rule-tester').RuleTester; + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const valid = [ + 'module.exports = {};', + ` + module.exports = { + create(context) {}, + }; + `, + ` + module.exports = { + meta: {}, + create(context) {}, + }; + `, + ` + module.exports = { + meta: { + deprecated: true, + }, + create(context) {}, + }; + `, + { + code: ` + module.exports = { + meta: { + deprecated: { + replacedBy: [ + { + rule: { + name: 'foo', + }, + }, + ], + }, + }, + create(context) {}, + }; + `, + errors: 0, + }, +]; + +const invalid = [ + { + code: ` + module.exports = { + meta: { + replacedBy: ['the-new-rule'], + }, + create(context) {}, + }; + `, + errors: [ + { + messageId: 'useNewFormat', + line: 4, + endLine: 4, + }, + ], + }, + { + code: ` + const meta = { + replacedBy: null, + }; + + module.exports = { + meta, + create(context) {}, + }; + `, + errors: [ + { + messageId: 'useNewFormat', + line: 3, + endLine: 3, + }, + ], + }, + { + code: ` + const spread = { + replacedBy: null, + }; + + module.exports = { + meta: { + ...spread, + }, + create(context) {}, + }; + `, + errors: [{ messageId: 'useNewFormat' }], + }, +]; + +const testToESM = (test) => { + if (typeof test === 'string') { + return test.replace('module.exports =', 'export default'); + } + + const code = test.code.replace('module.exports =', 'export default'); + + return { + ...test, + code, + }; +}; + +new RuleTester({ + languageOptions: { sourceType: 'commonjs' }, +}).run('no-meta-replaced-by', rule, { + valid, + invalid, +}); + +new RuleTester({ + languageOptions: { sourceType: 'module' }, +}).run('no-meta-replaced-by', rule, { + valid: valid.map(testToESM), + invalid: invalid.map(testToESM), +}); From 5fdc72ca34c10c85c99da243380f9aafeda1255d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 11:42:44 -0400 Subject: [PATCH 6/6] chore(main): release 6.5.0 (#520) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 510e4cad..cd509eda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,13 @@ * update dependency markdownlint-cli to ^0.38.0 ([#410](https://github.com/eslint-community/eslint-plugin-eslint-plugin/issues/410)) ([6b53c5b](https://github.com/eslint-community/eslint-plugin-eslint-plugin/commit/6b53c5b7b8bc9e19dcb86796ab29019f89c449fc)) * update dependency markdownlint-cli to ^0.39.0 ([#431](https://github.com/eslint-community/eslint-plugin-eslint-plugin/issues/431)) ([f005a2c](https://github.com/eslint-community/eslint-plugin-eslint-plugin/commit/f005a2c0231b8b77f6862dca81b4a6e3099e0493)) +## [6.5.0](https://github.com/eslint-community/eslint-plugin-eslint-plugin/compare/v6.4.0...v6.5.0) (2025-06-18) + + +### Features + +* Add new rule `no-meta-replaced-by` ([105f05d](https://github.com/eslint-community/eslint-plugin-eslint-plugin/commit/105f05d73ebed88d2c78ae75cb6f3c6ab8c21aa9)) + ## [6.4.0](https://github.com/eslint-community/eslint-plugin-eslint-plugin/compare/v6.3.2...v6.4.0) (2024-12-18) diff --git a/package.json b/package.json index 5f259b41..be4d50fc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-eslint-plugin", - "version": "6.4.0", + "version": "6.5.0", "description": "An ESLint plugin for linting ESLint plugins", "author": "Teddy Katz", "main": "./lib/index.js",