{"version":3,"file":"requireReturnsCheck.cjs","names":["iterateJsdoc","getDocumentNamepathDefiningTags","tryParseType","traverse","strictNativeTypes"],"sources":["../../src/rules/requireReturnsCheck.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\nimport {\n  getDocumentNamepathDefiningTags,\n  strictNativeTypes,\n} from '../jsdocUtils.js';\nimport {\n  traverse,\n  tryParse as tryParseType,\n} from '@es-joy/jsdoccomment';\n\n/**\n * @type {Partial<Record<import('../jsdocUtils.js').ParserMode, import('jsdoc-type-pratt-parser').ParseMode[]>>}\n */\nconst parseTypeModes = {\n  closure: [\n    'closure',\n  ],\n  jsdoc: [\n    'jsdoc',\n  ],\n  typescript: [\n    'typescript',\n  ],\n};\n\n/**\n * @param {import('../iterateJsdoc.js').Utils} utils\n * @param {import('../iterateJsdoc.js').Settings} settings\n * @returns {boolean}\n */\nconst canSkip = (utils, settings) => {\n  const voidingTags = [\n    // An abstract function is by definition incomplete\n    // so it is perfectly fine if a return is documented but\n    // not present within the function.\n    // A subclass may inherit the doc and implement the\n    // missing return.\n    'abstract',\n    'virtual',\n\n    // A constructor function returns `this` by default, so may be `@returns`\n    //   tag indicating this but no explicit return\n    'class',\n    'constructor',\n    'interface',\n  ];\n\n  if (settings.mode === 'closure') {\n    // Structural Interface in GCC terms, equivalent to @interface tag as far as this rule is concerned\n    voidingTags.push('record');\n  }\n\n  return utils.hasATag(voidingTags) ||\n    utils.isConstructor() ||\n    utils.classHasTag('interface') ||\n    settings.mode === 'closure' && utils.classHasTag('record');\n};\n\n/**\n * @param {import('jsdoc-type-pratt-parser').RootResult} parsedType\n * @returns {import('jsdoc-type-pratt-parser').RootResult}\n */\nconst getReturnTypeLevelNode = (parsedType) => {\n  return parsedType.type === 'JsdocTypeParenthesis' ?\n    parsedType.element :\n    parsedType;\n};\n\n/**\n * @param {import('eslint').Rule.RuleContext} context\n * @param {import('../jsdocUtils.js').ParserMode} mode\n * @returns {import('../jsdocUtils.js').ParserMode}\n */\nconst getParseMode = (context, mode) => {\n  const {\n    jsdoc,\n  } = /** @type {{jsdoc?: {mode?: import('../jsdocUtils.js').ParserMode}}} */ (context.settings);\n\n  return jsdoc?.mode ?? mode;\n};\n\nexport default iterateJsdoc(({\n  context,\n  node,\n  report,\n  settings,\n  sourceCode,\n  utils,\n}) => {\n  const {\n    exemptAsync = true,\n    exemptGenerators = settings.mode === 'typescript',\n    noNativeTypes = true,\n    reportMissingReturnForUndefinedTypes = false,\n  } = context.options[0] || {};\n  const {\n    mode,\n  } = settings;\n  const parseMode = getParseMode(context, mode);\n\n  if (canSkip(utils, settings)) {\n    return;\n  }\n\n  const isAsync = utils.isAsync();\n  if (exemptAsync && isAsync) {\n    return;\n  }\n\n  const tagName = /** @type {string} */ (utils.getPreferredTagName({\n    tagName: 'returns',\n  }));\n  if (!tagName) {\n    return;\n  }\n\n  const tags = utils.getTags(tagName);\n\n  if (tags.length === 0) {\n    return;\n  }\n\n  if (tags.length > 1) {\n    report(`Found more than one @${tagName} declaration.`);\n\n    return;\n  }\n\n  const [\n    tag,\n  ] = tags;\n\n  const type = tag.type.trim();\n\n  // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions\n  if (/asserts\\s/v.test(type)) {\n    return;\n  }\n\n  const returnNever = type === 'never';\n  const typedefs = getDocumentNamepathDefiningTags(sourceCode);\n\n  /**\n   * @param {import('comment-parser').Spec} returnTag\n   * @returns {boolean}\n   */\n  const mayReturnUndefined = (returnTag) => {\n    if (utils.mayBeUndefinedTypeTag(returnTag)) {\n      return true;\n    }\n\n    const returnType = returnTag.type.trim();\n    let parsedType;\n    try {\n      parsedType = tryParseType(returnType, parseTypeModes[parseMode]);\n    } catch {\n      return false;\n    }\n\n    const returnTypeLevelNode = getReturnTypeLevelNode(parsedType);\n    let returnIsUndefined = false;\n    traverse(returnTypeLevelNode, (nde, parentNode) => {\n      const isReturnLevelNode = !parentNode ||\n        returnTypeLevelNode.type === 'JsdocTypeUnion' && parentNode === returnTypeLevelNode;\n      if (!isReturnLevelNode) {\n        return;\n      }\n\n      const {\n        type: nodeType,\n      } = /** @type {import('jsdoc-type-pratt-parser').RootResult} */ (nde);\n\n      if (nodeType === 'JsdocTypeUndefined') {\n        returnIsUndefined = true;\n        return;\n      }\n\n      if (nodeType !== 'JsdocTypeName') {\n        return;\n      }\n\n      const {\n        value,\n      } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);\n\n      if (value === 'void') {\n        returnIsUndefined = true;\n        return;\n      }\n\n      const referencedTypedef = typedefs.find((typedefTag) => {\n        return typedefTag.name === value;\n      });\n\n      if (referencedTypedef && utils.mayBeUndefinedTypeTag(referencedTypedef)) {\n        returnIsUndefined = true;\n      }\n    });\n\n    return returnIsUndefined;\n  };\n\n  if (returnNever && utils.hasValueOrExecutorHasNonEmptyResolveValue(false)) {\n    report(`JSDoc @${tagName} declaration set with \"never\" but return expression is present in function.`);\n\n    return;\n  }\n\n  if (noNativeTypes && isAsync && strictNativeTypes.includes(type)) {\n    report('Function is async or otherwise returns a Promise but the return type is a native type.');\n    return;\n  }\n\n  // In case a return value is declared in JSDoc, we also expect one in the code.\n  if (\n    !returnNever &&\n    (\n      reportMissingReturnForUndefinedTypes ||\n      !mayReturnUndefined(tag)\n    ) &&\n    (tag.type === '' && !utils.hasValueOrExecutorHasNonEmptyResolveValue(\n      exemptAsync,\n    ) ||\n    tag.type !== '' && !utils.hasValueOrExecutorHasNonEmptyResolveValue(\n      exemptAsync,\n      true,\n    )) &&\n    Boolean(\n      !exemptGenerators || !node ||\n      !('generator' in /** @type {import('../iterateJsdoc.js').Node} */ (node)) ||\n      !(/** @type {import('@typescript-eslint/types').TSESTree.FunctionDeclaration} */ (node)).generator,\n    )\n  ) {\n    report(`JSDoc @${tagName} declaration present but return expression not available in function.`);\n  }\n}, {\n  meta: {\n    docs: {\n      description: 'Requires a return statement in function body if a `@returns` tag is specified in JSDoc comment(and reports if multiple `@returns` tags are present).',\n      url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-returns-check.md#repos-sticky-header',\n    },\n    schema: [\n      {\n        additionalProperties: false,\n        properties: {\n          exemptAsync: {\n            default: true,\n            description: `By default, functions which return a \\`Promise\\` that are not\ndetected as resolving with a non-\\`undefined\\` value and \\`async\\` functions\n(even ones that do not explicitly return a value, as these are returning a\n\\`Promise\\` implicitly) will be exempted from reporting by this rule.\nIf you wish to insist that only \\`Promise\\`'s which resolve to\nnon-\\`undefined\\` values or \\`async\\` functions with explicit \\`return\\`'s will\nbe exempted from reporting (i.e., that \\`async\\` functions can be reported\nif they lack an explicit (non-\\`undefined\\`) \\`return\\` when a \\`@returns\\` is\npresent), you can set \\`exemptAsync\\` to \\`false\\` on the options object.`,\n            type: 'boolean',\n          },\n          exemptGenerators: {\n            description: `Because a generator might be labeled as having a\n\\`IterableIterator\\` \\`@returns\\` value (along with an iterator type\ncorresponding to the type of any \\`yield\\` statements), projects might wish to\nleverage \\`@returns\\` in generators even without a \\`return\\` statement. This\noption is therefore \\`true\\` by default in \\`typescript\\` mode (in \"jsdoc\" mode,\none might be more likely to take advantage of \\`@yields\\`). Set it to \\`false\\`\nif you wish for a missing \\`return\\` to be flagged regardless.`,\n            type: 'boolean',\n          },\n          noNativeTypes: {\n            description: `Whether to check that async functions do not\nindicate they return non-native types. Defaults to \\`true\\`.`,\n            type: 'boolean',\n          },\n          reportMissingReturnForUndefinedTypes: {\n            default: false,\n            description: `If \\`true\\` and no return or\nresolve value is found, this setting will even insist that reporting occur\nwith \\`void\\` or \\`undefined\\` (including as an indicated \\`Promise\\` type).\nUnlike \\`require-returns\\`, with this option in the rule, one can\n*discourage* the labeling of \\`undefined\\` types. Defaults to \\`false\\`.`,\n            type: 'boolean',\n          },\n        },\n        type: 'object',\n      },\n    ],\n    type: 'suggestion',\n  },\n});\n"],"mappings":"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","ignoreList":[]}