Repository: facebook/react
Pull request: react-hooks/rules-of-hooks: detect issues in class properties

## Summary

This is a revival of the PR initially added by @ecraig12345 (https://github.com/facebook/react/pull/27435) to fix a recent change in the AST used by ESLint to represent class properties.

## How did you test this change?

Ran `yarn test packages/eslint-plugin-react-hooks` and `yarn test --prod packages/eslint-plugin-react-hooks`.

Changed files:
filename: packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js
patch: @@ -8300,6 +8300,7 @@ describe('rules-of-hooks/exhaustive-deps', () => {
     ecmaVersion: 6,
     sourceType: 'module',
   };
+
   const languageOptionsV9 = {
     ecmaVersion: 6,
     sourceType: 'module',
@@ -8442,7 +8443,7 @@ describe('rules-of-hooks/exhaustive-deps', () => {
       parser: require('@typescript-eslint/parser-v5'),
     },
   }).run(
-    'eslint: v9, parser: @typescript-eslint/parser@^5.0.0-0',
+    'eslint: v9, parser: @typescript-eslint/parser@^5.0.0',
     ReactHooksESLintRule,
     {
       valid: [

filename: packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js
patch: @@ -12,7 +12,6 @@
 const ESLintTesterV7 = require('eslint-v7').RuleTester;
 const ESLintTesterV9 = require('eslint-v9').RuleTester;
 const ReactHooksESLintPlugin = require('eslint-plugin-react-hooks');
-const BabelEslintParser = require('@babel/eslint-parser');
 const ReactHooksESLintRule = ReactHooksESLintPlugin.rules['rules-of-hooks'];
 
 /**
@@ -1561,19 +1560,117 @@ if (!process.env.CI) {
 }
 
 describe('rules-of-hooks/rules-of-hooks', () => {
-  new ESLintTesterV7({
-    parser: require.resolve('babel-eslint'),
+  const parserOptionsV7 = {
+    ecmaFeatures: {
+      jsx: true,
+    },
+    ecmaVersion: 6,
+    sourceType: 'module',
+  };
+
+  const languageOptionsV9 = {
+    ecmaVersion: 6,
+    sourceType: 'module',
     parserOptions: {
-      ecmaVersion: 6,
-      sourceType: 'module',
+      ecmaFeatures: {
+        jsx: true,
+      },
     },
-  }).run('eslint: v7', ReactHooksESLintRule, tests);
+  };
+
+  new ESLintTesterV7({
+    parser: require.resolve('babel-eslint'),
+    parserOptions: parserOptionsV7,
+  }).run('eslint: v7, parser: babel-eslint', ReactHooksESLintRule, tests);
 
   new ESLintTesterV9({
     languageOptions: {
-      parser: BabelEslintParser,
-      ecmaVersion: 6,
-      sourceType: 'module',
-    },
-  }).run('eslint: v9', ReactHooksESLintRule, tests);
+      ...languageOptionsV9,
+      parser: require('@babel/eslint-parser'),
+    },
+  }).run(
+    'eslint: v9, parser: @babel/eslint-parser',
+    ReactHooksESLintRule,
+    tests
+  );
+
+  new ESLintTesterV7({
+    parser: require.resolve('@typescript-eslint/parser-v2'),
+    parserOptions: parserOptionsV7,
+  }).run(
+    'eslint: v7, parser: @typescript-eslint/parser@2.x',
+    ReactHooksESLintRule,
+    tests
+  );
+
+  new ESLintTesterV9({
+    languageOptions: {
+      ...languageOptionsV9,
+      parser: require('@typescript-eslint/parser-v2'),
+    },
+  }).run(
+    'eslint: v9, parser: @typescript-eslint/parser@2.x',
+    ReactHooksESLintRule,
+    tests
+  );
+
+  new ESLintTesterV7({
+    parser: require.resolve('@typescript-eslint/parser-v3'),
+    parserOptions: parserOptionsV7,
+  }).run(
+    'eslint: v7, parser: @typescript-eslint/parser@3.x',
+    ReactHooksESLintRule,
+    tests
+  );
+
+  new ESLintTesterV9({
+    languageOptions: {
+      ...languageOptionsV9,
+      parser: require('@typescript-eslint/parser-v3'),
+    },
+  }).run(
+    'eslint: v9, parser: @typescript-eslint/parser@3.x',
+    ReactHooksESLintRule,
+    tests
+  );
+
+  new ESLintTesterV7({
+    parser: require.resolve('@typescript-eslint/parser-v4'),
+    parserOptions: parserOptionsV7,
+  }).run(
+    'eslint: v7, parser: @typescript-eslint/parser@4.x',
+    ReactHooksESLintRule,
+    tests
+  );
+
+  new ESLintTesterV9({
+    languageOptions: {
+      ...languageOptionsV9,
+      parser: require('@typescript-eslint/parser-v4'),
+    },
+  }).run(
+    'eslint: v9, parser: @typescript-eslint/parser@4.x',
+    ReactHooksESLintRule,
+    tests
+  );
+
+  new ESLintTesterV7({
+    parser: require.resolve('@typescript-eslint/parser-v5'),
+    parserOptions: parserOptionsV7,
+  }).run(
+    'eslint: v7, parser: @typescript-eslint/parser@^5.0.0-0',
+    ReactHooksESLintRule,
+    tests
+  );
+
+  new ESLintTesterV9({
+    languageOptions: {
+      ...languageOptionsV9,
+      parser: require('@typescript-eslint/parser-v5'),
+    },
+  }).run(
+    'eslint: v9, parser: @typescript-eslint/parser@^5.0.0',
+    ReactHooksESLintRule,
+    tests
+  );
 });

filename: packages/eslint-plugin-react-hooks/package.json
patch: @@ -35,7 +35,7 @@
     "@typescript-eslint/parser-v2": "npm:@typescript-eslint/parser@^2.26.0",
     "@typescript-eslint/parser-v3": "npm:@typescript-eslint/parser@^3.10.0",
     "@typescript-eslint/parser-v4": "npm:@typescript-eslint/parser@^4.1.0",
-    "@typescript-eslint/parser-v5": "npm:@typescript-eslint/parser@^5.0.0-0",
+    "@typescript-eslint/parser-v5": "npm:@typescript-eslint/parser@^5.62.0",
     "babel-eslint": "^10.0.3",
     "eslint-v7": "npm:eslint@^7.7.0",
     "eslint-v9": "npm:eslint@^9.0.0"

filename: packages/eslint-plugin-react-hooks/src/RulesOfHooks.js
patch: @@ -549,7 +549,8 @@ export default {
             } else if (
               codePathNode.parent &&
               (codePathNode.parent.type === 'MethodDefinition' ||
-                codePathNode.parent.type === 'ClassProperty') &&
+                codePathNode.parent.type === 'ClassProperty' ||
+                codePathNode.parent.type === 'PropertyDefinition') &&
               codePathNode.parent.value === codePathNode
             ) {
               // Custom message for hooks inside a class

filename: yarn.lock
patch: @@ -3536,15 +3536,15 @@
     "@typescript-eslint/typescript-estree" "4.1.0"
     debug "^4.1.1"
 
-"@typescript-eslint/parser-v5@npm:@typescript-eslint/parser@^5.0.0-0":
-  version "5.0.0-alpha.25"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.0.0-alpha.25.tgz#d966eb8b2cf97f0134a5589791017e0a720bb995"
-  integrity sha512-e0Q2fWVXle8l9pCCV2K/pQrn0Wyp8nV/Gp8AbEUqP6xLfgrOxejzcERP9y5x1rnwrp7pPXZhticsNLjqljhh6w==
-  dependencies:
-    "@typescript-eslint/scope-manager" "5.0.0-alpha.25+faf2d1d2"
-    "@typescript-eslint/types" "5.0.0-alpha.25+faf2d1d2"
-    "@typescript-eslint/typescript-estree" "5.0.0-alpha.25+faf2d1d2"
-    debug "^4.3.1"
+"@typescript-eslint/parser-v5@npm:@typescript-eslint/parser@^5.62.0":
+  version "5.62.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7"
+  integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==
+  dependencies:
+    "@typescript-eslint/scope-manager" "5.62.0"
+    "@typescript-eslint/types" "5.62.0"
+    "@typescript-eslint/typescript-estree" "5.62.0"
+    debug "^4.3.4"
 
 "@typescript-eslint/scope-manager@4.1.0":
   version "4.1.0"
@@ -3554,13 +3554,13 @@
     "@typescript-eslint/types" "4.1.0"
     "@typescript-eslint/visitor-keys" "4.1.0"
 
-"@typescript-eslint/scope-manager@5.0.0-alpha.25+faf2d1d2":
-  version "5.0.0-alpha.25"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.0.0-alpha.25.tgz#eb90cb682f6a3a14ba9afc4bd7c1f66cf362e1b0"
-  integrity sha512-tZumo5HziFbOI+unwQ7Xgimn4FHltg20TCxVCU2tl7YyFhiQl1WxnmhU7/1MUNWXzK9RA88MRKvUON1lgK1FLw==
+"@typescript-eslint/scope-manager@5.62.0":
+  version "5.62.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz#d9457ccc6a0b8d6b37d0eb252a23022478c5460c"
+  integrity sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==
   dependencies:
-    "@typescript-eslint/types" "5.0.0-alpha.25+faf2d1d2"
-    "@typescript-eslint/visitor-keys" "5.0.0-alpha.25+faf2d1d2"
+    "@typescript-eslint/types" "5.62.0"
+    "@typescript-eslint/visitor-keys" "5.62.0"
 
 "@typescript-eslint/scope-manager@6.21.0":
   version "6.21.0"
@@ -3580,10 +3580,10 @@
   resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.1.0.tgz#edbd3fec346f34e13ce7aa176b03b497a32c496a"
   integrity sha512-rkBqWsO7m01XckP9R2YHVN8mySOKKY2cophGM8K5uDK89ArCgahItQYdbg/3n8xMxzu2elss+an1TphlUpDuJw==
 
-"@typescript-eslint/types@5.0.0-alpha.25+faf2d1d2":
-  version "5.0.0-alpha.25"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.0.0-alpha.25.tgz#2c5aaaee8d41d08fbb91193cc6df482374700b2e"
-  integrity sha512-M9PZ+m1vD+UaBt+9hJ1bXTA94s4fvY3fOQkwYxrtreqqdzaiNcW8F5GAO3dthzmS+6II+XAsWfCQzCoBvoiOrw==
+"@typescript-eslint/types@5.62.0":
+  version "5.62.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f"
+  integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==
 
 "@typescript-eslint/types@6.21.0":
   version "6.21.0"
@@ -3631,17 +3631,17 @@
     semver "^7.3.2"
     tsutils "^3.17.1"
 
-"@typescript-eslint/typescript-estree@5.0.0-alpha.25+faf2d1d2":
-  version "5.0.0-alpha.25"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.0.0-alpha.25.tgz#1e9ad3464c93fffb1b17d8cc3e2523ae6add930b"
-  integrity sha512-EIEX4TSWGIBBi9DMZd8FZoI52Ua6hkHj2T8ah83BEBVMS9wCJDZyryuw0PHTesA2ZB5yiQbtNQrrODLJxz1hAw==
+"@typescript-eslint/typescript-estree@5.62.0":
+  version "5.62.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz#7d17794b77fabcac615d6a48fb143330d962eb9b"
+  integrity sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==
   dependencies:
-    "@typescript-eslint/types" "5.0.0-alpha.25+faf2d1d2"
-    "@typescript-eslint/visitor-keys" "5.0.0-alpha.25+faf2d1d2"
-    debug "^4.3.1"
-    globby "^11.0.3"
-    is-glob "^4.0.1"
-    semver "^7.3.5"
+    "@typescript-eslint/types" "5.62.0"
+    "@typescript-eslint/visitor-keys" "5.62.0"
+    debug "^4.3.4"
+    globby "^11.1.0"
+    is-glob "^4.0.3"
+    semver "^7.3.7"
     tsutils "^3.21.0"
 
 "@typescript-eslint/typescript-estree@6.21.0":
@@ -3686,13 +3686,13 @@
     "@typescript-eslint/types" "4.1.0"
     eslint-visitor-keys "^2.0.0"
 
-"@typescript-eslint/visitor-keys@5.0.0-alpha.25+faf2d1d2":
-  version "5.0.0-alpha.25"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.0.0-alpha.25.tgz#0b4a909d4020094e638dee1ff72e12d24783c94b"
-  integrity sha512-vh5AIlr3wxkhFMreop5Y1Wi5Sc9oK03J8+SiyKMEEAqwWmk6e2ryHr1001oWRuK4e6d/CjVNa73omERCWcTXTg==
+"@typescript-eslint/visitor-keys@5.62.0":
+  version "5.62.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz#2174011917ce582875954ffe2f6912d5931e353e"
+  integrity sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==
   dependencies:
-    "@typescript-eslint/types" "5.0.0-alpha.25+faf2d1d2"
-    eslint-visitor-keys "^3.0.0"
+    "@typescript-eslint/types" "5.62.0"
+    eslint-visitor-keys "^3.3.0"
 
 "@typescript-eslint/visitor-keys@6.21.0":
   version "6.21.0"
@@ -7522,11 +7522,6 @@ eslint-visitor-keys@^2.0.0:
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
   integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
 
-eslint-visitor-keys@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186"
-  integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==
-
 eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3:
   version "3.4.3"
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"