Skip to content

Commit 22cc878

Browse files
hank121314ljharb
authored andcommitted
[Fix] prop-types/no-unused-prop-types: handle CallExpression in ReturnType
Fixes #2795.
1 parent 4da7451 commit 22cc878

File tree

5 files changed

+288
-72
lines changed

5 files changed

+288
-72
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
2222
* [`prop-types`]: Detect JSX returned by sequential expression ([#2801][] @mikol)
2323
* [`jsx-props-no-multi-spaces`]: "Expected no line gap between" false positive ([#2792][] @karolina-benitez)
2424
* [`no-unknown-property`]: check attributes with any input case ([#2790][] @julienw)
25+
* [`prop-types`]/[`no-unused-prop-types`]: handle CallExpression in ReturnType ([#2802][] @hank121314)
2526

2627
### Changed
2728
* [Tests] [`jsx-one-expression-per-line`]: add passing tests ([#2799][] @TaLeaMonet)
2829

30+
[#2802]: https://github.com/yannickcr/eslint-plugin-react/pull/2802
2931
[#2801]: https://github.com/yannickcr/eslint-plugin-react/pull/2801
3032
[#2799]: https://github.com/yannickcr/eslint-plugin-react/pull/2799
3133
[#2796]: https://github.com/yannickcr/eslint-plugin-react/pull/2796

lib/util/ast.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ function isTSTypeQuery(node) {
261261
return nodeType === 'TSTypeQuery';
262262
}
263263

264+
function isTSTypeParameterInstantiation(node) {
265+
if (!node) return false;
266+
const nodeType = node.type;
267+
return nodeType === 'TSTypeParameterInstantiation';
268+
}
269+
264270
module.exports = {
265271
findReturnStatement,
266272
getFirstNodeInLine,
@@ -283,5 +289,6 @@ module.exports = {
283289
isTSTypeAliasDeclaration,
284290
isTSParenthesizedType,
285291
isTSFunctionType,
286-
isTSTypeQuery
292+
isTSTypeQuery,
293+
isTSTypeParameterInstantiation
287294
};

lib/util/propTypes.js

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -502,27 +502,20 @@ module.exports = function propTypesInstructions(context, components, utils) {
502502
this.referenceNameMap = new Set();
503503
this.sourceCode = context.getSourceCode();
504504
this.shouldIgnorePropTypes = false;
505-
this.startWithTSTypeAnnotation();
505+
this.visitTSNode(this.propTypes);
506506
this.endAndStructDeclaredPropTypes();
507507
}
508508

509-
startWithTSTypeAnnotation() {
510-
if (astUtil.isTSTypeAnnotation(this.propTypes)) {
511-
const typeAnnotation = this.propTypes.typeAnnotation;
512-
this.visitTSNode(typeAnnotation);
513-
} else {
514-
// weird cases such as TSTypeFunction
515-
this.shouldIgnorePropTypes = true;
516-
}
517-
}
518-
519509
/**
520510
* The node will be distribute to different function.
521511
* @param {ASTNode} node
522512
*/
523513
visitTSNode(node) {
524514
if (!node) return;
525-
if (astUtil.isTSTypeReference(node)) {
515+
if (astUtil.isTSTypeAnnotation(node)) {
516+
const typeAnnotation = node.typeAnnotation;
517+
this.visitTSNode(typeAnnotation);
518+
} else if (astUtil.isTSTypeReference(node)) {
526519
this.searchDeclarationByName(node);
527520
} else if (astUtil.isTSInterfaceHeritage(node)) {
528521
this.searchDeclarationByName(node);
@@ -535,12 +528,10 @@ module.exports = function propTypesInstructions(context, components, utils) {
535528
this.convertIntersectionTypeToPropTypes(node);
536529
} else if (astUtil.isTSParenthesizedType(node)) {
537530
const typeAnnotation = node.typeAnnotation;
538-
if (astUtil.isTSTypeLiteral(typeAnnotation)) {
539-
// Check node is an object literal
540-
if (Array.isArray(node.typeAnnotation.members)) {
541-
this.foundDeclaredPropertiesList = this.foundDeclaredPropertiesList
542-
.concat(node.typeAnnotation.members);
543-
}
531+
this.visitTSNode(typeAnnotation);
532+
} else if (astUtil.isTSTypeParameterInstantiation(node)) {
533+
if (Array.isArray(node.params)) {
534+
node.params.forEach(this.visitTSNode, this);
544535
}
545536
} else {
546537
this.shouldIgnorePropTypes = true;
@@ -671,6 +662,19 @@ module.exports = function propTypesInstructions(context, components, utils) {
671662
switch (res.type) {
672663
case 'ObjectExpression':
673664
iterateProperties(context, res.properties, (key, value, propNode) => {
665+
if (propNode && propNode.argument && propNode.argument.type === 'CallExpression') {
666+
if (propNode.argument.typeParameters) {
667+
this.visitTSNode(propNode.argument.typeParameters);
668+
} else {
669+
// Ignore this CallExpression return value since it doesn't have any typeParameters to let us know it's types.
670+
this.shouldIgnorePropTypes = true;
671+
return;
672+
}
673+
}
674+
if (!value) {
675+
this.shouldIgnorePropTypes = true;
676+
return;
677+
}
674678
const types = buildReactDeclarationTypes(value, key);
675679
types.fullName = key;
676680
types.name = key;
@@ -679,6 +683,14 @@ module.exports = function propTypesInstructions(context, components, utils) {
679683
this.declaredPropTypes[key] = types;
680684
});
681685
break;
686+
case 'CallExpression':
687+
if (res.typeParameters) {
688+
this.visitTSNode(res.typeParameters);
689+
} else {
690+
// Ignore this CallExpression return value since it doesn't have any typeParameters to let us know it's types.
691+
this.shouldIgnorePropTypes = true;
692+
}
693+
break;
682694
default:
683695
}
684696
}
@@ -689,15 +701,13 @@ module.exports = function propTypesInstructions(context, components, utils) {
689701
// Handle ReturnType<()=>returnType>
690702
if (astUtil.isTSFunctionType(returnType)) {
691703
if (astUtil.isTSTypeAnnotation(returnType.returnType)) {
692-
const returnTypeAnnotation = returnType.returnType.typeAnnotation;
693-
this.visitTSNode(returnTypeAnnotation);
704+
this.visitTSNode(returnType.returnType);
694705
return;
695706
}
696707
// This line is trying to handle typescript-eslint-parser
697708
// typescript-eslint-parser TSFunction name returnType as typeAnnotation
698709
if (astUtil.isTSTypeAnnotation(returnType.typeAnnotation)) {
699-
const returnTypeAnnotation = returnType.typeAnnotation.typeAnnotation;
700-
this.visitTSNode(returnTypeAnnotation);
710+
this.visitTSNode(returnType.typeAnnotation);
701711
return;
702712
}
703713
}

0 commit comments

Comments
 (0)