Skip to content

Commit 3e4d184

Browse files
author
Joachim Seminck
committed
Aadd support also for no-unused-prop-types
1 parent 19a2911 commit 3e4d184

File tree

3 files changed

+85
-44
lines changed

3 files changed

+85
-44
lines changed

lib/rules/no-unused-prop-types.js

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -725,49 +725,69 @@ module.exports = {
725725
}
726726

727727
/**
728-
* Marks all props found inside IntersectionTypeAnnotation as declared.
729-
* Since InterSectionTypeAnnotations can be nested, this handles recursively.
728+
* Marks all props found inside ObjectTypeAnnotaiton as declared.
730729
*
731-
* Modifies the declaredPropTypes object
730+
* Modifies the declaredProperties object
732731
* @param {ASTNode} propTypes
733732
* @param {Object} declaredPropTypes
734733
* @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
735734
*/
736-
function declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes) {
735+
function declarePropTypesForObjectTypeAnnotation(propTypes, declaredPropTypes) {
737736
let ignorePropsValidation = false;
738737

739-
propTypes.types.forEach(annotation => {
740-
const typeNode = typeScope(annotation.id.name);
741-
742-
if (!typeNode) {
738+
iterateProperties(propTypes.properties, (key, value) => {
739+
if (!value) {
743740
ignorePropsValidation = true;
744741
return;
745742
}
746743

747-
if (typeNode.type === 'IntersectionTypeAnnotation') {
748-
ignorePropsValidation = declarePropTypesForIntersectionTypeAnnotation(typeNode, declaredPropTypes);
749-
} else {
750-
iterateProperties(typeNode.properties, (key, value) => {
751-
if (!value) {
752-
ignorePropsValidation = true;
753-
return;
754-
}
755-
756-
let types = buildTypeAnnotationDeclarationTypes(value, key);
757-
if (types === true) {
758-
types = {};
759-
}
760-
types.fullName = key;
761-
types.name = key;
762-
types.node = value;
763-
declaredPropTypes.push(types);
764-
});
744+
let types = buildTypeAnnotationDeclarationTypes(value, key);
745+
if (types === true) {
746+
types = {};
765747
}
748+
types.fullName = key;
749+
types.name = key;
750+
types.node = value;
751+
declaredPropTypes.push(types);
766752
});
767753

768754
return ignorePropsValidation;
769755
}
770756

757+
/**
758+
* Marks all props found inside IntersectionTypeAnnotation as declared.
759+
* Since InterSectionTypeAnnotations can be nested, this handles recursively.
760+
*
761+
* Modifies the declaredPropTypes object
762+
* @param {ASTNode} propTypes
763+
* @param {Object} declaredPropTypes
764+
* @returns {Boolean} True if propTypes should be ignored (e.g. when a type can't be resolved, when it is imported)
765+
*/
766+
function declarePropTypesForIntersectionTypeAnnotation(propTypes, declaredPropTypes) {
767+
return propTypes.types.reduce((ignorePropsValidation, annotation) => {
768+
// If we already decided to skip props validation then we don't have to continue processing anything else
769+
if (ignorePropsValidation) {
770+
return ignorePropsValidation;
771+
}
772+
773+
if (annotation.type === 'ObjectTypeAnnotation') {
774+
ignorePropsValidation = declarePropTypesForObjectTypeAnnotation(annotation, declaredPropTypes);
775+
} else {
776+
const typeNode = typeScope(annotation.id.name);
777+
778+
if (!typeNode) {
779+
ignorePropsValidation = true;
780+
} else if (typeNode.type === 'IntersectionTypeAnnotation') {
781+
ignorePropsValidation = declarePropTypesForIntersectionTypeAnnotation(typeNode, declaredPropTypes);
782+
} else {
783+
ignorePropsValidation = declarePropTypesForObjectTypeAnnotation(typeNode, declaredPropTypes);
784+
}
785+
}
786+
787+
return ignorePropsValidation;
788+
}, false);
789+
}
790+
771791
/**
772792
* Mark a prop type as declared
773793
* @param {ASTNode} node The AST node being checked.
@@ -780,20 +800,7 @@ module.exports = {
780800

781801
switch (propTypes && propTypes.type) {
782802
case 'ObjectTypeAnnotation':
783-
iterateProperties(propTypes.properties, (key, value) => {
784-
if (!value) {
785-
ignorePropsValidation = true;
786-
return;
787-
}
788-
let types = buildTypeAnnotationDeclarationTypes(value, key);
789-
if (types === true) {
790-
types = {};
791-
}
792-
types.fullName = key;
793-
types.name = key;
794-
types.node = value;
795-
declaredPropTypes.push(types);
796-
});
803+
ignorePropsValidation = declarePropTypesForObjectTypeAnnotation(propTypes, declaredPropTypes);
797804
break;
798805
case 'ObjectExpression':
799806
iterateProperties(propTypes.properties, (key, value) => {

lib/rules/prop-types.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -762,10 +762,7 @@ module.exports = {
762762
}
763763
}
764764

765-
// Return early if we have to ignore props validation. No point to continue processing.
766-
if (ignorePropsValidation) {
767-
return ignorePropsValidation;
768-
}
765+
return ignorePropsValidation;
769766
}, false);
770767
}
771768

tests/lib/rules/no-unused-prop-types.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,23 @@ ruleTester.run('no-unused-prop-types', rule, {
871871
}
872872
`,
873873
parser: 'babel-eslint'
874+
}, {
875+
code: `
876+
type PropsB = { foo: string };
877+
type PropsC = { bar: string };
878+
type Props = PropsB & {
879+
zap: string
880+
};
881+
882+
class Bar extends React.Component {
883+
props: Props & PropsC;
884+
885+
render() {
886+
return <div>{this.props.foo} - {this.props.bar} - {this.props.zap}</div>
887+
}
888+
}
889+
`,
890+
parser: 'babel-eslint'
874891
}, {
875892
code: [
876893
'import type Props from "fake";',
@@ -2794,6 +2811,26 @@ ruleTester.run('no-unused-prop-types', rule, {
27942811
errors: [
27952812
{message: '\'zap\' PropType is defined but prop is never used'}
27962813
]
2814+
}, {
2815+
code: `
2816+
type PropsB = { foo: string };
2817+
type PropsC = { bar: string };
2818+
type Props = PropsB & {
2819+
zap: string
2820+
};
2821+
2822+
class Bar extends React.Component {
2823+
props: Props & PropsC;
2824+
2825+
render() {
2826+
return <div>{this.props.foo} - {this.props.bar}</div>
2827+
}
2828+
}
2829+
`,
2830+
errors: [
2831+
{message: '\'zap\' PropType is defined but prop is never used'}
2832+
],
2833+
parser: 'babel-eslint'
27972834
}, {
27982835
code: [
27992836
'class Hello extends React.Component {',

0 commit comments

Comments
 (0)