Skip to content

Commit 7cd9b39

Browse files
committed
Fix props validation in constructor (fixes #254)
1 parent eb985f5 commit 7cd9b39

File tree

2 files changed

+60
-2
lines changed

2 files changed

+60
-2
lines changed

lib/rules/prop-types.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,31 @@ module.exports = function(context) {
307307
return true;
308308
}
309309

310+
/**
311+
* Check if we are in a class constructor
312+
* @return {boolean} true if we are in a class constructor, false if not
313+
*/
314+
function inConstructor() {
315+
var scope = context.getScope();
316+
while (scope) {
317+
if (scope.block && scope.block.parent && scope.block.parent.kind === 'constructor') {
318+
return true;
319+
}
320+
scope = scope.upper;
321+
}
322+
return false;
323+
}
324+
310325
/**
311326
* Retrieve the name of a property node
312327
* @param {ASTNode} node The AST node with the property.
313328
* @return {string} the name of the property or undefined if not found
314329
*/
315330
function getPropertyName(node) {
316-
if (componentUtil.getNode(context, node)) {
331+
if (componentUtil.getNode(context, node) && !inConstructor()) {
332+
if (node.object.name === 'props') {
333+
return void 0;
334+
}
317335
node = node.parent;
318336
}
319337
var property = node.property;
@@ -400,7 +418,7 @@ module.exports = function(context) {
400418
usedPropTypes.push({
401419
name: name,
402420
allNames: allNames,
403-
node: node.object.name !== 'props' ? node.parent.property : node.property
421+
node: node.object.name !== 'props' && !inConstructor() ? node.parent.property : node.property
404422
});
405423
break;
406424
case 'destructuring':

tests/lib/rules/prop-types.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,19 @@ ruleTester.run('prop-types', rule, {
782782
'}'
783783
].join('\n'),
784784
parser: 'babel-eslint'
785+
}, {
786+
code: [
787+
'class Hello extends React.Component {',
788+
' constructor(props, context) {',
789+
' super(props, context)',
790+
' this.state = { status: props.source.uri }',
791+
' }',
792+
' static propTypes = {',
793+
' source: PropTypes.object',
794+
' }',
795+
'}'
796+
].join('\n'),
797+
parser: 'babel-eslint'
785798
}
786799
],
787800

@@ -1236,6 +1249,33 @@ ruleTester.run('prop-types', rule, {
12361249
errors: [
12371250
{message: '\'lastname\' is missing in props validation for Hello'}
12381251
]
1252+
}, {
1253+
code: [
1254+
'class Hello extends React.Component {',
1255+
' constructor(props, context) {',
1256+
' super(props, context)',
1257+
' this.state = { status: props.source }',
1258+
' }',
1259+
'}'
1260+
].join('\n'),
1261+
parser: 'babel-eslint',
1262+
errors: [
1263+
{message: '\'source\' is missing in props validation for Hello'}
1264+
]
1265+
}, {
1266+
code: [
1267+
'class Hello extends React.Component {',
1268+
' constructor(props, context) {',
1269+
' super(props, context)',
1270+
' this.state = { status: props.source.uri }',
1271+
' }',
1272+
'}'
1273+
].join('\n'),
1274+
parser: 'babel-eslint',
1275+
errors: [
1276+
{message: '\'source\' is missing in props validation for Hello'},
1277+
{message: '\'source.uri\' is missing in props validation for Hello'}
1278+
]
12391279
}
12401280
]
12411281
});

0 commit comments

Comments
 (0)