Repository: not-an-aardvark/eslint-plugin-eslint-plugin
Pull request #112 (2021-04-16 11:20:22)

Refactor: `utils.getRuleInfo`
Make it accept object contains `ast` and optional `scopeManager`, so we can simply just pass `sourceCode` to it. I believe this will fix some reference searching.

aladdin-add: just to confirm: `sourceCode` contains more than `ast` and `scopeManager`, but other properties will not be used?

I feel a little hesitate to pass the unused properties - it could be confusing. :)
fisker: > just to confirm: sourceCode contains more than ast and scopeManager, but other properties will not be used?

Yes. But accessing `sourceCode` is cheap, almost every rule need access to it.

Patch:
diff --git a/lib/rules/meta-property-ordering.js b/lib/rules/meta-property-ordering.js
index 6fb67a5..6a58ff4 100644
--- a/lib/rules/meta-property-ordering.js
+++ b/lib/rules/meta-property-ordering.js
@@ -27,7 +27,7 @@ module.exports = {
 
   create (context) {
     const sourceCode = context.getSourceCode();
-    const info = getRuleInfo(sourceCode.ast);
+    const info = getRuleInfo(sourceCode);
 
     const message = 'The meta properties should be placed in a consistent order: [{{order}}].';
     const order = context.options[0] || ['type', 'docs', 'fixable', 'schema', 'messages'];
diff --git a/lib/rules/prefer-object-rule.js b/lib/rules/prefer-object-rule.js
index 4cd781a..f8d3b49 100644
--- a/lib/rules/prefer-object-rule.js
+++ b/lib/rules/prefer-object-rule.js
@@ -31,7 +31,7 @@ module.exports = {
     // ----------------------------------------------------------------------
 
     const sourceCode = context.getSourceCode();
-    const ruleInfo = utils.getRuleInfo(sourceCode.ast);
+    const ruleInfo = utils.getRuleInfo(sourceCode);
 
     return {
       Program () {
diff --git a/lib/rules/report-message-format.js b/lib/rules/report-message-format.js
index d2291ea..cef98cf 100644
--- a/lib/rules/report-message-format.js
+++ b/lib/rules/report-message-format.js
@@ -54,7 +54,7 @@ module.exports = {
     return {
       Program (node) {
         contextIdentifiers = utils.getContextIdentifiers(context, node);
-        const ruleInfo = utils.getRuleInfo(context.getSourceCode().ast);
+        const ruleInfo = utils.getRuleInfo(context.getSourceCode());
         const messagesObject = ruleInfo &&
           ruleInfo.meta &&
           ruleInfo.meta.type === 'ObjectExpression' &&
diff --git a/lib/rules/require-meta-docs-description.js b/lib/rules/require-meta-docs-description.js
index dbf7e32..4e5b77b 100644
--- a/lib/rules/require-meta-docs-description.js
+++ b/lib/rules/require-meta-docs-description.js
@@ -47,7 +47,7 @@ module.exports = {
 
   create (context) {
     const sourceCode = context.getSourceCode();
-    const info = utils.getRuleInfo(sourceCode.ast, sourceCode.scopeManager);
+    const info = utils.getRuleInfo(sourceCode);
 
     return {
       Program () {
diff --git a/lib/rules/require-meta-docs-url.js b/lib/rules/require-meta-docs-url.js
index da21104..7843139 100644
--- a/lib/rules/require-meta-docs-url.js
+++ b/lib/rules/require-meta-docs-url.js
@@ -66,7 +66,7 @@ module.exports = {
 
     return {
       Program (node) {
-        const info = util.getRuleInfo(node);
+        const info = util.getRuleInfo(sourceCode);
         if (info === null) {
           return;
         }
diff --git a/lib/rules/require-meta-fixable.js b/lib/rules/require-meta-fixable.js
index 497e88f..bdf368b 100644
--- a/lib/rules/require-meta-fixable.js
+++ b/lib/rules/require-meta-fixable.js
@@ -24,7 +24,7 @@ module.exports = {
 
   create (context) {
     const sourceCode = context.getSourceCode();
-    const ruleInfo = utils.getRuleInfo(sourceCode.ast);
+    const ruleInfo = utils.getRuleInfo(sourceCode);
     let contextIdentifiers;
     let usesFixFunctions;
 
diff --git a/lib/rules/require-meta-schema.js b/lib/rules/require-meta-schema.js
index f46b039..143563c 100644
--- a/lib/rules/require-meta-schema.js
+++ b/lib/rules/require-meta-schema.js
@@ -35,8 +35,8 @@ module.exports = {
 
   create (context) {
     const sourceCode = context.getSourceCode();
-    const { ast, scopeManager } = sourceCode;
-    const info = utils.getRuleInfo(ast, scopeManager);
+    const { scopeManager } = sourceCode;
+    const info = utils.getRuleInfo(sourceCode);
 
     return {
       Program () {
diff --git a/lib/rules/require-meta-type.js b/lib/rules/require-meta-type.js
index d9cb520..f0bb1e8 100644
--- a/lib/rules/require-meta-type.js
+++ b/lib/rules/require-meta-type.js
@@ -30,7 +30,7 @@ module.exports = {
 
   create (context) {
     const sourceCode = context.getSourceCode();
-    const info = utils.getRuleInfo(sourceCode.ast, sourceCode.scopeManager);
+    const info = utils.getRuleInfo(sourceCode);
 
     // ----------------------------------------------------------------------
     // Helpers
diff --git a/lib/utils.js b/lib/utils.js
index fd92b1b..829c16a 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -85,13 +85,13 @@ module.exports = {
 
   /**
   * Performs static analysis on an AST to try to determine the final value of `module.exports`.
-  * @param {ASTNode} ast The `Program` AST node
+  * @param {{ast: ASTNode, scopeManager?: ScopeManager}} sourceCode The object contains `Program` AST node, and optional `scopeManager`
   * @returns {Object} An object with keys `meta`, `create`, and `isNewStyle`. `meta` and `create` correspond to the AST nodes
   for the final values of `module.exports.meta` and `module.exports.create`. `isNewStyle` will be `true` if `module.exports`
   is an object, and `false` if module.exports is just the `create` function. If no valid ESLint rule info can be extracted
   from the file, the return value will be `null`.
   */
-  getRuleInfo (ast, scopeManager) {
+  getRuleInfo ({ ast, scopeManager }) {
     const INTERESTING_KEYS = new Set(['create', 'meta']);
     let exportsVarOverridden = false;
     let exportsIsFunction = false;
@@ -171,7 +171,7 @@ module.exports = {
   * @returns {Set<ASTNode>} A Set of all `Identifier` nodes that are references to the `context` value for the file
   */
   getContextIdentifiers (context, ast) {
-    const ruleInfo = module.exports.getRuleInfo(ast);
+    const ruleInfo = module.exports.getRuleInfo({ ast });
 
     if (!ruleInfo || !ruleInfo.create.params.length || ruleInfo.create.params[0].type !== 'Identifier') {
       return new Set();


Test patch:
diff --git a/tests/lib/utils.js b/tests/lib/utils.js
index efbcc97..8f5cb5e 100644
--- a/tests/lib/utils.js
+++ b/tests/lib/utils.js
@@ -28,7 +28,7 @@ describe('utils', () => {
       ].forEach(noRuleCase => {
         it(`returns null for ${noRuleCase}`, () => {
           const ast = espree.parse(noRuleCase, { ecmaVersion: 8, range: true });
-          assert.isNull(utils.getRuleInfo(ast), 'Expected no rule to be found');
+          assert.isNull(utils.getRuleInfo({ ast }), 'Expected no rule to be found');
         });
       });
     });
@@ -115,7 +115,7 @@ describe('utils', () => {
       Object.keys(CASES).forEach(ruleSource => {
         it(ruleSource, () => {
           const ast = espree.parse(ruleSource, { ecmaVersion: 6, range: true });
-          const ruleInfo = utils.getRuleInfo(ast);
+          const ruleInfo = utils.getRuleInfo({ ast });
           assert(
             lodash.isMatch(ruleInfo, CASES[ruleSource]),
             `Expected \n${util.inspect(ruleInfo)}\nto match\n${util.inspect(CASES[ruleSource])}`
@@ -139,8 +139,8 @@ describe('utils', () => {
           isNewStyle: true,
         };
         it(`ScopeOptions: ${JSON.stringify(scopeOptions)}`, () => {
-          const scope = eslintScope.analyze(ast, scopeOptions);
-          const ruleInfo = utils.getRuleInfo(ast, scope);
+          const scopeManager = eslintScope.analyze(ast, scopeOptions);
+          const ruleInfo = utils.getRuleInfo({ ast, scopeManager });
           assert(
             lodash.isMatch(ruleInfo, expected),
             `Expected \n${util.inspect(ruleInfo)}\nto match\n${util.inspect(expected)}`