From 182e95da9208e1530a008861e4b12bf605257106 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 23 Oct 2021 14:42:37 -0700 Subject: [PATCH] [Fix] `destructuring-assignment`: detect refs nested in functions Fixes #3102 --- CHANGELOG.md | 2 + lib/rules/destructuring-assignment.js | 10 ++++- tests/lib/rules/destructuring-assignment.js | 50 +++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 210c136a82..1731915d1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,10 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel * [`jsx-props-no-multi-spaces`]: avoid a crash on long member chains in tag names in `typescript-eslint` parser (@ljharb) * [`no-unused-prop-types`], `usedPropTypes`: avoid crash with typescript-eslint parser (@ljharb) * [`display-name`]: unwrap TS `as` expressions ([#3110][] @ljharb) +* [`destructuring-assignment`]: detect refs nested in functions ([#3102] @ljharb) [#3110]: https://github.com/yannickcr/eslint-plugin-react/pull/3110 +[#3102]: https://github.com/yannickcr/eslint-plugin-react/issue/3102 [#3092]: https://github.com/yannickcr/eslint-plugin-react/pull/3092 [#2166]: https://github.com/yannickcr/eslint-plugin-react/pull/2166 [#1980]: https://github.com/yannickcr/eslint-plugin-react/pull/1980 diff --git a/lib/rules/destructuring-assignment.js b/lib/rules/destructuring-assignment.js index a30af53d7e..5d9687f402 100644 --- a/lib/rules/destructuring-assignment.js +++ b/lib/rules/destructuring-assignment.js @@ -182,11 +182,17 @@ module.exports = { 'FunctionExpression:exit': handleStatelessComponentExit, MemberExpression(node) { - const SFCComponent = components.get(context.getScope(node).block); - const classComponent = utils.getParentComponent(node); + let scope = context.getScope(node); + let SFCComponent = components.get(scope.block); + while (!SFCComponent && scope.upper && scope.upper !== scope) { + SFCComponent = components.get(scope.upper.block); + scope = scope.upper; + } if (SFCComponent) { handleSFCUsage(node); } + + const classComponent = utils.getParentComponent(node); if (classComponent) { handleClassUsage(node); } diff --git a/tests/lib/rules/destructuring-assignment.js b/tests/lib/rules/destructuring-assignment.js index fb0f08dc9e..6efae95582 100644 --- a/tests/lib/rules/destructuring-assignment.js +++ b/tests/lib/rules/destructuring-assignment.js @@ -529,6 +529,17 @@ ruleTester.run('destructuring-assignment', rule, { { messageId: 'useDestructAssignment', data: { type: 'props' }, + line: 5, + }, + { + messageId: 'useDestructAssignment', + data: { type: 'props' }, + line: 7, + }, + { + messageId: 'useDestructAssignment', + data: { type: 'props' }, + line: 8, }, ], }, @@ -565,5 +576,44 @@ ruleTester.run('destructuring-assignment', rule, { }, ], }, + { + code: ` + import React from 'react'; + + const TestComp = (props) => { + props.onClick3102(); + + return ( +
{ + if (props.onClick3102) { + props.onClick3102(evt); + } + }} + > +
+
+ ); + }; + `, + parser: parsers.BABEL_ESLINT, + errors: [ + { + messageId: 'useDestructAssignment', + data: { type: 'props' }, + line: 5, + }, + { + messageId: 'useDestructAssignment', + data: { type: 'props' }, + line: 10, + }, + { + messageId: 'useDestructAssignment', + data: { type: 'props' }, + line: 11, + }, + ], + }, ]), });