Skip to content

Commit

Permalink
Support recursive type annotations, fixes jsx-eslint#913
Browse files Browse the repository at this point in the history
  • Loading branch information
phpnode committed Apr 3, 2017
1 parent a70cbce commit 3a114e5
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 5 deletions.
21 changes: 16 additions & 5 deletions lib/rules/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -484,14 +484,25 @@ module.exports = {
* Creates the representation of the React props type annotation for the component.
* The representation is used to verify nested used properties.
* @param {ASTNode} annotation Type annotation for the props class property.
* @param {Array} seen Keeps track of annotations we've already seen.
* @return {Object|Boolean} The representation of the declaration, true means
* the property is declared without the need for further analysis.
*/
function buildTypeAnnotationDeclarationTypes(annotation) {
function buildTypeAnnotationDeclarationTypes(annotation, seen) {
if (seen === void 0) {
// Keeps track of annotations we've already seen to
// prevent problems with cyclic types.
seen = [];
}
if (seen.indexOf(annotation) > -1) {
// this must be a recursive type annotation, just accept anything.
return true;
}
seen.push(annotation);
switch (annotation.type) {
case 'GenericTypeAnnotation':
if (typeScope(annotation.id.name)) {
return buildTypeAnnotationDeclarationTypes(typeScope(annotation.id.name));
return buildTypeAnnotationDeclarationTypes(typeScope(annotation.id.name), seen);
}
return true;
case 'ObjectTypeAnnotation':
Expand All @@ -500,7 +511,7 @@ module.exports = {
children: {}
};
iterateProperties(annotation.properties, function(childKey, childValue) {
shapeTypeDefinition.children[childKey] = buildTypeAnnotationDeclarationTypes(childValue);
shapeTypeDefinition.children[childKey] = buildTypeAnnotationDeclarationTypes(childValue, seen);
});
return shapeTypeDefinition;
case 'UnionTypeAnnotation':
Expand All @@ -509,7 +520,7 @@ module.exports = {
children: []
};
for (var i = 0, j = annotation.types.length; i < j; i++) {
var type = buildTypeAnnotationDeclarationTypes(annotation.types[i]);
var type = buildTypeAnnotationDeclarationTypes(annotation.types[i], seen);
// keep only complex type
if (type !== true) {
if (type.children === true) {
Expand All @@ -530,7 +541,7 @@ module.exports = {
return {
type: 'object',
children: {
__ANY_KEY__: buildTypeAnnotationDeclarationTypes(annotation.elementType)
__ANY_KEY__: buildTypeAnnotationDeclarationTypes(annotation.elementType, seen)
}
};
default:
Expand Down
13 changes: 13 additions & 0 deletions tests/lib/rules/prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,19 @@ ruleTester.run('prop-types', rule, {
'}'
].join('\n'),
parser: 'babel-eslint'
}, {
code: [
'type Note = {text: string, children?: Note[]};',
'type Props = {',
' notes: Note[];',
'};',
'class Hello extends React.Component<void, Props, void> {',
' render () {',
' return <div>Hello {this.props.notes[0].text}</div>;',
' }',
'}'
].join('\n'),
parser: 'babel-eslint'
}, {
code: [
'type Props = {name: Object;};',
Expand Down

0 comments on commit 3a114e5

Please sign in to comment.