From 997a99f389a7df9673de890d71a17e2b6838f72b Mon Sep 17 00:00:00 2001 From: Alex Kovar Date: Tue, 16 Jun 2020 00:02:15 -0500 Subject: [PATCH] [Fix] `forbid-prop-types`: warn on destructured values as well Fixes #2662. Co-authored-by: Alex Kovar Co-authored-by: Jordan Harband --- lib/rules/forbid-prop-types.js | 33 +++++++--- tests/lib/rules/forbid-prop-types.js | 95 ++++++++++++++++++++++++---- 2 files changed, 104 insertions(+), 24 deletions(-) diff --git a/lib/rules/forbid-prop-types.js b/lib/rules/forbid-prop-types.js index a5bc7a4b02..55416ee667 100644 --- a/lib/rules/forbid-prop-types.js +++ b/lib/rules/forbid-prop-types.js @@ -59,6 +59,15 @@ module.exports = { return forbid.indexOf(type) >= 0; } + function reportIfForbidden(type, declaration, target) { + if (isForbidden(type)) { + context.report({ + node: declaration, + message: `Prop type \`${target}\` is forbidden` + }); + } + } + function shouldCheckContextTypes(node) { if (checkContextTypes && propsUtil.isContextTypesDeclaration(node)) { return true; @@ -93,10 +102,10 @@ module.exports = { ) { value = value.object; } - if ( - value.type === 'CallExpression' - && value.callee.type === 'MemberExpression' - ) { + if (value.type === 'CallExpression') { + value.arguments.forEach((arg) => { + reportIfForbidden(arg.name, declaration, target); + }); value = value.callee; } if (value.property) { @@ -104,12 +113,7 @@ module.exports = { } else if (value.type === 'Identifier') { target = value.name; } - if (isForbidden(target)) { - context.report({ - node: declaration, - message: `Prop type \`${target}\` is forbidden` - }); - } + reportIfForbidden(target, declaration, target); }); } @@ -161,6 +165,15 @@ module.exports = { checkNode(node.parent.right); }, + CallExpression(node) { + if ( + node.arguments.length > 0 + && (node.callee.name === 'shape' || astUtil.getPropertyName(node.callee) === 'shape') + ) { + checkProperties(node.arguments[0].properties); + } + }, + MethodDefinition(node) { if ( !propsUtil.isPropTypesDeclaration(node) diff --git a/tests/lib/rules/forbid-prop-types.js b/tests/lib/rules/forbid-prop-types.js index aa48f1401a..e8d90819eb 100644 --- a/tests/lib/rules/forbid-prop-types.js +++ b/tests/lib/rules/forbid-prop-types.js @@ -572,20 +572,6 @@ ruleTester.run('forbid-prop-types', rule, { ' preview: PropTypes.bool,', '}, componentApi, teaserListProps);' ].join('\n') - }, { - code: [ - 'var First = createReactClass({', - ' propTypes: {', - ' s: PropTypes.shape({', - ' o: PropTypes.object', - ' })', - ' },', - ' render: function() {', - ' return
;', - ' }', - '});' - ].join('\n'), - errors: 0 // TODO: fix #1673 and move this to "invalid" }], invalid: [{ @@ -1460,5 +1446,86 @@ ruleTester.run('forbid-prop-types', rule, { checkChildContextTypes: true }], errors: 1 + }, { + code: [ + 'import { object, string } from "prop-types";', + 'function C({ a, b }) { return [a, b]; }', + 'C.propTypes = {', + ' a: object,', + ' b: string', + '};' + ].join('\n'), + options: [{ + forbid: ['object'] + }], + errors: 1 + }, { + code: [ + 'import { objectOf, any } from "prop-types";', + 'function C({ a }) { return a; }', + 'C.propTypes = {', + ' a: objectOf(any)', + '};' + ].join('\n'), + options: [{ + forbid: ['any'] + }], + errors: 1 + }, { + code: [ + 'import { objectOf, any } from "prop-types";', + 'function C({ a }) { return a; }', + 'C.propTypes = {', + ' a: objectOf(any)', + '};' + ].join('\n'), + options: [{ + forbid: ['objectOf'] + }], + errors: 1 + }, + { + code: [ + 'import { shape, any } from "prop-types";', + 'function C({ a }) { return a; }', + 'C.propTypes = {', + ' a: shape({', + ' b: any', + ' })', + '};' + ].join('\n'), + options: [{ + forbid: ['any'] + }], + errors: 1 + }, + { + code: [ + 'import { any } from "prop-types";', + 'function C({ a }) { return a; }', + 'C.propTypes = {', + ' a: PropTypes.shape({', + ' b: any', + ' })', + '};' + ].join('\n'), + options: [{ + forbid: ['any'] + }], + errors: 1 + }, { + code: [ + 'var First = createReactClass({', + ' propTypes: {', + ' s: PropTypes.shape({', + ' o: PropTypes.object', + ' })', + ' },', + ' render: function() {', + ' return
;', + ' }', + '});' + ].join('\n'), + errors: 1 }] });