From e15bafa35ae1d70983551e259879e3858e9e9347 Mon Sep 17 00:00:00 2001 From: Luke Zapart Date: Wed, 2 Jan 2019 18:30:53 -0800 Subject: [PATCH] [Fix] `no-unused-prop-types`: fix issue with propTypes misclassifying props --- lib/util/propTypes.js | 22 ++++++++++++++++++++++ tests/lib/rules/no-unused-prop-types.js | 15 +++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/lib/util/propTypes.js b/lib/util/propTypes.js index 5d4c3de7f1..59d4d6d94c 100644 --- a/lib/util/propTypes.js +++ b/lib/util/propTypes.js @@ -67,6 +67,24 @@ function iterateProperties(context, properties, fn) { } } +/** + * Checks if a node is inside a class property. + * + * @param {ASTNode} node the AST node being checked. + * @returns {Boolean} True if the node has a ClassProperty ancestor, false if not. + */ +function isInsideClassProperty(node) { + let parent = node.parent; + while (parent) { + if (parent.type === 'ClassProperty') { + return true; + } + parent = parent.parent; + } + + return false; +} + module.exports = function propTypesInstructions(context, components, utils) { // Used to track the type annotations in scope. // Necessary because babel's scopes do not track type annotations. @@ -554,6 +572,10 @@ module.exports = function propTypesInstructions(context, components, utils) { return; } + if (isInsideClassProperty(node)) { + return; + } + const param = node.params[0]; if (param.typeAnnotation && param.typeAnnotation.typeAnnotation && param.typeAnnotation.typeAnnotation.type === 'UnionTypeAnnotation') { param.typeAnnotation.typeAnnotation.types.forEach(annotation => { diff --git a/tests/lib/rules/no-unused-prop-types.js b/tests/lib/rules/no-unused-prop-types.js index 5b180d5c60..359676c1d7 100644 --- a/tests/lib/rules/no-unused-prop-types.js +++ b/tests/lib/rules/no-unused-prop-types.js @@ -2929,6 +2929,21 @@ ruleTester.run('no-unused-prop-types', rule, { ' })', '};' ].join('\n') + }, { + code: ` + type Props = { + used: string, + } + class Hello extends React.Component { + renderHelper = ({unused}: {unused: string}) => { + return
; + } + render() { + return
{this.props.used}
; + } + } + `, + parser: 'babel-eslint' } ],