Skip to content

Commit 997a99f

Browse files
ajkovarljharb
andcommitted
[Fix] forbid-prop-types: warn on destructured values as well
Fixes #2662. Co-authored-by: Alex Kovar <ajkovar@gmail.com> Co-authored-by: Jordan Harband <ljharb@gmail.com>
1 parent a4025bd commit 997a99f

File tree

2 files changed

+104
-24
lines changed

2 files changed

+104
-24
lines changed

lib/rules/forbid-prop-types.js

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ module.exports = {
5959
return forbid.indexOf(type) >= 0;
6060
}
6161

62+
function reportIfForbidden(type, declaration, target) {
63+
if (isForbidden(type)) {
64+
context.report({
65+
node: declaration,
66+
message: `Prop type \`${target}\` is forbidden`
67+
});
68+
}
69+
}
70+
6271
function shouldCheckContextTypes(node) {
6372
if (checkContextTypes && propsUtil.isContextTypesDeclaration(node)) {
6473
return true;
@@ -93,23 +102,18 @@ module.exports = {
93102
) {
94103
value = value.object;
95104
}
96-
if (
97-
value.type === 'CallExpression'
98-
&& value.callee.type === 'MemberExpression'
99-
) {
105+
if (value.type === 'CallExpression') {
106+
value.arguments.forEach((arg) => {
107+
reportIfForbidden(arg.name, declaration, target);
108+
});
100109
value = value.callee;
101110
}
102111
if (value.property) {
103112
target = value.property.name;
104113
} else if (value.type === 'Identifier') {
105114
target = value.name;
106115
}
107-
if (isForbidden(target)) {
108-
context.report({
109-
node: declaration,
110-
message: `Prop type \`${target}\` is forbidden`
111-
});
112-
}
116+
reportIfForbidden(target, declaration, target);
113117
});
114118
}
115119

@@ -161,6 +165,15 @@ module.exports = {
161165
checkNode(node.parent.right);
162166
},
163167

168+
CallExpression(node) {
169+
if (
170+
node.arguments.length > 0
171+
&& (node.callee.name === 'shape' || astUtil.getPropertyName(node.callee) === 'shape')
172+
) {
173+
checkProperties(node.arguments[0].properties);
174+
}
175+
},
176+
164177
MethodDefinition(node) {
165178
if (
166179
!propsUtil.isPropTypesDeclaration(node)

tests/lib/rules/forbid-prop-types.js

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -572,20 +572,6 @@ ruleTester.run('forbid-prop-types', rule, {
572572
' preview: PropTypes.bool,',
573573
'}, componentApi, teaserListProps);'
574574
].join('\n')
575-
}, {
576-
code: [
577-
'var First = createReactClass({',
578-
' propTypes: {',
579-
' s: PropTypes.shape({',
580-
' o: PropTypes.object',
581-
' })',
582-
' },',
583-
' render: function() {',
584-
' return <div />;',
585-
' }',
586-
'});'
587-
].join('\n'),
588-
errors: 0 // TODO: fix #1673 and move this to "invalid"
589575
}],
590576

591577
invalid: [{
@@ -1460,5 +1446,86 @@ ruleTester.run('forbid-prop-types', rule, {
14601446
checkChildContextTypes: true
14611447
}],
14621448
errors: 1
1449+
}, {
1450+
code: [
1451+
'import { object, string } from "prop-types";',
1452+
'function C({ a, b }) { return [a, b]; }',
1453+
'C.propTypes = {',
1454+
' a: object,',
1455+
' b: string',
1456+
'};'
1457+
].join('\n'),
1458+
options: [{
1459+
forbid: ['object']
1460+
}],
1461+
errors: 1
1462+
}, {
1463+
code: [
1464+
'import { objectOf, any } from "prop-types";',
1465+
'function C({ a }) { return a; }',
1466+
'C.propTypes = {',
1467+
' a: objectOf(any)',
1468+
'};'
1469+
].join('\n'),
1470+
options: [{
1471+
forbid: ['any']
1472+
}],
1473+
errors: 1
1474+
}, {
1475+
code: [
1476+
'import { objectOf, any } from "prop-types";',
1477+
'function C({ a }) { return a; }',
1478+
'C.propTypes = {',
1479+
' a: objectOf(any)',
1480+
'};'
1481+
].join('\n'),
1482+
options: [{
1483+
forbid: ['objectOf']
1484+
}],
1485+
errors: 1
1486+
},
1487+
{
1488+
code: [
1489+
'import { shape, any } from "prop-types";',
1490+
'function C({ a }) { return a; }',
1491+
'C.propTypes = {',
1492+
' a: shape({',
1493+
' b: any',
1494+
' })',
1495+
'};'
1496+
].join('\n'),
1497+
options: [{
1498+
forbid: ['any']
1499+
}],
1500+
errors: 1
1501+
},
1502+
{
1503+
code: [
1504+
'import { any } from "prop-types";',
1505+
'function C({ a }) { return a; }',
1506+
'C.propTypes = {',
1507+
' a: PropTypes.shape({',
1508+
' b: any',
1509+
' })',
1510+
'};'
1511+
].join('\n'),
1512+
options: [{
1513+
forbid: ['any']
1514+
}],
1515+
errors: 1
1516+
}, {
1517+
code: [
1518+
'var First = createReactClass({',
1519+
' propTypes: {',
1520+
' s: PropTypes.shape({',
1521+
' o: PropTypes.object',
1522+
' })',
1523+
' },',
1524+
' render: function() {',
1525+
' return <div />;',
1526+
' }',
1527+
'});'
1528+
].join('\n'),
1529+
errors: 1
14631530
}]
14641531
});

0 commit comments

Comments
 (0)