diff --git a/lib/rules/no-unused-prop-types.js b/lib/rules/no-unused-prop-types.js index 252e349574..5127971d1a 100644 --- a/lib/rules/no-unused-prop-types.js +++ b/lib/rules/no-unused-prop-types.js @@ -661,7 +661,7 @@ module.exports = { break; } - components.set(node, { + components.set(component ? component.node : node, { usedPropTypes: usedPropTypes, ignorePropsValidation: ignorePropsValidation }); diff --git a/tests/lib/rules/no-unused-prop-types.js b/tests/lib/rules/no-unused-prop-types.js index 1984159c2f..eff0e9c962 100644 --- a/tests/lib/rules/no-unused-prop-types.js +++ b/tests/lib/rules/no-unused-prop-types.js @@ -1581,6 +1581,36 @@ ruleTester.run('no-unused-prop-types', rule, { '}' ].join('\n'), parser: 'babel-eslint' + }, { + // Props used inside of an async class property + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' }', + ' classProperty = async () => {', + ' await this.props.foo();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint' + }, { + // Multiple props used inside of an async class property + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' classProperty = async () => {', + ' await this.props.foo();', + ' await this.props.bar();', + ' await this.props.baz();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint' }, { code: [ 'class Hello extends Component {', @@ -1619,6 +1649,38 @@ ruleTester.run('no-unused-prop-types', rule, { '}' ].join('\n'), parser: 'babel-eslint' + }, { + // Destructured props inside of async class property + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' }', + ' classProperty = async () => {', + ' const { foo } = this.props;', + ' await foo();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint' + }, { + // Multiple destructured props inside of async class property + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' classProperty = async () => {', + ' const { foo, bar, baz } = this.props;', + ' await foo();', + ' await bar();', + ' await baz();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint' }, { code: [ 'class Hello extends Component {', @@ -1657,6 +1719,50 @@ ruleTester.run('no-unused-prop-types', rule, { '}' ].join('\n'), parser: 'babel-eslint' + }, { + // Props used inside of an async class method + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' }', + ' async method() {', + ' await this.props.foo();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint' + }, { + // Multiple props used inside of an async class method + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' async method() {', + ' await this.props.foo();', + ' await this.props.bar();', + ' await this.props.baz();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint' + }, { + // Destrucuted props inside of async class method + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' }', + ' async method() {', + ' const { foo } = this.props;', + ' await foo();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint' }, { code: [ 'class Hello extends Component {', @@ -1695,6 +1801,62 @@ ruleTester.run('no-unused-prop-types', rule, { '}' ].join('\n'), parser: 'babel-eslint' + }, { + // Multiple destructured props inside of async class method + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' async method() {', + ' const { foo, bar, baz } = this.props;', + ' await foo();', + ' await bar();', + ' await baz();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint' + }, { + // factory functions that return async functions + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' factory() {', + ' return async () => {', + ' await this.props.foo();', + ' await this.props.bar();', + ' await this.props.baz();', + ' };', + ' }', + '}' + ].join('\n'), + parser: 'babel-eslint' + }, { + // factory functions that return async functions + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' factory() {', + ' return async function onSubmit() {', + ' await this.props.foo();', + ' await this.props.bar();', + ' await this.props.baz();', + ' };', + ' }', + '}' + ].join('\n'), + parser: 'babel-eslint' }, { code: [ 'class Hello extends Component {', @@ -1713,6 +1875,57 @@ ruleTester.run('no-unused-prop-types', rule, { ' bar: PropTypes.string,', '};' ].join('\n') + }, { + // Multiple props used inside of an async method + code: [ + 'class Example extends Component {', + ' async method() {', + ' await this.props.foo();', + ' await this.props.bar();', + ' };', + '}', + 'Example.propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + '}' + ].join('\n'), + parserOptions: Object.assign({}, parserOptions, {ecmaVersion: 2017}) + }, { + // Multiple props used inside of an async function + code: [ + 'class Example extends Component {', + ' render() {', + ' async function onSubmit() {', + ' await this.props.foo();', + ' await this.props.bar();', + ' }', + ' return
', + ' };', + '}', + 'Example.propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + '}' + ].join('\n'), + parserOptions: Object.assign({}, parserOptions, {ecmaVersion: 2017}) + }, { + // Multiple props used inside of an async arrow function + code: [ + 'class Example extends Component {', + ' render() {', + ' const onSubmit = async () => {', + ' await this.props.foo();', + ' await this.props.bar();', + ' }', + ' return ', + ' };', + '}', + 'Example.propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + '}' + ].join('\n'), + parserOptions: Object.assign({}, parserOptions, {ecmaVersion: 2017}) } ], @@ -2680,6 +2893,27 @@ ruleTester.run('no-unused-prop-types', rule, { line: 4, column: 10 }] + }, { + // Multiple props used inside of an async class property + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' classProperty = async () => {', + ' await this.props.foo();', + ' await this.props.bar();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint', + errors: [{ + message: '\'baz\' PropType is defined but prop is never used', + line: 5, + column: 10 + }] }, { code: [ 'class Hello extends Component {', @@ -2720,6 +2954,47 @@ ruleTester.run('no-unused-prop-types', rule, { line: 4, column: 10 }] + }, { + // Multiple destructured props inside of async class property + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' classProperty = async () => {', + ' const { bar, baz } = this.props;', + ' await bar();', + ' await baz();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint', + errors: [{ + message: '\'foo\' PropType is defined but prop is never used' + }] + }, { + // Multiple props used inside of an async class method + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' async method() {', + ' await this.props.foo();', + ' await this.props.baz();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint', + errors: [{ + message: '\'bar\' PropType is defined but prop is never used', + line: 4, + column: 10 + }] }, { code: [ 'class Hello extends Component {', @@ -2760,6 +3035,51 @@ ruleTester.run('no-unused-prop-types', rule, { line: 4, column: 10 }] + }, { + // Multiple destructured props inside of async class method + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' async method() {', + ' const { foo, bar } = this.props;', + ' await foo();', + ' await bar();', + ' };', + '}' + ].join('\n'), + parser: 'babel-eslint', + errors: [{ + message: '\'baz\' PropType is defined but prop is never used', + line: 5, + column: 10 + }] + }, { + // factory functions that return async functions + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' factory() {', + ' return async () => {', + ' await this.props.foo();', + ' await this.props.bar();', + ' };', + ' }', + '}' + ].join('\n'), + parser: 'babel-eslint', + errors: [{ + message: '\'baz\' PropType is defined but prop is never used', + line: 5, + column: 10 + }] }, { code: [ 'class Hello extends Component {', @@ -2824,6 +3144,77 @@ ruleTester.run('no-unused-prop-types', rule, { settings: { propWrapperFunctions: ['forbidExtraProps'] } + }, { + // factory functions that return async functions + code: [ + 'export class Example extends Component {', + ' static propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + ' }', + ' factory() {', + ' return async function onSubmit() {', + ' await this.props.bar();', + ' await this.props.baz();', + ' };', + ' }', + '}' + ].join('\n'), + parser: 'babel-eslint', + errors: [{ + message: '\'foo\' PropType is defined but prop is never used', + line: 3, + column: 10 + }] + }, { + // Multiple props used inside of an async function + code: [ + 'class Example extends Component {', + ' render() {', + ' async function onSubmit() {', + ' await this.props.foo();', + ' await this.props.bar();', + ' }', + ' return ', + ' };', + '}', + 'Example.propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + '}' + ].join('\n'), + parserOptions: Object.assign({}, parserOptions, {ecmaVersion: 2017}), + errors: [{ + message: '\'baz\' PropType is defined but prop is never used', + line: 13, + column: 8 + }] + }, { + // Multiple props used inside of an async arrow function + code: [ + 'class Example extends Component {', + ' render() {', + ' const onSubmit = async () => {', + ' await this.props.bar();', + ' await this.props.baz();', + ' }', + ' return ', + ' };', + '}', + 'Example.propTypes = {', + ' foo: PropTypes.func,', + ' bar: PropTypes.func,', + ' baz: PropTypes.func,', + '}' + ].join('\n'), + parserOptions: Object.assign({}, parserOptions, {ecmaVersion: 2017}), + errors: [{ + message: '\'foo\' PropType is defined but prop is never used', + line: 11, + column: 8 + }] } /* , { // Enable this when the following issue is fixed