Skip to content

Commit bdd6af2

Browse files
committedOct 22, 2022
fix(require-returns-check): checks that all branches of final node return; fixes #892
This release expressed as a reversion of a commit (bba377e) in order to fix the commit message to properly trigger a release.
1 parent bba377e commit bdd6af2

File tree

6 files changed

+498
-52
lines changed

6 files changed

+498
-52
lines changed
 

‎.README/rules/require-returns-check.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
Requires a return statement (or non-`undefined` Promise resolve value) in
44
function bodies if a `@returns` tag (without a `void` or `undefined` type)
5-
is specified in the function's jsdoc comment.
5+
is specified in the function's JSDoc comment.
66

77
Will also report `@returns {void}` and `@returns {undefined}` if `exemptAsync`
8-
is set to `false` no non-`undefined` returned or resolved value is found.
8+
is set to `false` and a non-`undefined` value is returned or a resolved value
9+
is found. Also reports if `@returns {never}` is discovered with a return value.
910

1011
Will also report if multiple `@returns` tags are present.
1112

‎README.md

+147-19
Original file line numberDiff line numberDiff line change
@@ -17208,10 +17208,11 @@ The following patterns are not considered problems:
1720817208

1720917209
Requires a return statement (or non-`undefined` Promise resolve value) in
1721017210
function bodies if a `@returns` tag (without a `void` or `undefined` type)
17211-
is specified in the function's jsdoc comment.
17211+
is specified in the function's JSDoc comment.
1721217212

1721317213
Will also report `@returns {void}` and `@returns {undefined}` if `exemptAsync`
17214-
is set to `false` no non-`undefined` returned or resolved value is found.
17214+
is set to `false` and a non-`undefined` value is returned or a resolved value
17215+
is found. Also reports if `@returns {never}` is discovered with a return value.
1721517216

1721617217
Will also report if multiple `@returns` tags are present.
1721717218

@@ -17437,6 +17438,17 @@ export function readFixture(path: string): void;
1743717438
export function readFixture(path: string);
1743817439
// Message: JSDoc @returns declaration present but return expression not available in function.
1743917440

17441+
/**
17442+
* @returns {SomeType}
17443+
*/
17444+
function quux (path) {
17445+
if (true) {
17446+
return;
17447+
}
17448+
return 15;
17449+
};
17450+
// Message: JSDoc @returns declaration present but return expression not available in function.
17451+
1744017452
/**
1744117453
* Reads a test fixture.
1744217454
*
@@ -17449,6 +17461,87 @@ export function readFixture(path: string): void {
1744917461
return;
1745017462
};
1745117463
// Message: JSDoc @returns declaration present but return expression not available in function.
17464+
17465+
/**
17466+
* @returns {true}
17467+
*/
17468+
function quux () {
17469+
if (true) {
17470+
return true;
17471+
}
17472+
}
17473+
// Message: JSDoc @returns declaration present but return expression not available in function.
17474+
17475+
/**
17476+
* @returns {true}
17477+
*/
17478+
function quux () {
17479+
if (true) {
17480+
} else {
17481+
return;
17482+
}
17483+
}
17484+
// Message: JSDoc @returns declaration present but return expression not available in function.
17485+
17486+
/**
17487+
* @returns {true}
17488+
*/
17489+
function quux (someVar) {
17490+
switch (someVar) {
17491+
case 1:
17492+
return true;
17493+
case 2:
17494+
return;
17495+
}
17496+
}
17497+
// Message: JSDoc @returns declaration present but return expression not available in function.
17498+
17499+
/**
17500+
* @returns {boolean}
17501+
*/
17502+
const quux = (someVar) => {
17503+
if (someVar) {
17504+
return true;
17505+
}
17506+
};
17507+
// Message: JSDoc @returns declaration present but return expression not available in function.
17508+
17509+
/**
17510+
* @returns {true}
17511+
*/
17512+
function quux () {
17513+
try {
17514+
return true;
17515+
} catch (error) {
17516+
}
17517+
}
17518+
// Message: JSDoc @returns declaration present but return expression not available in function.
17519+
17520+
/**
17521+
* @returns {true}
17522+
*/
17523+
function quux () {
17524+
try {
17525+
return true;
17526+
} catch (error) {
17527+
return true;
17528+
} finally {
17529+
return;
17530+
}
17531+
}
17532+
// Message: JSDoc @returns declaration present but return expression not available in function.
17533+
17534+
/**
17535+
* @returns {true}
17536+
*/
17537+
function quux () {
17538+
try {
17539+
} catch (error) {
17540+
} finally {
17541+
return true;
17542+
}
17543+
}
17544+
// Message: JSDoc @returns declaration present but return expression not available in function.
1745217545
````
1745317546

