From 1cca82fcc765d1289b580ebc0a4a3bc17bd5ae2a Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 3 Feb 2022 13:58:55 -0800 Subject: [PATCH] [Fix] `prop-types`/`propTypes`: follow a returned identifier to see if it is JSX Fixes #1046 --- CHANGELOG.md | 2 ++ lib/util/jsx.js | 11 ++++++++++- tests/lib/rules/prop-types.js | 27 +++++++++++++++++++++++++++ tests/util/jsx.js | 11 ++++++++++- 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 944a9f1472..f8b7f6a127 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange * `propTypes`: Handle TSTypeReference in no-unused-prop-type ([#3195][] @niik) * [`sort-prop-types`]: avoid repeated warnings of the same node/reason ([#519][] @ljharb) * [`jsx-indent`]: Fix indent handling for closing parentheses ([#620][] @stefanbuck]) +* [`prop-types`/`propTypes`]: follow a returned identifier to see if it is JSX ([#1046][] @ljharb) ### Changed * [readme] change [`jsx-runtime`] link from branch to sha ([#3160][] @tatsushitoji) @@ -41,6 +42,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange [#3133]: https://github.com/yannickcr/eslint-plugin-react/pull/3133 [#2921]: https://github.com/yannickcr/eslint-plugin-react/pull/2921 [#2753]: https://github.com/yannickcr/eslint-plugin-react/pull/2753 +[#1046]: https://github.com/yannickcr/eslint-plugin-react/issues/1046 [#620]: https://github.com/yannickcr/eslint-plugin-react/pull/620 [#519]: https://github.com/yannickcr/eslint-plugin-react/issues/519 diff --git a/lib/util/jsx.js b/lib/util/jsx.js index 8e84b05d43..e7ae2357d7 100644 --- a/lib/util/jsx.js +++ b/lib/util/jsx.js @@ -8,6 +8,7 @@ const estraverse = require('estraverse'); const elementType = require('jsx-ast-utils/elementType'); const astUtil = require('./ast'); +const variableUtil = require('./variable'); // See https://github.com/babel/babel/blob/ce420ba51c68591e057696ef43e028f41c6e04cd/packages/babel-types/src/validators/react/isCompatTag.js // for why we only test for the first character @@ -125,7 +126,8 @@ function isReturningJSX(isCreateElement, ASTnode, context, strict, ignoreNull) { break; case 'JSXElement': case 'JSXFragment': - setFound(); break; + setFound(); + break; case 'CallExpression': if (isCreateElement(childNode)) { setFound(); @@ -137,6 +139,13 @@ function isReturningJSX(isCreateElement, ASTnode, context, strict, ignoreNull) { setFound(); } break; + case 'Identifier': { + const variable = variableUtil.findVariableByName(context, childNode.name); + if (isJSX(variable)) { + setFound(); + } + break; + } default: } }, diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js index eba83ebfba..26259d43d0 100644 --- a/tests/lib/rules/prop-types.js +++ b/tests/lib/rules/prop-types.js @@ -7624,6 +7624,33 @@ ruleTester.run('prop-types', rule, { }, ], features: ['ts', 'no-babel'], + }, + { + code: ` + const Foo = ({ foo }) => { + return ; + } + `, + errors: [ + { + messageId: 'missingPropType', + data: { name: 'foo' }, + }, + ], + }, + { + code: ` + const Foo = ({ foo }) => { + const returnValue = ; + return returnValue; + } + `, + errors: [ + { + messageId: 'missingPropType', + data: { name: 'foo' }, + }, + ], } )), }); diff --git a/tests/util/jsx.js b/tests/util/jsx.js index b06ea70c1f..6aef83e0a4 100644 --- a/tests/util/jsx.js +++ b/tests/util/jsx.js @@ -20,7 +20,16 @@ const parseCode = (code) => { return ASTnode.body[0]; }; -const mockContext = {}; +const mockContext = { + getScope() { + return { + type: 'global', + upper: null, + childScopes: [], + variables: [], + }; + }, +}; describe('jsxUtil', () => { describe('isReturningJSX', () => {