Skip to content

Commit a98fa94

Browse files
committed
Fix scope limit for stateless component detection (fixes #268)
1 parent 1a5143a commit a98fa94

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

lib/rules/prop-types.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,10 +417,13 @@ module.exports = Components.detect(function(context, components) {
417417
if (Object.prototype[name]) {
418418
break;
419419
}
420+
421+
var isDirectProp = /^props\./.test(context.getSource(node));
422+
420423
usedPropTypes.push({
421424
name: name,
422425
allNames: allNames,
423-
node: node.object.name !== 'props' && !inConstructor() ? node.parent.property : node.property
426+
node: !isDirectProp && !inConstructor(node) ? node.parent.property : node.property
424427
});
425428
break;
426429
case 'destructuring':

lib/util/Components.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,17 @@ function componentRule(rule, context) {
202202
*/
203203
getParentStatelessComponent: function() {
204204
var scope = context.getScope();
205-
var node = scope.block;
206-
var isNotAFunction = !/Function/.test(node.type); // Ignore non functions
207-
var isMethod = node.parent && node.parent.type === 'MethodDefinition'; // Ignore classes methods
208-
var isArgument = node.parent && node.parent.type === 'CallExpression'; // Ignore arguments (map, callback, etc.)
209-
if (isNotAFunction || isMethod || isArgument) {
210-
return null;
205+
while (scope) {
206+
var node = scope.block;
207+
var isFunction = /Function/.test(node.type); // Ignore non functions
208+
var isNotMethod = !node.parent || node.parent.type !== 'MethodDefinition'; // Ignore classes methods
209+
var isNotArgument = !node.parent || node.parent.type !== 'CallExpression'; // Ignore arguments (callback, etc.)
210+
if (isFunction && isNotMethod && isNotArgument) {
211+
return node;
212+
}
213+
scope = scope.upper;
211214
}
212-
return node;
215+
return null;
213216
},
214217

215218
/**

tests/lib/rules/prop-types.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,20 @@ ruleTester.run('prop-types', rule, {
869869
'};'
870870
].join('\n'),
871871
parser: 'babel-eslint'
872+
}, {
873+
code: [
874+
'const Hello = (props) => {',
875+
' let team = props.names.map((name) => {',
876+
' return <li>{name}, {props.company}</li>;',
877+
' });',
878+
' return <ul>{team}</ul>;',
879+
'};',
880+
'Hello.propTypes = {',
881+
' names: React.PropTypes.array,',
882+
' company: React.PropTypes.string',
883+
'};'
884+
].join('\n'),
885+
parser: 'babel-eslint'
872886
}
873887
],
874888

@@ -1430,6 +1444,21 @@ ruleTester.run('prop-types', rule, {
14301444
{message: '\'firstname\' is missing in props validation'},
14311445
{message: '\'name\' is missing in props validation'}
14321446
]
1447+
}, {
1448+
code: [
1449+
'const Hello = (props) => {',
1450+
' let team = props.names.map((name) => {',
1451+
' return <li>{name}, {props.company}</li>;',
1452+
' });',
1453+
' return <ul>{team}</ul>;',
1454+
'};'
1455+
].join('\n'),
1456+
parser: 'babel-eslint',
1457+
errors: [
1458+
{message: '\'names\' is missing in props validation'},
1459+
{message: '\'names.map\' is missing in props validation'},
1460+
{message: '\'company\' is missing in props validation'}
1461+
]
14331462
}
14341463
]
14351464
});

0 commit comments

Comments
 (0)