Skip to content

Commit 0867728

Browse files
authored
fix(no-types, require-example, implements-on-classes): allow any to match function variable declarations; fixes #1446 (#1448)
1 parent b19f6f9 commit 0867728

File tree

8 files changed

+166
-9
lines changed

8 files changed

+166
-9
lines changed

docs/rules/no-types.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,24 @@ class Example {
149149
x: number;
150150
}
151151
// Message: Types are not permitted on @property in the supplied context.
152+
153+
/**
154+
* Returns a Promise...
155+
*
156+
* @param {number} ms - The number of ...
157+
*/
158+
const sleep = (ms: number): Promise<unknown> => {};
159+
// "jsdoc/no-types": ["error"|"warn", {"contexts":["any"]}]
160+
// Message: Types are not permitted on @param.
161+
162+
/**
163+
* Returns a Promise...
164+
*
165+
* @param {number} ms - The number of ...
166+
*/
167+
export const sleep = (ms: number): Promise<unknown> => {};
168+
// "jsdoc/no-types": ["error"|"warn", {"contexts":["any"]}]
169+
// Message: Types are not permitted on @param.
152170
````
153171

154172

docs/rules/require-example.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,15 @@ function quux (someParam) {
234234
}
235235
// "jsdoc/require-example": ["error"|"warn", {"enableFixer":false}]
236236
// Message: Missing JSDoc @example declaration.
237+
238+
/**
239+
* Returns a Promise...
240+
*
241+
* @param {number} ms - The number of ...
242+
*/
243+
const sleep = (ms: number): Promise<unknown> => {};
244+
// "jsdoc/require-example": ["error"|"warn", {"contexts":["any"]}]
245+
// Message: Missing JSDoc @example declaration.
237246
````
238247

239248

src/iterateJsdoc.js

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ import esquery from 'esquery';
476476
/**
477477
* @typedef {BasicUtils & {
478478
* isIteratingFunction: IsIteratingFunction,
479+
* isIteratingFunctionOrVariable: IsIteratingFunction,
479480
* isVirtualFunction: IsVirtualFunction,
480481
* stringify: Stringify,
481482
* reportJSDoc: ReportJSDoc,
@@ -716,14 +717,36 @@ const getUtils = (
716717
tagNamePreference,
717718
} = settings;
718719

720+
const functionTypes = [
721+
'ArrowFunctionExpression',
722+
'FunctionDeclaration',
723+
'FunctionExpression',
724+
'MethodDefinition',
725+
];
726+
719727
/** @type {IsIteratingFunction} */
720728
utils.isIteratingFunction = () => {
721-
return !iteratingAll || [
722-
'ArrowFunctionExpression',
723-
'FunctionDeclaration',
724-
'FunctionExpression',
725-
'MethodDefinition',
726-
].includes(String(node && node.type));
729+
return !iteratingAll || functionTypes.includes(String(node?.type));
730+
};
731+
732+
/** @type {IsIteratingFunction} */
733+
utils.isIteratingFunctionOrVariable = () => {
734+
if (utils.isIteratingFunction()) {
735+
return true;
736+
}
737+
738+
/** @type {import('estree').VariableDeclarator[]} */
739+
const declarations = node?.type === 'VariableDeclaration' ?
740+
node.declarations :
741+
(node?.type === 'ExportNamedDeclaration' && node.declaration?.type === 'VariableDeclaration' ?
742+
node.declaration.declarations :
743+
[]);
744+
745+
return declarations.some(({
746+
init,
747+
}) => {
748+
return functionTypes.includes(String(init?.type));
749+
});
727750
};
728751

729752
/** @type {IsVirtualFunction} */

src/rules/implementsOnClasses.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default iterateJsdoc(({
44
report,
55
utils,
66
}) => {
7-
const iteratingFunction = utils.isIteratingFunction();
7+
const iteratingFunction = utils.isIteratingFunctionOrVariable();
88

99
if (iteratingFunction) {
1010
if (utils.hasATag([

src/rules/noTypes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default iterateJsdoc(({
1414
node,
1515
utils,
1616
}) => {
17-
if (!utils.isIteratingFunction() && !utils.isVirtualFunction()) {
17+
if (!utils.isIteratingFunctionOrVariable() && !utils.isVirtualFunction()) {
1818
return;
1919
}
2020

src/rules/requireExample.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default iterateJsdoc(({
2424
});
2525

2626
if (!functionExamples.length) {
27-
if (exemptNoArguments && utils.isIteratingFunction() &&
27+
if (exemptNoArguments && utils.isIteratingFunctionOrVariable() &&
2828
!utils.hasParams()
2929
) {
3030
return;

test/rules/assertions/noTypes.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,74 @@ export default /** @type {import('../index.js').TestCases} */ ({
286286
}
287287
`,
288288
},
289+
{
290+
code: `
291+
/**
292+
* Returns a Promise...
293+
*
294+
* @param {number} ms - The number of ...
295+
*/
296+
const sleep = (ms: number): Promise<unknown> => {};
297+
`,
298+
errors: [
299+
{
300+
line: 5,
301+
message: 'Types are not permitted on @param.',
302+
},
303+
],
304+
languageOptions: {
305+
parser: typescriptEslintParser,
306+
},
307+
options: [
308+
{
309+
contexts: [
310+
'any',
311+
],
312+
},
313+
],
314+
output: `
315+
/**
316+
* Returns a Promise...
317+
*
318+
* @param ms - The number of ...
319+
*/
320+
const sleep = (ms: number): Promise<unknown> => {};
321+
`,
322+
},
323+
{
324+
code: `
325+
/**
326+
* Returns a Promise...
327+
*
328+
* @param {number} ms - The number of ...
329+
*/
330+
export const sleep = (ms: number): Promise<unknown> => {};
331+
`,
332+
errors: [
333+
{
334+
line: 5,
335+
message: 'Types are not permitted on @param.',
336+
},
337+
],
338+
languageOptions: {
339+
parser: typescriptEslintParser,
340+
},
341+
options: [
342+
{
343+
contexts: [
344+
'any',
345+
],
346+
},
347+
],
348+
output: `
349+
/**
350+
* Returns a Promise...
351+
*
352+
* @param ms - The number of ...
353+
*/
354+
export const sleep = (ms: number): Promise<unknown> => {};
355+
`,
356+
},
289357
],
290358
valid: [
291359
{

test/rules/assertions/requireExample.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import {
2+
parser as typescriptEslintParser,
3+
} from 'typescript-eslint';
4+
15
export default /** @type {import('../index.js').TestCases} */ ({
26
invalid: [
37
{
@@ -378,6 +382,41 @@ function quux () {
378382
],
379383
output: null,
380384
},
385+
{
386+
code: `
387+
/**
388+
* Returns a Promise...
389+
*
390+
* @param {number} ms - The number of ...
391+
*/
392+
const sleep = (ms: number): Promise<unknown> => {};
393+
`,
394+
errors: [
395+
{
396+
line: 2,
397+
message: 'Missing JSDoc @example declaration.',
398+
},
399+
],
400+
languageOptions: {
401+
parser: typescriptEslintParser,
402+
},
403+
options: [
404+
{
405+
contexts: [
406+
'any',
407+
],
408+
},
409+
],
410+
output: `
411+
/**
412+
* Returns a Promise...
413+
*
414+
* @param {number} ms - The number of ...
415+
* @example
416+
*/
417+
const sleep = (ms: number): Promise<unknown> => {};
418+
`,
419+
},
381420
],
382421
valid: [
383422
{

0 commit comments

Comments
 (0)