Skip to content

Commit 12fca71

Browse files
committedJul 30, 2024·
fix(check-template-names): check for param and returns tags; fixes #1286
1 parent 31e0a35 commit 12fca71

File tree

3 files changed

+81
-29
lines changed

3 files changed

+81
-29
lines changed
 

‎docs/rules/check-template-names.md

+12
Original file line numberDiff line numberDiff line change
@@ -315,5 +315,17 @@ export default class <NumType> {
315315
zeroValue: NumType;
316316
add: (x: NumType, y: NumType) => NumType;
317317
}
318+
319+
/**
320+
* Uses the provided callback to group the given array into the keys of a map.
321+
* Based on the array grouping proposal: https://github.com/tc39/proposal-array-grouping/
322+
*
323+
* @template T
324+
* @param {T[]} array
325+
* @param {(value: T, index: number) => string} callbackFn
326+
* @returns {Map<string, T[]>}
327+
*/
328+
export function mapGroupBy(array, callbackFn) {
329+
}
318330
````
319331

‎src/rules/checkTemplateNames.js

+51-29
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,60 @@ export default iterateJsdoc(({
1919
const templateTags = utils.getTags('template');
2020

2121
const usedNames = new Set();
22+
/**
23+
* @param {string} potentialType
24+
*/
25+
const checkForUsedTypes = (potentialType) => {
26+
let parsedType;
27+
try {
28+
parsedType = mode === 'permissive' ?
29+
tryParseType(/** @type {string} */ (potentialType)) :
30+
parseType(/** @type {string} */ (potentialType), mode);
31+
} catch {
32+
return;
33+
}
34+
35+
traverse(parsedType, (nde) => {
36+
const {
37+
type,
38+
value,
39+
} = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
40+
if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {
41+
usedNames.add(value);
42+
}
43+
});
44+
};
45+
2246
/**
2347
* @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration|
2448
* import('@typescript-eslint/types').TSESTree.ClassDeclaration|
2549
* import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|
2650
* import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration
51+
* @param {boolean} [checkParamsAndReturns]
2752
*/
28-
const checkParameters = (aliasDeclaration) => {
53+
const checkParameters = (aliasDeclaration, checkParamsAndReturns) => {
2954
/* c8 ignore next -- Guard */
3055
const {params} = aliasDeclaration.typeParameters ?? {params: []};
3156
for (const {name: {name}} of params) {
3257
usedNames.add(name);
3358
}
59+
if (checkParamsAndReturns) {
60+
const paramName = /** @type {string} */ (utils.getPreferredTagName({
61+
tagName: 'param',
62+
}));
63+
const paramTags = utils.getTags(paramName);
64+
for (const paramTag of paramTags) {
65+
checkForUsedTypes(paramTag.type);
66+
}
67+
68+
const returnsName = /** @type {string} */ (utils.getPreferredTagName({
69+
tagName: 'returns',
70+
}));
71+
const returnsTags = utils.getTags(returnsName);
72+
for (const returnsTag of returnsTags) {
73+
checkForUsedTypes(returnsTag.type);
74+
}
75+
}
3476
for (const tag of templateTags) {
3577
const {name} = tag;
3678
const names = name.split(/,\s*/);
@@ -53,16 +95,20 @@ export default iterateJsdoc(({
5395
case 'ExportDefaultDeclaration':
5496
case 'ExportNamedDeclaration':
5597
switch (nde.declaration?.type) {
56-
case 'ClassDeclaration':
5798
case 'FunctionDeclaration':
99+
checkParameters(nde.declaration, true);
100+
break;
101+
case 'ClassDeclaration':
58102
case 'TSTypeAliasDeclaration':
59103
case 'TSInterfaceDeclaration':
60104
checkParameters(nde.declaration);
61105
break;
62106
}
63107
break;
64-
case 'ClassDeclaration':
65108
case 'FunctionDeclaration':
109+
checkParameters(nde, true);
110+
break;
111+
case 'ClassDeclaration':
66112
case 'TSTypeAliasDeclaration':
67113
case 'TSInterfaceDeclaration':
68114
checkParameters(nde);
@@ -76,37 +122,13 @@ export default iterateJsdoc(({
76122
return;
77123
}
78124

79-
/**
80-
* @param {string} potentialType
81-
*/
82-
const checkForUsedTypes = (potentialType) => {
83-
let parsedType;
84-
try {
85-
parsedType = mode === 'permissive' ?
86-
tryParseType(/** @type {string} */ (potentialType)) :
87-
parseType(/** @type {string} */ (potentialType), mode);
88-
} catch {
89-
return;
90-
}
91-
92-
traverse(parsedType, (nde) => {
93-
const {
94-
type,
95-
value,
96-
} = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
97-
if (type === 'JsdocTypeName' && (/^[A-Z]$/).test(value)) {
98-
usedNames.add(value);
99-
}
100-
});
101-
};
102-
103125
const potentialTypedefType = typedefTags[0].type;
104126
checkForUsedTypes(potentialTypedefType);
105127

106-
const tagName = /** @type {string} */ (utils.getPreferredTagName({
128+
const propertyName = /** @type {string} */ (utils.getPreferredTagName({
107129
tagName: 'property',
108130
}));
109-
const propertyTags = utils.getTags(tagName);
131+
const propertyTags = utils.getTags(propertyName);
110132
for (const propertyTag of propertyTags) {
111133
checkForUsedTypes(propertyTag.type);
112134
}

‎test/rules/assertions/checkTemplateNames.js

+18
Original file line numberDiff line numberDiff line change
@@ -606,5 +606,23 @@ export default {
606606
parser: typescriptEslintParser
607607
},
608608
},
609+
{
610+
code: `
611+
/**
612+
* Uses the provided callback to group the given array into the keys of a map.
613+
* Based on the array grouping proposal: https://github.com/tc39/proposal-array-grouping/
614+
*
615+
* @template T
616+
* @param {T[]} array
617+
* @param {(value: T, index: number) => string} callbackFn
618+
* @returns {Map<string, T[]>}
619+
*/
620+
export function mapGroupBy(array, callbackFn) {
621+
}
622+
`,
623+
languageOptions: {
624+
parser: typescriptEslintParser
625+
},
626+
},
609627
],
610628
};

0 commit comments

Comments
 (0)
Please sign in to comment.