1745417547
The following patterns are not considered problems:
@@ -17614,7 +17707,7 @@ function quux () {
1761417707
return true;
1761517708
} catch (err) {
1761617709
}
17617-
return;
17710+
return true;
1761817711
}
1761917712

1762017713
/**
@@ -17625,15 +17718,15 @@ function quux () {
1762517718
} finally {
1762617719
return true;
1762717720
}
17628-
return;
17721+
return true;
1762917722
}
1763017723

1763117724
/**
1763217725
* @returns {true}
1763317726
*/
1763417727
function quux () {
1763517728
try {
17636-
return;
17729+
return true;
1763717730
} catch (err) {
1763817731
}
1763917732
return true;
@@ -17648,7 +17741,7 @@ function quux () {
1764817741
} catch (err) {
1764917742
return true;
1765017743
}
17651-
return;
17744+
return true;
1765217745
}
1765317746

1765417747
/**
@@ -17659,7 +17752,7 @@ function quux () {
1765917752
case 'abc':
1766017753
return true;
1766117754
}
17662-
return;
17755+
return true;
1766317756
}
1766417757

1766517758
/**
@@ -17668,7 +17761,7 @@ function quux () {
1766817761
function quux () {
1766917762
switch (true) {
1767017763
case 'abc':
17671-
return;
17764+
return true;
1767217765
}
1767317766
return true;
1767417767
}
@@ -17680,7 +17773,7 @@ function quux () {
1768017773
for (const i of abc) {
1768117774
return true;
1768217775
}
17683-
return;
17776+
return true;
1768417777
}
1768517778

1768617779
/**
@@ -17696,7 +17789,7 @@ function quux () {
1769617789
* @returns {true}
1769717790
*/
1769817791
function quux () {
17699-
for (let i=0; i<n; i+=1) {
17792+
for (const a of b) {
1770017793
return true;
1770117794
}
1770217795
}
@@ -17705,29 +17798,37 @@ function quux () {
1770517798
* @returns {true}
1770617799
*/
1770717800
function quux () {
17708-
while(true) {
17709-
return true
17801+
loop: for (const a of b) {
17802+
return true;
1771017803
}
1771117804
}
1771217805

1771317806
/**
1771417807
* @returns {true}
1771517808
*/
1771617809
function quux () {
17717-
do {
17810+
for (let i=0; i<n; i+=1) {
17811+
return true;
17812+
}
17813+
}
17814+
17815+
/**
17816+
* @returns {true}
17817+
*/
17818+
function quux () {
17819+
while(true) {
1771817820
return true
1771917821
}
17720-
while(true)
1772117822
}
1772217823

1772317824
/**
1772417825
* @returns {true}
1772517826
*/
1772617827
function quux () {
17727-
if (true) {
17728-
return;
17828+
do {
17829+
return true
1772917830
}
17730-
return true;
17831+
while(true)
1773117832
}
1773217833

1773317834
/**
@@ -17737,6 +17838,7 @@ function quux () {
1773717838
if (true) {
1773817839
return true;
1773917840
}
17841+
return true;
1774017842
}
1774117843

1774217844
/**
@@ -17754,11 +17856,11 @@ function quux () {
1775417856
*/
1775517857
function quux () {
1775617858
if (true) {
17757-
return;
17859+
return true;
1775817860
} else {
1775917861
return true;
1776017862
}
17761-
return;
17863+
return true;
1776217864
}
1776317865

1776417866
/**
@@ -17865,6 +17967,32 @@ export function readFixture(path: string): Promise<Buffer> {
1786517967
* @returns {void} The file contents as buffer.
1786617968
*/
1786717969
export function readFixture(path: string);
17970+
17971+
/**
17972+
* @returns {SomeType}
17973+
*/
17974+
function quux (path) {
17975+
if (true) {
17976+
return 5;
17977+
}
17978+
return 15;
17979+
};
17980+
17981+
/**
17982+
* @returns {*} Foo.
17983+
*/
17984+
const quux = () => new Promise((resolve) => {
17985+
resolve(3);
17986+
});
17987+
17988+
/**
17989+
* @returns {*} Foo.
17990+
*/
17991+
const quux = function () {
17992+
return new Promise((resolve) => {
17993+
resolve(3);
17994+
});
17995+
};
1786817996
````
1786917997

1787017998

‎src/iterateJsdoc.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -680,8 +680,8 @@ const getUtils = (
680680
return jsdocUtils.hasDefinedTypeTag(tag);
681681
};
682682

683-
utils.hasValueOrExecutorHasNonEmptyResolveValue = (anyPromiseAsReturn) => {
684-
return jsdocUtils.hasValueOrExecutorHasNonEmptyResolveValue(node, anyPromiseAsReturn);
683+
utils.hasValueOrExecutorHasNonEmptyResolveValue = (anyPromiseAsReturn, allBranches) => {
684+
return jsdocUtils.hasValueOrExecutorHasNonEmptyResolveValue(node, anyPromiseAsReturn, allBranches);
685685
};
686686

687687
utils.hasYieldValue = () => {

‎src/rules/requireReturnsCheck.js

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ export default iterateJsdoc(({
9696
) &&
9797
!utils.hasValueOrExecutorHasNonEmptyResolveValue(
9898
exemptAsync,
99+
true,
99100
) && (!exemptGenerators || !node.generator)
100101
) {
101102
report(`JSDoc @${tagName} declaration present but return expression not available in function.`);

‎src/utils/hasReturnValue.js

+125-12
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,92 @@ const undefinedKeywords = new Set([
1919
'TSVoidKeyword', 'TSUndefinedKeyword', 'TSNeverKeyword',
2020
]);
2121

22+
/**
23+
* Checks if a node has a return statement. Void return does not count.
24+
*
25+
* @param {object} node
26+
* @param {PromiseFilter} promFilter
27+
* @returns {boolean|Node}
28+
*/
29+
// eslint-disable-next-line complexity
30+
const allBrancheshaveReturnValues = (node, promFilter) => {
31+
if (!node) {
32+
return false;
33+
}
34+
35+
switch (node.type) {
36+
case 'TSDeclareFunction':
37+
case 'TSFunctionType':
38+
case 'TSMethodSignature': {
39+
const type = node?.returnType?.typeAnnotation?.type;
40+
return type && !undefinedKeywords.has(type);
41+
}
42+
43+
// case 'MethodDefinition':
44+
// return allBrancheshaveReturnValues(node.value, promFilter);
45+
case 'FunctionExpression':
46+
case 'FunctionDeclaration':
47+
case 'ArrowFunctionExpression': {
48+
return node.expression && (!isNewPromiseExpression(node.body) || !isVoidPromise(node.body)) ||
49+
allBrancheshaveReturnValues(node.body, promFilter);
50+
}
51+
52+
case 'BlockStatement': {
53+
const lastBodyNode = node.body.slice(-1)[0];
54+
return allBrancheshaveReturnValues(lastBodyNode, promFilter);
55+
}
56+
57+
case 'LabeledStatement':
58+
case 'WhileStatement':
59+
case 'DoWhileStatement':
60+
case 'ForStatement':
61+
case 'ForInStatement':
62+
case 'ForOfStatement':
63+
case 'WithStatement': {
64+
return allBrancheshaveReturnValues(node.body, promFilter);
65+
}
66+
67+
case 'IfStatement': {
68+
return allBrancheshaveReturnValues(node.consequent, promFilter) && allBrancheshaveReturnValues(node.alternate, promFilter);
69+
}
70+
71+
case 'TryStatement': {
72+
return allBrancheshaveReturnValues(node.block, promFilter) &&
73+
allBrancheshaveReturnValues(node.handler && node.handler.body, promFilter) &&
74+
allBrancheshaveReturnValues(node.finalizer, promFilter);
75+
}
76+
77+
case 'SwitchStatement': {
78+
return node.cases.every(
79+
(someCase) => {
80+
return someCase.consequent.every((nde) => {
81+
return allBrancheshaveReturnValues(nde, promFilter);
82+
});
83+
},
84+
);
85+
}
86+
87+
case 'ReturnStatement': {
88+
// void return does not count.
89+
if (node.argument === null) {
90+
return false;
91+
}
92+
93+
if (promFilter && isNewPromiseExpression(node.argument)) {
94+
// Let caller decide how to filter, but this is, at the least,
95+
// a return of sorts and truthy
96+
return promFilter(node.argument);
97+
}
98+
99+
return true;
100+
}
101+
102+
default: {
103+
return false;
104+
}
105+
}
106+
};
107+
22108
/**
23109
* @callback PromiseFilter
24110
* @param {object} node
@@ -29,11 +115,12 @@ const undefinedKeywords = new Set([
29115
* Checks if a node has a return statement. Void return does not count.
30116
*
31117
* @param {object} node
118+
* @param {boolean} throwOnNullReturn
32119
* @param {PromiseFilter} promFilter
33120
* @returns {boolean|Node}
34121
*/
35122
// eslint-disable-next-line complexity
36-
const hasReturnValue = (node, promFilter) => {
123+
const hasReturnValue = (node, throwOnNullReturn, promFilter) => {
37124
if (!node) {
38125
return false;
39126
}
@@ -47,17 +134,17 @@ const hasReturnValue = (node, promFilter) => {
47134
}
48135

49136
case 'MethodDefinition':
50-
return hasReturnValue(node.value, promFilter);
137+
return hasReturnValue(node.value, throwOnNullReturn, promFilter);
51138
case 'FunctionExpression':
52139
case 'FunctionDeclaration':
53140
case 'ArrowFunctionExpression': {
54141
return node.expression && (!isNewPromiseExpression(node.body) || !isVoidPromise(node.body)) ||
55-
hasReturnValue(node.body, promFilter);
142+
hasReturnValue(node.body, throwOnNullReturn, promFilter);
56143
}
57144

58145
case 'BlockStatement': {
59146
return node.body.some((bodyNode) => {
60-
return bodyNode.type !== 'FunctionDeclaration' && hasReturnValue(bodyNode, promFilter);
147+
return bodyNode.type !== 'FunctionDeclaration' && hasReturnValue(bodyNode, throwOnNullReturn, promFilter);
61148
});
62149
}
63150

@@ -68,24 +155,25 @@ const hasReturnValue = (node, promFilter) => {
68155
case 'ForInStatement':
69156
case 'ForOfStatement':
70157
case 'WithStatement': {
71-
return hasReturnValue(node.body, promFilter);
158+
return hasReturnValue(node.body, throwOnNullReturn, promFilter);
72159
}
73160

74161
case 'IfStatement': {
75-
return hasReturnValue(node.consequent, promFilter) || hasReturnValue(node.alternate, promFilter);
162+
return hasReturnValue(node.consequent, throwOnNullReturn, promFilter) ||
163+
hasReturnValue(node.alternate, throwOnNullReturn, promFilter);
76164
}
77165

78166
case 'TryStatement': {
79-
return hasReturnValue(node.block, promFilter) ||
80-
hasReturnValue(node.handler && node.handler.body, promFilter) ||
81-
hasReturnValue(node.finalizer, promFilter);
167+
return hasReturnValue(node.block, throwOnNullReturn, promFilter) ||
168+
hasReturnValue(node.handler && node.handler.body, throwOnNullReturn, promFilter) ||
169+
hasReturnValue(node.finalizer, throwOnNullReturn, promFilter);
82170
}
83171

84172
case 'SwitchStatement': {
85173
return node.cases.some(
86174
(someCase) => {
87175
return someCase.consequent.some((nde) => {
88-
return hasReturnValue(nde, promFilter);
176+
return hasReturnValue(nde, throwOnNullReturn, promFilter);
89177
});
90178
},
91179
);
@@ -94,6 +182,10 @@ const hasReturnValue = (node, promFilter) => {
94182
case 'ReturnStatement': {
95183
// void return does not count.
96184
if (node.argument === null) {
185+
if (throwOnNullReturn) {
186+
throw new Error('Null return');
187+
}
188+
97189
return false;
98190
}
99191

@@ -320,10 +412,31 @@ const hasNonEmptyResolverCall = (node, resolverName) => {
320412
*
321413
* @param {object} node
322414
* @param {boolean} anyPromiseAsReturn
415+
* @param {boolean} allBranches
323416
* @returns {boolean}
324417
*/
325-
const hasValueOrExecutorHasNonEmptyResolveValue = (node, anyPromiseAsReturn) => {
326-
return hasReturnValue(node, (prom) => {
418+
const hasValueOrExecutorHasNonEmptyResolveValue = (node, anyPromiseAsReturn, allBranches) => {
419+
const hasReturnMethod = allBranches ?
420+
(nde, promiseFilter) => {
421+
try {
422+
hasReturnValue(nde, true, promiseFilter);
423+
} catch (error) {
424+
// istanbul ignore else
425+
if (error.message === 'Null return') {
426+
return false;
427+
}
428+
429+
// istanbul ignore next
430+
throw error;
431+
}
432+
433+
return allBrancheshaveReturnValues(nde, promiseFilter);
434+
} :
435+
(nde, promiseFilter) => {
436+
return hasReturnValue(nde, false, promiseFilter);
437+
};
438+
439+
return hasReturnMethod(node, (prom) => {
327440
if (anyPromiseAsReturn) {
328441
return true;
329442
}

‎test/rules/assertions/requireReturnsCheck.js

+220-17
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,25 @@ export default {
411411
],
412412
parser: require.resolve('@typescript-eslint/parser'),
413413
},
414+
{
415+
code: `
416+
/**
417+
* @returns {SomeType}
418+
*/
419+
function quux (path) {
420+
if (true) {
421+
return;
422+
}
423+
return 15;
424+
};
425+
`,
426+
errors: [
427+
{
428+
line: 2,
429+
message: 'JSDoc @returns declaration present but return expression not available in function.',
430+
},
431+
],
432+
},
414433
{
415434
code: `
416435
/**
@@ -433,6 +452,143 @@ export default {
433452
],
434453
parser: require.resolve('@typescript-eslint/parser'),
435454
},
455+
{
456+
code: `
457+
/**
458+
* @returns {true}
459+
*/
460+
function quux () {
461+
if (true) {
462+
return true;
463+
}
464+
}
465+
`,
466+
errors: [
467+
{
468+
line: 2,
469+
message: 'JSDoc @returns declaration present but return expression not available in function.',
470+
},
471+
],
472+
},
473+
{
474+
code: `
475+
/**
476+
* @returns {true}
477+
*/
478+
function quux () {
479+
if (true) {
480+
} else {
481+
return;
482+
}
483+
}
484+
`,
485+
errors: [
486+
{
487+
line: 2,
488+
message: 'JSDoc @returns declaration present but return expression not available in function.',
489+
},
490+
],
491+
},
492+
{
493+
code: `
494+
/**
495+
* @returns {true}
496+
*/
497+
function quux (someVar) {
498+
switch (someVar) {
499+
case 1:
500+
return true;
501+
case 2:
502+
return;
503+
}
504+
}
505+
`,
506+
errors: [
507+
{
508+
line: 2,
509+
message: 'JSDoc @returns declaration present but return expression not available in function.',
510+
},
511+
],
512+
},
513+
{
514+
code: `
515+
/**
516+
* @returns {boolean}
517+
*/
518+
const quux = (someVar) => {
519+
if (someVar) {
520+
return true;
521+
}
522+
};
523+
`,
524+
errors: [
525+
{
526+
line: 2,
527+
message: 'JSDoc @returns declaration present but return expression not available in function.',
528+
},
529+
],
530+
},
531+
{
532+
code: `
533+
/**
534+
* @returns {true}
535+
*/
536+
function quux () {
537+
try {
538+
return true;
539+
} catch (error) {
540+
}
541+
}
542+
`,
543+
errors: [
544+
{
545+
line: 2,
546+
message: 'JSDoc @returns declaration present but return expression not available in function.',
547+
},
548+
],
549+
},
550+
{
551+
code: `
552+
/**
553+
* @returns {true}
554+
*/
555+
function quux () {
556+
try {
557+
return true;
558+
} catch (error) {
559+
return true;
560+
} finally {
561+
return;
562+
}
563+
}
564+
`,
565+
errors: [
566+
{
567+
line: 2,
568+
message: 'JSDoc @returns declaration present but return expression not available in function.',
569+
},
570+
],
571+
},
572+
{
573+
code: `
574+
/**
575+
* @returns {true}
576+
*/
577+
function quux () {
578+
try {
579+
} catch (error) {
580+
} finally {
581+
return true;
582+
}
583+
}
584+
`,
585+
errors: [
586+
{
587+
line: 2,
588+
message: 'JSDoc @returns declaration present but return expression not available in function.',
589+
},
590+
],
591+
},
436592
],
437593
valid: [
438594
{
@@ -676,7 +832,7 @@ export default {
676832
return true;
677833
} catch (err) {
678834
}
679-
return;
835+
return true;
680836
}
681837
`,
682838
},
@@ -690,7 +846,7 @@ export default {
690846
} finally {
691847
return true;
692848
}
693-
return;
849+
return true;
694850
}
695851
`,
696852
},
@@ -701,7 +857,7 @@ export default {
701857
*/
702858
function quux () {
703859
try {
704-
return;
860+
return true;
705861
} catch (err) {
706862
}
707863
return true;
@@ -719,7 +875,7 @@ export default {
719875
} catch (err) {
720876
return true;
721877
}
722-
return;
878+
return true;
723879
}
724880
`,
725881
},
@@ -733,7 +889,7 @@ export default {
733889
case 'abc':
734890
return true;
735891
}
736-
return;
892+
return true;
737893
}
738894
`,
739895
},
@@ -745,7 +901,7 @@ export default {
745901
function quux () {
746902
switch (true) {
747903
case 'abc':
748-
return;
904+
return true;
749905
}
750906
return true;
751907
}
@@ -760,7 +916,7 @@ export default {
760916
for (const i of abc) {
761917
return true;
762918
}
763-
return;
919+
return true;
764920
}
765921
`,
766922
},
@@ -782,7 +938,7 @@ export default {
782938
* @returns {true}
783939
*/
784940
function quux () {
785-
for (let i=0; i<n; i+=1) {
941+
for (const a of b) {
786942
return true;
787943
}
788944
}
@@ -794,8 +950,8 @@ export default {
794950
* @returns {true}
795951
*/
796952
function quux () {
797-
while(true) {
798-
return true
953+
loop: for (const a of b) {
954+
return true;
799955
}
800956
}
801957
`,
@@ -806,10 +962,21 @@ export default {
806962
* @returns {true}
807963
*/
808964
function quux () {
809-
do {
965+
for (let i=0; i<n; i+=1) {
966+
return true;
967+
}
968+
}
969+
`,
970+
},
971+
{
972+
code: `
973+
/**
974+
* @returns {true}
975+
*/
976+
function quux () {
977+
while(true) {
810978
return true
811979
}
812-
while(true)
813980
}
814981
`,
815982
},
@@ -819,10 +986,10 @@ export default {
819986
* @returns {true}
820987
*/
821988
function quux () {
822-
if (true) {
823-
return;
989+
do {
990+
return true
824991
}
825-
return true;
992+
while(true)
826993
}
827994
`,
828995
},
@@ -835,6 +1002,7 @@ export default {
8351002
if (true) {
8361003
return true;
8371004
}
1005+
return true;
8381006
}
8391007
`,
8401008
},
@@ -858,11 +1026,11 @@ export default {
8581026
*/
8591027
function quux () {
8601028
if (true) {
861-
return;
1029+
return true;
8621030
} else {
8631031
return true;
8641032
}
865-
return;
1033+
return true;
8661034
}
8671035
`,
8681036
},
@@ -1057,5 +1225,40 @@ export default {
10571225
`,
10581226
parser: require.resolve('@typescript-eslint/parser'),
10591227
},
1228+
{
1229+
code: `
1230+
/**
1231+
* @returns {SomeType}
1232+
*/
1233+
function quux (path) {
1234+
if (true) {
1235+
return 5;
1236+
}
1237+
return 15;
1238+
};
1239+
`,
1240+
},
1241+
{
1242+
code: `
1243+
/**
1244+
* @returns {*} Foo.
1245+
*/
1246+
const quux = () => new Promise((resolve) => {
1247+
resolve(3);
1248+
});
1249+
`,
1250+
},
1251+
{
1252+
code: `
1253+
/**
1254+
* @returns {*} Foo.
1255+
*/
1256+
const quux = function () {
1257+
return new Promise((resolve) => {
1258+
resolve(3);
1259+
});
1260+
};
1261+
`,
1262+
},
10601263
],
10611264
};

0 commit comments

Comments
 (0)
Please sign in to comment.