Skip to content

Commit ab5b92a

Browse files
HenryBrown0ljharb
authored andcommitted
refactor: add getTypeArguments util
1 parent 79a2686 commit ab5b92a

File tree

6 files changed

+58
-39
lines changed

6 files changed

+58
-39
lines changed

lib/rules/boolean-prop-naming.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,14 +257,14 @@ module.exports = {
257257
}
258258

259259
const typeAnnotation = component.node.parent.id.typeAnnotation.typeAnnotation;
260-
const annotationTypeParams = typeAnnotation.typeArguments || typeAnnotation.typeParameters;
260+
const annotationTypeArguments = propsUtil.getTypeArguments(typeAnnotation);
261261
if (
262-
annotationTypeParams && (
263-
annotationTypeParams.type === 'TSTypeParameterInstantiation'
264-
|| annotationTypeParams.type === 'TypeParameterInstantiation'
262+
annotationTypeArguments && (
263+
annotationTypeArguments.type === 'TSTypeParameterInstantiation'
264+
|| annotationTypeArguments.type === 'TypeParameterInstantiation'
265265
)
266266
) {
267-
return annotationTypeParams.params.find(
267+
return annotationTypeArguments.params.find(
268268
(param) => param.type === 'TSTypeReference' || param.type === 'GenericTypeAnnotation'
269269
);
270270
}

lib/rules/function-component-definition.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const Components = require('../util/Components');
1010
const docsUrl = require('../util/docsUrl');
1111
const reportC = require('../util/report');
1212
const getText = require('../util/eslint').getText;
13+
const propsUtil = require('../util/props');
1314

1415
// ------------------------------------------------------------------------------
1516
// Rule Definition
@@ -34,12 +35,12 @@ const UNNAMED_FUNCTION_TEMPLATES = {
3435
};
3536

3637
function hasOneUnconstrainedTypeParam(node) {
37-
const nodeTypeParams = node.typeArguments || node.typeParameters;
38+
const nodeTypeArguments = propsUtil.getTypeArguments(node);
3839

39-
return nodeTypeParams
40-
&& nodeTypeParams.params
41-
&& nodeTypeParams.params.length === 1
42-
&& !nodeTypeParams.params[0].constraint;
40+
return nodeTypeArguments
41+
&& nodeTypeArguments.params
42+
&& nodeTypeArguments.params.length === 1
43+
&& !nodeTypeArguments.params[0].constraint;
4344
}
4445

4546
function hasName(node) {
@@ -202,11 +203,12 @@ module.exports = {
202203
varType = node.parent.parent.kind;
203204
}
204205

206+
const nodeTypeArguments = propsUtil.getTypeArguments(node);
205207
return (fixer) => fixer.replaceTextRange(
206208
options.range,
207209
buildFunction(options.template, {
208210
typeAnnotation,
209-
typeParams: getNodeText(node.typeArguments || node.typeParameters, source),
211+
typeParams: getNodeText(nodeTypeArguments, source),
210212
params: getParams(node, source),
211213
returnType: getNodeText(node.returnType, source),
212214
body: getBody(node, source),

lib/rules/jsx-first-prop-new-line.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
const docsUrl = require('../util/docsUrl');
99
const report = require('../util/report');
10+
const propsUtil = require('../util/props');
1011

1112
// ------------------------------------------------------------------------------
1213
// Rule Definition
@@ -55,7 +56,8 @@ module.exports = {
5556
report(context, messages.propOnNewLine, 'propOnNewLine', {
5657
node: decl,
5758
fix(fixer) {
58-
return fixer.replaceTextRange([(node.typeArguments || node.typeParameters || node.name).range[1], decl.range[0]], '\n');
59+
const nodeTypeArguments = propsUtil.getTypeArguments(node);
60+
return fixer.replaceTextRange([(nodeTypeArguments || node.name).range[1], decl.range[0]], '\n');
5961
},
6062
});
6163
}

lib/rules/jsx-props-no-multi-spaces.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
const docsUrl = require('../util/docsUrl');
99
const eslintUtil = require('../util/eslint');
1010
const report = require('../util/report');
11+
const propsUtil = require('../util/props');
1112

1213
const getSourceCode = eslintUtil.getSourceCode;
1314
const getText = eslintUtil.getText;
@@ -103,26 +104,26 @@ module.exports = {
103104
}
104105

105106
function containsGenericType(node) {
106-
const nodeTypeParams = node.typeArguments || node.typeParameters;
107-
if (typeof nodeTypeParams === 'undefined') {
107+
const nodeTypeArguments = propsUtil.getTypeArguments(node);
108+
if (typeof nodeTypeArguments === 'undefined') {
108109
return false;
109110
}
110111

111-
return nodeTypeParams.type === 'TSTypeParameterInstantiation';
112+
return nodeTypeArguments.type === 'TSTypeParameterInstantiation';
112113
}
113114

114115
function getGenericNode(node) {
115116
const name = node.name;
116117
if (containsGenericType(node)) {
117-
const type = node.typeArguments || node.typeParameters;
118+
const nodeTypeArguments = propsUtil.getTypeArguments(node);
118119

119120
return Object.assign(
120121
{},
121122
node,
122123
{
123124
range: [
124125
name.range[0],
125-
type.range[1],
126+
nodeTypeArguments.range[1],
126127
],
127128
}
128129
);

lib/util/propTypes.js

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,8 @@ module.exports = function propTypesInstructions(context, components, utils) {
637637
typeName = node.typeName.name;
638638
const leftMostName = getLeftMostTypeName(node.typeName);
639639
const shouldTraverseTypeParams = genericReactTypesImport.has(leftMostName);
640-
const nodeTypeParams = node.typeArguments || node.typeParameters;
641-
if (shouldTraverseTypeParams && nodeTypeParams && nodeTypeParams.length !== 0) {
640+
const nodeTypeArguments = propsUtil.getTypeArguments(node);
641+
if (shouldTraverseTypeParams && nodeTypeArguments && nodeTypeArguments.length !== 0) {
642642
// All react Generic types are derived from:
643643
// type PropsWithChildren<P> = P & { children?: ReactNode | undefined }
644644
// So we should construct an optional children prop
@@ -660,7 +660,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
660660
const idx = genericTypeParamIndexWherePropsArePresent[
661661
leftMostName !== rightMostName ? rightMostName : importedName
662662
];
663-
const nextNode = nodeTypeParams.params[idx];
663+
const nextNode = nodeTypeArguments.params[idx];
664664
this.visitTSNode(nextNode);
665665
return;
666666
}
@@ -749,10 +749,10 @@ module.exports = function propTypesInstructions(context, components, utils) {
749749

750750
convertReturnTypeToPropTypes(node, rootNode) {
751751
// ReturnType<T> should always have one parameter
752-
const nodeTypeParams = node.typeArguments || node.typeParameters;
753-
if (nodeTypeParams) {
754-
if (nodeTypeParams.params.length === 1) {
755-
let returnType = nodeTypeParams.params[0];
752+
const nodeTypeArguments = propsUtil.getTypeArguments(node);
753+
if (nodeTypeArguments) {
754+
if (nodeTypeArguments.params.length === 1) {
755+
let returnType = nodeTypeArguments.params[0];
756756
// This line is trying to handle typescript-eslint-parser
757757
// typescript-eslint-parser TSTypeQuery is wrapped by TSTypeReference
758758
if (astUtil.isTSTypeReference(returnType)) {
@@ -784,10 +784,9 @@ module.exports = function propTypesInstructions(context, components, utils) {
784784
case 'ObjectExpression':
785785
iterateProperties(context, res.properties, (key, value, propNode) => {
786786
if (propNode && propNode.argument && propNode.argument.type === 'CallExpression') {
787-
const propNodeTypeParams = propNode.argument.typeArguments
788-
|| propNode.argument.typeParameters;
789-
if (propNodeTypeParams) {
790-
this.visitTSNode(propNodeTypeParams);
787+
const propNodeTypeArguments = propsUtil.getTypeArguments(propNode.argument);
788+
if (propNodeTypeArguments) {
789+
this.visitTSNode(propNodeTypeArguments);
791790
} else {
792791
// Ignore this CallExpression return value since it doesn't have any typeParameters to let us know it's types.
793792
this.shouldIgnorePropTypes = true;
@@ -807,8 +806,8 @@ module.exports = function propTypesInstructions(context, components, utils) {
807806
});
808807
break;
809808
case 'CallExpression':
810-
if (res.typeArguments || res.typeParameters) {
811-
this.visitTSNode(res.typeArguments || res.typeParameters);
809+
if (propsUtil.getTypeArguments(res)) {
810+
this.visitTSNode(propsUtil.getTypeArguments(res));
812811
} else {
813812
// Ignore this CallExpression return value since it doesn't have any typeParameters to let us know it's types.
814813
this.shouldIgnorePropTypes = true;
@@ -993,9 +992,9 @@ module.exports = function propTypesInstructions(context, components, utils) {
993992
break;
994993
case 'GenericTypeAnnotation':
995994
if (propTypes.id.name === '$ReadOnly') {
996-
const propTypeParams = propTypes.typeArguments || propTypes.typeParameters;
995+
const propTypeArguments = propsUtil.getTypeArguments(propTypes);
997996
ignorePropsValidation = declarePropTypesForObjectTypeAnnotation(
998-
propTypeParams.params[0],
997+
propTypeArguments.params[0],
999998
declaredPropTypes
1000999
);
10011000
} else {
@@ -1032,13 +1031,16 @@ module.exports = function propTypesInstructions(context, components, utils) {
10321031
return;
10331032
}
10341033

1034+
let propTypesArguments = null;
1035+
if (node.parent) {
1036+
propTypesArguments = propsUtil.getTypeArguments(node.parent);
1037+
}
1038+
10351039
if (
10361040
node.parent
10371041
&& node.parent.callee
1038-
&& (
1039-
(node.parent.typeArguments && node.parent.typeArguments.params)
1040-
|| (node.parent.typeParameters && node.parent.typeParameters.params)
1041-
)
1042+
&& propTypesArguments
1043+
&& propTypesArguments.params
10421044
&& (
10431045
node.parent.callee.name === 'forwardRef' || (
10441046
node.parent.callee.object
@@ -1048,9 +1050,8 @@ module.exports = function propTypesInstructions(context, components, utils) {
10481050
)
10491051
)
10501052
) {
1051-
const propTypesParams = node.parent.typeArguments || node.parent.typeParameters;
10521053
const declaredPropTypes = {};
1053-
const obj = new DeclarePropTypesForTSTypeAnnotation(propTypesParams.params[1], declaredPropTypes, rootNode);
1054+
const obj = new DeclarePropTypesForTSTypeAnnotation(propTypesArguments.params[1], declaredPropTypes, rootNode);
10541055
components.set(node, {
10551056
declaredPropTypes: obj.declaredPropTypes,
10561057
ignorePropsValidation: obj.shouldIgnorePropTypes,
@@ -1096,7 +1097,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
10961097
if (
10971098
annotation
10981099
&& annotation.type !== 'TSTypeReference'
1099-
&& (annotation.typeArguments == null || annotation.typeParameters == null)
1100+
&& propsUtil.getTypeArguments(annotation) == null
11001101
) {
11011102
return;
11021103
}

lib/util/props.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ function isRequiredPropType(propTypeExpression) {
9292
return propTypeExpression.type === 'MemberExpression' && propTypeExpression.property.name === 'isRequired';
9393
}
9494

95+
/**
96+
* Returns the type arguments of a node or type parameters if type arguments are not available.
97+
* @param {ASTNode} node The node to get the type arguments from.
98+
* @returns {ASTNode} The type arguments or type parameters of the node.
99+
*/
100+
function getTypeArguments(node) {
101+
if ('typeArguments' in node) {
102+
return node.typeArguments;
103+
}
104+
return node.typeParameters;
105+
}
106+
95107
module.exports = {
96108
isPropTypesDeclaration,
97109
isContextTypesDeclaration,
@@ -100,4 +112,5 @@ module.exports = {
100112
isDefaultPropsDeclaration,
101113
isDisplayNameDeclaration,
102114
isRequiredPropType,
115+
getTypeArguments,
103116
};

0 commit comments

Comments
 (0)