Skip to content

Commit

Permalink
fix(require-returns-check, require-yields-check): check for undef…
Browse files Browse the repository at this point in the history
…ined/void within union; fixes #925
  • Loading branch information
brettz9 committed Oct 24, 2022
1 parent 12da503 commit cfbdf8b
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 2 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18141,6 +18141,16 @@ function getTrue() {
console.log('returning...');
}
}

/**
* Maybe return a boolean.
* @returns {boolean|void} true, or undefined.
*/
function maybeTrue() {
if (Math.random() > 0.5) {
return true;
}
}
````


Expand Down
2 changes: 1 addition & 1 deletion src/iterateJsdoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ const getUtils = (
};

utils.hasDefinedTypeTag = (tag) => {
return jsdocUtils.hasDefinedTypeTag(tag);
return jsdocUtils.hasDefinedTypeTag(tag, settings.mode);
};

utils.hasValueOrExecutorHasNonEmptyResolveValue = (anyPromiseAsReturn, allBranches) => {
Expand Down
31 changes: 30 additions & 1 deletion src/jsdocUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/* eslint-disable jsdoc/no-undefined-types */

import {
tryParse,
} from '@es-joy/jsdoccomment';
import WarnSettings from './WarnSettings';
import getDefaultTagStructureForMode from './getDefaultTagStructureForMode';
import {
Expand Down Expand Up @@ -465,21 +468,47 @@ const hasATag = (jsdoc, targetTagNames) => {
*
* @param {JsDocTag} tag
* the tag which should be checked.
* @param {"jsdoc"|"closure"|"typescript"} mode
* @returns {boolean}
* true in case a defined type is declared; otherwise false.
*/
const hasDefinedTypeTag = (tag) => {
const hasDefinedTypeTag = (tag, mode) => {
// The function should not continue in the event the type is not defined...
if (typeof tag === 'undefined' || tag === null) {
return false;
}

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

// Exit early if matching
if (tagType === 'undefined' || tagType === 'void') {
return false;
}

let parsedTypes;
try {
parsedTypes = tryParse(
tagType,
mode === 'permissive' ? undefined : [
mode,
],
);
} catch {
// Ignore
}

if (
// We do not traverse deeply as it could be, e.g., `Promise<void>`
parsedTypes &&
parsedTypes.type === 'JsdocTypeUnion' &&
parsedTypes.elements.find((elem) => {
return elem.type === 'JsdocTypeUndefined' ||
elem.type === 'JsdocTypeName' && elem.value === 'void';
})) {
return false;
}

// In any other case, a type is present
return true;
};
Expand Down
32 changes: 32 additions & 0 deletions test/rules/assertions/requireReturnsCheck.js
Original file line number Diff line number Diff line change
Expand Up @@ -1426,5 +1426,37 @@ export default {
}
`,
},
{
code: `
/**
* Maybe return a boolean.
* @returns {boolean|void} true, or undefined.
*/
function maybeTrue() {
if (Math.random() > 0.5) {
return true;
}
}
`,
},
{
code: `
/**
* Maybe return a boolean.
* @return {boolean|void} true, or undefined.
*/
function maybeTrue() {
if (Math.random() > 0.5) {
return true;
}
}
`,
ignoreReadme: true,
settings: {
jsdoc: {
mode: 'permissive',
},
},
},
],
};

0 comments on commit cfbdf8b

Please sign in to comment.