Skip to content

Commit e0f4862

Browse files
committed
fix(require-returns-check, require-yields-check): allow * and any types to avoid reporting of missing return; fixes #950
1 parent 2c42830 commit e0f4862

File tree

7 files changed

+48
-22
lines changed

7 files changed

+48
-22
lines changed

README.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17875,7 +17875,7 @@ function quux () {
1787517875
}
1787617876

1787717877
/**
17878-
* @returns {*} Foo.
17878+
* @returns {SomeType} Foo.
1787917879
*/
1788017880
const quux = () => foo;
1788117881

@@ -18276,14 +18276,14 @@ function quux (path) {
1827618276
};
1827718277

1827818278
/**
18279-
* @returns {*} Foo.
18279+
* @returns {SomeType} Foo.
1828018280
*/
1828118281
const quux = () => new Promise((resolve) => {
1828218282
resolve(3);
1828318283
});
1828418284

1828518285
/**
18286-
* @returns {*} Foo.
18286+
* @returns {SomeType} Foo.
1828718287
*/
1828818288
const quux = function () {
1828918289
return new Promise((resolve) => {
@@ -18420,6 +18420,16 @@ export function f(): string {
1842018420

1842118421
interface I {}
1842218422
}
18423+
18424+
/**
18425+
* @param {boolean} bar A fun variable.
18426+
* @returns {*} Anything at all!
18427+
*/
18428+
function foo( bar ) {
18429+
if ( bar ) {
18430+
return functionWithUnknownReturnType();
18431+
}
18432+
}
1842318433
````
1842418434

1842518435

src/iterateJsdoc.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -724,8 +724,8 @@ const getUtils = (
724724
return jsdocUtils.getTagStructureForMode(mde, settings.structuredTags);
725725
};
726726

727-
utils.hasDefinedTypeTag = (tag) => {
728-
return jsdocUtils.hasDefinedTypeTag(tag, settings.mode);
727+
utils.mayBeUndefinedTypeTag = (tag) => {
728+
return jsdocUtils.mayBeUndefinedTypeTag(tag, settings.mode);
729729
};
730730

731731
utils.hasValueOrExecutorHasNonEmptyResolveValue = (anyPromiseAsReturn, allBranches) => {

src/jsdocUtils.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -464,26 +464,29 @@ const hasATag = (jsdoc, targetTagNames) => {
464464
};
465465

466466
/**
467-
* Checks if the JSDoc comment declares a defined type.
467+
* Checks if the JSDoc comment has an undefined type.
468468
*
469469
* @param {JsDocTag} tag
470470
* the tag which should be checked.
471471
* @param {"jsdoc"|"closure"|"typescript"} mode
472472
* @returns {boolean}
473-
* true in case a defined type is declared; otherwise false.
473+
* true in case a defined type is undeclared; otherwise false.
474474
*/
475-
const hasDefinedTypeTag = (tag, mode) => {
475+
const mayBeUndefinedTypeTag = (tag, mode) => {
476476
// The function should not continue in the event the type is not defined...
477477
if (typeof tag === 'undefined' || tag === null) {
478-
return false;
478+
return true;
479479
}
480480

481481
// .. same applies if it declares an `{undefined}` or `{void}` type
482482
const tagType = tag.type.trim();
483483

484484
// Exit early if matching
485-
if (tagType === 'undefined' || tagType === 'void') {
486-
return false;
485+
if (
486+
tagType === 'undefined' || tagType === 'void' ||
487+
tagType === '*' || tagType === 'any'
488+
) {
489+
return true;
487490
}
488491

489492
let parsedTypes;
@@ -506,11 +509,11 @@ const hasDefinedTypeTag = (tag, mode) => {
506509
return elem.type === 'JsdocTypeUndefined' ||
507510
elem.type === 'JsdocTypeName' && elem.value === 'void';
508511
})) {
509-
return false;
512+
return true;
510513
}
511514

512515
// In any other case, a type is present
513-
return true;
516+
return false;
514517
};
515518

516519
/**
@@ -1239,7 +1242,6 @@ export default {
12391242
getTagsByType,
12401243
getTagStructureForMode,
12411244
hasATag,
1242-
hasDefinedTypeTag,
12431245
hasParams,
12441246
hasReturnValue,
12451247
hasTag,
@@ -1251,6 +1253,7 @@ export default {
12511253
isNamepathDefiningTag,
12521254
isSetter,
12531255
isValidTag,
1256+
mayBeUndefinedTypeTag,
12541257
overrideTagStructure,
12551258
parseClosureTemplateTag,
12561259
pathDoesNotBeginWith,

src/rules/requireReturnsCheck.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export default iterateJsdoc(({
9292
!returnNever &&
9393
(
9494
reportMissingReturnForUndefinedTypes ||
95-
utils.hasDefinedTypeTag(tag)
95+
!utils.mayBeUndefinedTypeTag(tag)
9696
) &&
9797
!utils.hasValueOrExecutorHasNonEmptyResolveValue(
9898
exemptAsync,

src/rules/requireYieldsCheck.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export default iterateJsdoc(({
9090
return true;
9191
}
9292

93-
return utils.hasDefinedTypeTag(yieldTag) && !utils.hasYieldValue();
93+
return !utils.mayBeUndefinedTypeTag(yieldTag) && !utils.hasYieldValue();
9494
};
9595

9696
// In case a yield value is declared in JSDoc, we also expect one in the code.
@@ -120,7 +120,7 @@ export default iterateJsdoc(({
120120
return true;
121121
}
122122

123-
return utils.hasDefinedTypeTag(nextTag) && !utils.hasYieldReturnValue();
123+
return !utils.mayBeUndefinedTypeTag(nextTag) && !utils.hasYieldReturnValue();
124124
};
125125

126126
if (shouldReportNext()) {

test/jsdocUtils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@ describe('jsdocUtils', () => {
6868
});
6969
});
7070
});
71-
describe('hasDefinedTypeTag()', () => {
71+
describe('mayBeUndefinedTypeTag()', () => {
7272
context('Missing tag', () => {
7373
it('should return `false` with a missing tag', () => {
74-
expect(jsdocUtils.hasDefinedTypeTag(null)).to.equal(false);
74+
expect(jsdocUtils.mayBeUndefinedTypeTag(null)).to.equal(true);
7575
});
7676
});
7777
});

test/rules/assertions/requireReturnsCheck.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@ export default {
701701
{
702702
code: `
703703
/**
704-
* @returns {*} Foo.
704+
* @returns {SomeType} Foo.
705705
*/
706706
const quux = () => foo;
707707
`,
@@ -1306,7 +1306,7 @@ export default {
13061306
{
13071307
code: `
13081308
/**
1309-
* @returns {*} Foo.
1309+
* @returns {SomeType} Foo.
13101310
*/
13111311
const quux = () => new Promise((resolve) => {
13121312
resolve(3);
@@ -1316,7 +1316,7 @@ export default {
13161316
{
13171317
code: `
13181318
/**
1319-
* @returns {*} Foo.
1319+
* @returns {SomeType} Foo.
13201320
*/
13211321
const quux = function () {
13221322
return new Promise((resolve) => {
@@ -1505,5 +1505,18 @@ export default {
15051505
`,
15061506
parser: require.resolve('@typescript-eslint/parser'),
15071507
},
1508+
{
1509+
code: `
1510+
/**
1511+
* @param {boolean} bar A fun variable.
1512+
* @returns {*} Anything at all!
1513+
*/
1514+
function foo( bar ) {
1515+
if ( bar ) {
1516+
return functionWithUnknownReturnType();
1517+
}
1518+
}
1519+
`,
1520+
},
15081521
],
15091522
};

0 commit comments

Comments
 (0)