Repository: eslint-community/eslint-plugin-eslint-plugin (js)

Issue:
New false positives in 5.4.0 for functions that aren't ESLint rules
https://github.com/typescript-eslint/typescript-eslint/pull/8574 attempts to upgrade `eslint-plugin-eslint-plugin` from [5.3.0 -> 5.4.0](https://renovatebot.com/diffs/npm/eslint-plugin-eslint-plugin/5.3.0/5.4.0). It has the following new failures:

```plaintext
/home/runner/work/typescript-eslint/typescript-eslint/packages/eslint-plugin/tests/RuleTester.ts
  43:8  error  `meta.messages` must contain at least one violation message                    eslint-plugin/prefer-message-ids
  43:8  error  Rules should be declared using the object style                                eslint-plugin/prefer-object-rule
  43:8  error  `meta.type` is required (must be either `problem`, `suggestion`, or `layout`)  eslint-plugin/require-meta-type
  43:8  error  `meta.schema` is required (use [] if rule has no schema)                       eslint-plugin/require-meta-schema

/home/runner/work/typescript-eslint/typescript-eslint/packages/eslint-plugin/tests/rules/naming-convention/cases/createTestCases.ts
  85:8  error  `meta.messages` must contain at least one violation message                    eslint-plugin/prefer-message-ids
  85:8  error  Rules should be declared using the object style                                eslint-plugin/prefer-object-rule
  85:8  error  `meta.type` is required (must be either `problem`, `suggestion`, or `layout`)  eslint-plugin/require-meta-type
  85:8  error  `meta.schema` is required (use [] if rule has no schema)                       eslint-plugin/require-meta-schema

/home/runner/work/typescript-eslint/typescript-eslint/packages/eslint-plugin/tests/rules/prefer-optional-chain/base-cases.ts
  232:43  error  `meta.messages` must contain at least one violation message                    eslint-plugin/prefer-message-ids
  232:43  error  Rules should be declared using the object style                                eslint-plugin/prefer-object-rule
  232:43  error  `meta.type` is required (must be either `problem`, `suggestion`, or `layout`)  eslint-plugin/require-meta-type
  232:43  error  `meta.schema` is required (use [] if rule has no schema)                       eslint-plugin/require-meta-schema
```

None of those three flagged code constructs should be reported on:

* `tests/RuleTester.ts`: `export function batchedSingleLineTests`
* `naming-convention/cases/createTestCases.ts`: `export function createTestCases(cases: Cases): void {`
* `prefer-optional-chain/base-cases.ts`: `export const BaseCases: BaseCaseCreator = ({`

It looks like the detection for what is an ESLint rule might be overly permissive?

Pull request description:
fix: false positives in 5.4.0 for functions that aren't ESLint rules
fixes #450

To make the ci happy:
* updated eslint-remote-tester config
* upgraded eslint-doc-generator

