Skip to content

Commit ea8b0f7

Browse files
committed
fix(require-returns, require-returns-check): properly handle catch
refactor: Don't need undefined tag checks in `hasDefinedTypeReturnTag` testing(jsdocUtils): `getFunctionParameterNames` and `hasDefinedTypeReturnTag` for full coverage testing(require-returns-check): Complete coverage (try/switch/for/if/else branches)
1 parent 5129f67 commit ea8b0f7

File tree

3 files changed

+168
-4
lines changed

3 files changed

+168
-4
lines changed

src/jsdocUtils.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ const lookupTable = {
262262
return node.type === 'ReturnStatement';
263263
},
264264
check (node) {
265+
/* istanbul ignore next */
265266
if (!lookupTable.ReturnStatement.is(node)) {
266267
return false;
267268
}
@@ -280,6 +281,7 @@ const lookupTable = {
280281
return node.type === 'IfStatement';
281282
},
282283
check (node) {
284+
/* istanbul ignore next */
283285
if (!lookupTable.IfStatement.is(node)) {
284286
return false;
285287
}
@@ -324,6 +326,7 @@ const lookupTable = {
324326
return node.type === 'TryStatement';
325327
},
326328
check (node) {
329+
/* istanbul ignore next */
327330
if (!lookupTable.TryStatement.is(node)) {
328331
return false;
329332
}
@@ -332,12 +335,11 @@ const lookupTable = {
332335
return true;
333336
}
334337

335-
if (node.handler && node.handler.block) {
336-
if (lookupTable['@default'].check(node)) {
338+
if (node.handler && node.handler.body) {
339+
if (lookupTable['@default'].check(node.handler.body)) {
337340
return true;
338341
}
339342
}
340-
341343
if (lookupTable.BlockStatement.check(node.finalizer)) {
342344
return true;
343345
}
@@ -351,10 +353,12 @@ const lookupTable = {
351353
},
352354
check (node, context) {
353355
// E.g. the catch block statement is optional.
356+
/* istanbul ignore next */
354357
if (typeof node === 'undefined' || node === null) {
355358
return false;
356359
}
357360

361+
/* istanbul ignore next */
358362
if (!lookupTable.BlockStatement.is(node)) {
359363
return false;
360364
}
@@ -411,10 +415,12 @@ const lookupTable = {
411415
}
412416

413417
// Everything else cannot return anything.
418+
/* istanbul ignore next */
414419
if (RETURNFREE_STATEMENTS.includes(node.type)) {
415420
return false;
416421
}
417422

423+
/* istanbul ignore next */
418424
// If we end up here, we stumbled upon an unknown element.
419425
// Most likely it is enough to add it to the blacklist.
420426
//
@@ -444,7 +450,7 @@ const hasReturnValue = (node, context, ignoreAsync) => {
444450
return lookupTable[item].check(node, context, ignoreAsync);
445451
}
446452
}
447-
453+
/* istanbul ignore next */
448454
throw new Error('Unknown element ' + node.type);
449455
};
450456

test/jsdocUtils.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,24 @@ describe('jsdocUtils', () => {
4545
});
4646
});
4747
});
48+
describe('getFunctionParameterNames()', () => {
49+
context('Unhandled param type', () => {
50+
it('should throw with an unknown param type', () => {
51+
expect(() => {
52+
jsdocUtils.getFunctionParameterNames({params: [
53+
{
54+
type: 'AssignmentPattern'
55+
}
56+
]});
57+
}).to.throw('Unsupported function signature format.');
58+
});
59+
});
60+
});
61+
describe('hasDefinedTypeReturnTag()', () => {
62+
context('Missing tag', () => {
63+
it('should return `false` with a missing tag', () => {
64+
expect(jsdocUtils.hasDefinedTypeReturnTag(null)).to.equal(false);
65+
});
66+
});
67+
});
4868
});

test/rules/assertions/requireReturnsCheck.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,144 @@ export default {
280280
return;
281281
}
282282
`
283+
},
284+
{
285+
code: `
286+
/**
287+
* @returns {true}
288+
*/
289+
function quux () {
290+
try {
291+
return true;
292+
} catch (err) {
293+
}
294+
return;
295+
}
296+
`
297+
},
298+
{
299+
code: `
300+
/**
301+
* @returns {true}
302+
*/
303+
function quux () {
304+
try {
305+
} finally {
306+
return true;
307+
}
308+
return;
309+
}
310+
`
311+
},
312+
{
313+
code: `
314+
/**
315+
* @returns {true}
316+
*/
317+
function quux () {
318+
try {
319+
return;
320+
} catch (err) {
321+
}
322+
return true;
323+
}
324+
`
325+
},
326+
{
327+
code: `
328+
/**
329+
* @returns {true}
330+
*/
331+
function quux () {
332+
try {
333+
something();
334+
} catch (err) {
335+
return true;
336+
}
337+
return;
338+
}
339+
`
340+
},
341+
{
342+
code: `
343+
/**
344+
* @returns {true}
345+
*/
346+
function quux () {
347+
switch (true) {
348+
case 'abc':
349+
return true;
350+
}
351+
return;
352+
}
353+
`
354+
},
355+
{
356+
code: `
357+
/**
358+
* @returns {true}
359+
*/
360+
function quux () {
361+
switch (true) {
362+
case 'abc':
363+
return;
364+
}
365+
return true;
366+
}
367+
`
368+
},
369+
{
370+
code: `
371+
/**
372+
* @returns {true}
373+
*/
374+
function quux () {
375+
for (const i of abc) {
376+
return true;
377+
}
378+
return;
379+
}
380+
`
381+
},
382+
{
383+
code: `
384+
/**
385+
* @returns {true}
386+
*/
387+
function quux () {
388+
if (true) {
389+
return;
390+
}
391+
return true;
392+
}
393+
`
394+
},
395+
{
396+
code: `
397+
/**
398+
* @returns {true}
399+
*/
400+
function quux () {
401+
if (true) {
402+
return true;
403+
}
404+
}
405+
`
406+
},
407+
{
408+
code: `
409+
/**
410+
* @returns {true}
411+
*/
412+
function quux () {
413+
if (true) {
414+
return;
415+
} else {
416+
return true;
417+
}
418+
return;
419+
}
420+
`
283421
}
284422
]
285423
};

0 commit comments

Comments
 (0)