diff --git a/lib/rules/no-unused-prop-types.js b/lib/rules/no-unused-prop-types.js index 0471913737..a5afea72af 100644 --- a/lib/rules/no-unused-prop-types.js +++ b/lib/rules/no-unused-prop-types.js @@ -791,6 +791,13 @@ module.exports = { types.name = key; types.node = value; declaredPropTypes.push(types); + // Handle custom prop validators using props inside + if ( + value.type === 'ArrowFunctionExpression' + || value.type === 'FunctionExpression' + ) { + markPropTypesAsUsed(value); + } }); break; case 'MemberExpression': diff --git a/tests/lib/rules/no-unused-prop-types.js b/tests/lib/rules/no-unused-prop-types.js index 62ef6094c0..e8b3e8e210 100644 --- a/tests/lib/rules/no-unused-prop-types.js +++ b/tests/lib/rules/no-unused-prop-types.js @@ -829,10 +829,10 @@ ruleTester.run('no-unused-prop-types', rule, { type PropsA = { a: string } type PropsB = { b: string } type Props = PropsA & PropsB; - + class MyComponent extends React.Component { props: Props; - + render() { return
{this.props.a} - {this.props.b}
} @@ -848,7 +848,7 @@ ruleTester.run('no-unused-prop-types', rule, { class Bar extends React.Component { props: Props & PropsC; - + render() { return
{this.props.foo} - {this.props.bar} - {this.props.zap}
} @@ -864,7 +864,7 @@ ruleTester.run('no-unused-prop-types', rule, { class Bar extends React.Component { props: Props & PropsC; - + render() { return
{this.props.foo} - {this.props.bar} - {this.props.zap}
} @@ -876,12 +876,12 @@ ruleTester.run('no-unused-prop-types', rule, { type PropsB = { foo: string }; type PropsC = { bar: string }; type Props = PropsB & { - zap: string + zap: string }; class Bar extends React.Component { props: Props & PropsC; - + render() { return
{this.props.foo} - {this.props.bar} - {this.props.zap}
} @@ -893,12 +893,12 @@ ruleTester.run('no-unused-prop-types', rule, { type PropsB = { foo: string }; type PropsC = { bar: string }; type Props = { - zap: string + zap: string } & PropsB; class Bar extends React.Component { props: Props & PropsC; - + render() { return
{this.props.foo} - {this.props.bar} - {this.props.zap}
} @@ -2208,6 +2208,78 @@ ruleTester.run('no-unused-prop-types', rule, { `, settings: {react: {flowVersion: '0.53'}}, parser: 'babel-eslint' + }, { + // Issue #1068 + code: ` + class MyComponent extends Component { + static propTypes = { + validate: PropTypes.bool, + options: PropTypes.array, + value: ({options, value, validate}) => { + if (!validate) return; + if (options.indexOf(value) < 0) + throw new Errow('oops'); + } + } + + render() { + return + } + } + `, + parser: 'babel-eslint' + }, { + // Issue #1068 + code: ` + class MyComponent extends Component { + static propTypes = { + validate: PropTypes.bool, + options: PropTypes.array, + value: function ({options, value, validate}) { + if (!validate) return; + if (options.indexOf(value) < 0) + throw new Errow('oops'); + } + } + + render() { + return + } + } + `, + parser: 'babel-eslint' + }, { + // Issue #1068 + code: ` + class MyComponent extends Component { + static propTypes = { + validate: PropTypes.bool, + options: PropTypes.array, + value({options, value, validate}) { + if (!validate) return; + if (options.indexOf(value) < 0) + throw new Errow('oops'); + } + } + + render() { + return + } + } + `, + parser: 'babel-eslint' } ], @@ -2796,10 +2868,10 @@ ruleTester.run('no-unused-prop-types', rule, { type PropsA = { a: string } type PropsB = { b: string } type Props = PropsA & PropsB; - + class MyComponent extends React.Component { props: Props; - + render() { return
{this.props.a}
} @@ -2818,7 +2890,7 @@ ruleTester.run('no-unused-prop-types', rule, { class Bar extends React.Component { props: Props & PropsC; - + render() { return
{this.props.foo} - {this.props.bar}
} @@ -2833,12 +2905,12 @@ ruleTester.run('no-unused-prop-types', rule, { type PropsB = { foo: string }; type PropsC = { bar: string }; type Props = PropsB & { - zap: string + zap: string }; class Bar extends React.Component { props: Props & PropsC; - + render() { return
{this.props.foo} - {this.props.bar}
} @@ -2853,12 +2925,12 @@ ruleTester.run('no-unused-prop-types', rule, { type PropsB = { foo: string }; type PropsC = { bar: string }; type Props = { - zap: string + zap: string } & PropsB; class Bar extends React.Component { props: Props & PropsC; - + render() { return
{this.props.foo} - {this.props.bar}
}