Patch:
diff --git a/README.md b/README.md
index 2e95af1..908c2ad 100644
--- a/README.md
+++ b/README.md
@@ -79,8 +79,8 @@ module.exports = [
 💼 [Configurations](https://github.com/eslint-community/eslint-plugin-eslint-plugin#presets) enabled in.\
 ✅ Set in the `recommended` [configuration](https://github.com/eslint-community/eslint-plugin-eslint-plugin#presets).\
 🔧 Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\
-💡 Manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).\
-💭 Requires type information.
+💡 Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).\
+💭 Requires [type information](https://typescript-eslint.io/linting/typed-linting).
 
 ### Rules
 
diff --git a/docs/rules/no-property-in-node.md b/docs/rules/no-property-in-node.md
index 22da26d..1a44c31 100644
--- a/docs/rules/no-property-in-node.md
+++ b/docs/rules/no-property-in-node.md
@@ -1,6 +1,6 @@
 # Disallow using `in` to narrow node types instead of looking at properties (`eslint-plugin/no-property-in-node`)
 
-💭 This rule requires type information.
+💭 This rule requires [type information](https://typescript-eslint.io/linting/typed-linting).
 
 <!-- end auto-generated rule header -->
 
diff --git a/docs/rules/require-meta-schema.md b/docs/rules/require-meta-schema.md
index de1b682..c479d25 100644
--- a/docs/rules/require-meta-schema.md
+++ b/docs/rules/require-meta-schema.md
@@ -2,7 +2,7 @@
 
 💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/eslint-community/eslint-plugin-eslint-plugin#presets).
 
-💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
+💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
 
 <!-- end auto-generated rule header -->
 
diff --git a/lib/utils.js b/lib/utils.js
index da5faa7..ae708f8 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -139,15 +139,24 @@ function getRuleExportsESM(ast, scopeManager) {
           possibleNodes.push(specifier.local);
         }
         if (statement.declaration) {
-          if (statement.declaration.type === 'VariableDeclaration') {
-            for (const declarator of statement.declaration.declarations) {
-              if (declarator.init) {
-                possibleNodes.push(declarator.init);
-              }
-            }
-          } else {
-            possibleNodes.push(statement.declaration);
-          }
+          const nodes =
+            statement.declaration.type === 'VariableDeclaration'
+              ? statement.declaration.declarations.map(
+                  (declarator) => declarator.init
+                )
+              : [statement.declaration];
+
+          // named exports like `export const rule = { ... };`
+          // skip if it's function-style to avoid false positives
+          // refs: https://github.com/eslint-community/eslint-plugin-eslint-plugin/issues/450
+          possibleNodes.push(
+            ...nodes.filter(
+              (node) =>
+                node &&
+                node.type !== 'FunctionDeclaration' &&
+                node.type !== 'FunctionExpression'
+            )
+          );
         }
         break;
       }
diff --git a/package.json b/package.json
index 792a8c9..51511b3 100644
--- a/package.json
+++ b/package.json
@@ -64,14 +64,14 @@
     "eslint": "^8.23.0",
     "eslint-config-not-an-aardvark": "^2.1.0",
     "eslint-config-prettier": "^8.5.0",
-    "eslint-doc-generator": "^1.6.1",
+    "eslint-doc-generator": "^1.7.0",
     "eslint-plugin-eslint-comments": "^3.2.0",
     "eslint-plugin-eslint-plugin": "file:./",
     "eslint-plugin-markdown": "^3.0.0",
     "eslint-plugin-n": "^16.6.2",
     "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-unicorn": "^46.0.0",
-    "eslint-remote-tester": "^3.0.0",
+    "eslint-remote-tester": "^3.0.1",
     "eslint-scope": "^7.1.1",
     "espree": "^9.4.0",
     "globals": "^13.20.0",


Test patch:
diff --git a/docs/rules/no-only-tests.md b/docs/rules/no-only-tests.md
index d5db7dd..3e8828c 100644
--- a/docs/rules/no-only-tests.md
+++ b/docs/rules/no-only-tests.md
@@ -2,7 +2,7 @@
 
 💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/eslint-community/eslint-plugin-eslint-plugin#presets).
 
-💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
+💡 This rule is manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions).
 
 <!-- end auto-generated rule header -->
 
diff --git a/eslint-remote-tester.config.js b/eslint-remote-tester.config.js
index f9d44f6..daf0601 100644
--- a/eslint-remote-tester.config.js
+++ b/eslint-remote-tester.config.js
@@ -41,10 +41,13 @@ module.exports = {
   /** Optional boolean flag used to enable caching of cloned repositories. For CIs it's ideal to disable caching. Defaults to true. */
   cache: false,
 
+  pathIgnorePattern: 'fixtures',
+
   /** ESLint configuration */
   eslintrc: {
+    root: true,
     extends: ['plugin:eslint-plugin/all'],
-
+    // ignorePatterns: ['fixtures/**/*'],  // not working somehow - using `pathIgnorePattern` as of now.
     overrides: [
       {
         files: ['*.ts', '*.mts', '*.cts'],
diff --git a/tests/lib/utils.js b/tests/lib/utils.js
index e90ecd6..0e8c83e 100644
--- a/tests/lib/utils.js
+++ b/tests/lib/utils.js
@@ -86,6 +86,14 @@ describe('utils', () => {
         'export default function () { return {}; }',
         'export default function (foo, bar) { return {}; }',
 
+        // named export of functions
+        // refs: https://github.com/eslint-community/eslint-plugin-eslint-plugin/issues/450
+        'export function foo(options) { return {}; }',
+        'export async function foo(options) { return {}; }',
+        'export const foo = function (options) { return {}; }',
+        'export function foo(options) { return; }',
+        'export function foo({opt1, opt2}) { return {}; }',
+
         // Incorrect TypeScript helper structure:
         'export default foo()({ create() {}, meta: {} });',
         'export default foo().bar({ create() {}, meta: {} });',