Skip to content

Commit a151815

Browse files
author
Yannick Croissant
committed
Fix require-default-props crash with babel-eslint@5 (fixes #1029)
1 parent 0f79aa3 commit a151815

File tree

2 files changed

+51
-12
lines changed

2 files changed

+51
-12
lines changed

lib/rules/require-default-props.js

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,33 @@ module.exports = {
2525
},
2626

2727
create: Components.detect(function(context, components, utils) {
28+
29+
/**
30+
* Get properties name
31+
* @param {Object} node - Property.
32+
* @returns {String} Property name.
33+
*/
34+
function getPropertyName(node) {
35+
if (node.key || ['MethodDefinition', 'Property'].indexOf(node.type) !== -1) {
36+
return node.key.name;
37+
} else if (node.type === 'MemberExpression') {
38+
return node.property.name;
39+
// Special case for class properties
40+
// (babel-eslint@5 does not expose property name so we have to rely on tokens)
41+
} else if (node.type === 'ClassProperty') {
42+
var tokens = context.getFirstTokens(node, 2);
43+
return tokens[1] && tokens[1].type === 'Identifier' ? tokens[1].value : tokens[0].value;
44+
}
45+
return '';
46+
}
47+
2848
/**
2949
* Checks if the Identifier node passed in looks like a propTypes declaration.
3050
* @param {ASTNode} node The node to check. Must be an Identifier node.
3151
* @returns {Boolean} `true` if the node is a propTypes declaration, `false` if not
3252
*/
3353
function isPropTypesDeclaration(node) {
34-
return node.type === 'Identifier' && node.name === 'propTypes';
54+
return getPropertyName(node) === 'propTypes';
3555
}
3656

3757
/**
@@ -40,8 +60,7 @@ module.exports = {
4060
* @returns {Boolean} `true` if the node is a defaultProps declaration, `false` if not
4161
*/
4262
function isDefaultPropsDeclaration(node) {
43-
return node.type === 'Identifier' &&
44-
(node.name === 'defaultProps' || node.name === 'getDefaultProps');
63+
return (getPropertyName(node) === 'defaultProps' || getPropertyName(node) === 'getDefaultProps');
4564
}
4665

4766
/**
@@ -289,7 +308,7 @@ module.exports = {
289308
}
290309

291310
function isPropTypeAnnotation(node) {
292-
return (node.key.name === 'props' && !!node.typeAnnotation);
311+
return (getPropertyName(node) === 'props' && !!node.typeAnnotation);
293312
}
294313

295314
/**
@@ -328,8 +347,8 @@ module.exports = {
328347

329348
return {
330349
MemberExpression: function(node) {
331-
var isPropType = isPropTypesDeclaration(node.property);
332-
var isDefaultProp = isDefaultPropsDeclaration(node.property);
350+
var isPropType = isPropTypesDeclaration(node);
351+
var isDefaultProp = isDefaultPropsDeclaration(node);
333352

334353
if (!isPropType && !isDefaultProp) {
335354
return;
@@ -412,8 +431,8 @@ module.exports = {
412431
return;
413432
}
414433

415-
var isPropType = isPropTypesDeclaration(node.key);
416-
var isDefaultProp = isDefaultPropsDeclaration(node.key);
434+
var isPropType = isPropTypesDeclaration(node);
435+
var isDefaultProp = isDefaultPropsDeclaration(node);
417436

418437
if (!isPropType && !isDefaultProp) {
419438
return;
@@ -468,8 +487,8 @@ module.exports = {
468487
return;
469488
}
470489

471-
var isPropType = isPropTypesDeclaration(node.key);
472-
var isDefaultProp = isDefaultPropsDeclaration(node.key);
490+
var isPropType = getPropertyName(node) === 'propTypes';
491+
var isDefaultProp = getPropertyName(node) === 'defaultProps' || getPropertyName(node) === 'getDefaultProps';
473492

474493
if (!isPropType && !isDefaultProp) {
475494
return;
@@ -520,8 +539,8 @@ module.exports = {
520539
return;
521540
}
522541

523-
var isPropType = isPropTypesDeclaration(property.key);
524-
var isDefaultProp = isDefaultPropsDeclaration(property.key);
542+
var isPropType = isPropTypesDeclaration(property);
543+
var isDefaultProp = isDefaultPropsDeclaration(property);
525544

526545
if (!isPropType && !isDefaultProp) {
527546
return;

tests/lib/rules/require-default-props.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,26 @@ ruleTester.run('require-default-props', rule, {
17181718
column: 3
17191719
}
17201720
]
1721+
},
1722+
{
1723+
code: [
1724+
'class Hello extends React.Component {',
1725+
' static propTypes = {',
1726+
' foo: PropTypes.string',
1727+
' };',
1728+
' render() {',
1729+
' return <div>Hello {this.props.foo}</div>;',
1730+
' }',
1731+
'}'
1732+
].join('\n'),
1733+
parser: 'babel-eslint',
1734+
errors: [
1735+
{
1736+
message: 'propType "foo" is not required, but has no corresponding defaultProp declaration.',
1737+
line: 3,
1738+
column: 5
1739+
}
1740+
]
17211741
}
17221742
]
17231743
});

0 commit comments

Comments
 (0)