From f02e8aeee59d2dd08303d0b5776041a8ab860d48 Mon Sep 17 00:00:00 2001 From: toshi-toma Date: Tue, 24 Dec 2019 01:22:49 +0900 Subject: [PATCH] [Fix] `prop-types`: Does not validate missing propTypes for LogicalExpression --- lib/util/Components.js | 41 +++++++++++++++++++++++++---------- tests/lib/rules/prop-types.js | 28 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/lib/util/Components.js b/lib/util/Components.js index c4334c8c0f..515a39dd00 100644 --- a/lib/util/Components.js +++ b/lib/util/Components.js @@ -46,6 +46,30 @@ function mergeUsedPropTypes(propsList, newPropsList) { return propsList.concat(propsToAdd); } +function isReturnsConditionalJSX(node, property, strict) { + const returnsConditionalJSXConsequent = node[property] && + node[property].type === 'ConditionalExpression' && + jsxUtil.isJSX(node[property].consequent); + const returnsConditionalJSXAlternate = node[property] && + node[property].type === 'ConditionalExpression' && + jsxUtil.isJSX(node[property].alternate); + return strict ? + (returnsConditionalJSXConsequent && returnsConditionalJSXAlternate) : + (returnsConditionalJSXConsequent || returnsConditionalJSXAlternate); +} + +function isReturnsLogicalJSX(node, property, strict) { + const returnsLogicalJSXLeft = node[property] && + node[property].type === 'LogicalExpression' && + jsxUtil.isJSX(node[property].left); + const returnsLogicalJSXRight = node[property] && + node[property].type === 'LogicalExpression' && + jsxUtil.isJSX(node[property].right); + return strict ? + (returnsLogicalJSXLeft && returnsLogicalJSXRight) : + (returnsLogicalJSXLeft || returnsLogicalJSXRight); +} + const Lists = new WeakMap(); /** @@ -373,22 +397,15 @@ function componentRule(rule, context) { return false; } - const returnsConditionalJSXConsequent = node[property] && - node[property].type === 'ConditionalExpression' && - jsxUtil.isJSX(node[property].consequent); - const returnsConditionalJSXAlternate = node[property] && - node[property].type === 'ConditionalExpression' && - jsxUtil.isJSX(node[property].alternate); - const returnsConditionalJSX = strict ? - (returnsConditionalJSXConsequent && returnsConditionalJSXAlternate) : - (returnsConditionalJSXConsequent || returnsConditionalJSXAlternate); + const returnsConditionalJSX = isReturnsConditionalJSX(node, property, strict); + const returnsLogicalJSX = isReturnsLogicalJSX(node, property, strict); - const returnsJSX = node[property] && - jsxUtil.isJSX(node[property]); + const returnsJSX = node[property] && jsxUtil.isJSX(node[property]); const returnsPragmaCreateElement = this.isCreateElement(node[property]); - return Boolean( + return !!( returnsConditionalJSX || + returnsLogicalJSX || returnsJSX || returnsPragmaCreateElement ); diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js index b55fd6e0db..7f1ec41835 100755 --- a/tests/lib/rules/prop-types.js +++ b/tests/lib/rules/prop-types.js @@ -2465,6 +2465,19 @@ ruleTester.run('prop-types', rule, { pragma: 'Foo' } } + }, + { + code: ` + const Foo = ({length, ordering}) => ( + length > 0 && ( + + ) + ); + Foo.propTypes = { + length: PropTypes.number, + ordering: PropTypes.array + }; + ` } ], @@ -4895,6 +4908,21 @@ ruleTester.run('prop-types', rule, { errors: [{ message: '\'foo.baz\' is missing in props validation' }] + }, + { + code: ` + const Foo = ({length, ordering}) => ( + length > 0 && ( + + ) + ); + `, + errors: [{ + message: '\'length\' is missing in props validation' + }, + { + message: '\'ordering\' is missing in props validation' + }] } ] });