"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = iterateJsdoc; Object.defineProperty(exports, "parseComment", { enumerable: true, get: function () { return _jsdoccomment.parseComment; } }); exports.getSettings = void 0; var _jsdoccomment = require("@es-joy/jsdoccomment"); var _commentParser = require("comment-parser"); var _lodash = _interopRequireDefault(require("lodash")); var _jsdocUtils = _interopRequireDefault(require("./jsdocUtils")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const { rewireSpecs, seedTokens } = _commentParser.util; /* const { align as commentAlign, flow: commentFlow, indent: commentIndent, } = transforms; */ const globalState = new Map(); const getBasicUtils = (context, { tagNamePreference, mode }) => { const utils = {}; utils.reportSettings = message => { context.report({ loc: { start: { column: 1, line: 1 } }, message }); }; utils.parseClosureTemplateTag = tag => { return _jsdocUtils.default.parseClosureTemplateTag(tag); }; utils.pathDoesNotBeginWith = _jsdocUtils.default.pathDoesNotBeginWith; utils.getPreferredTagNameObject = ({ tagName }) => { const ret = _jsdocUtils.default.getPreferredTagName(context, mode, tagName, tagNamePreference); const isObject = ret && typeof ret === 'object'; if (ret === false || isObject && !ret.replacement) { return { blocked: true, tagName }; } return ret; }; return utils; }; const getUtils = (node, jsdoc, jsdocNode, settings, report, context, iteratingAll, ruleConfig, indent) => { const ancestors = context.getAncestors(); const sourceCode = context.getSourceCode(); const utils = getBasicUtils(context, settings); const { tagNamePreference, overrideReplacesDocs, ignoreReplacesDocs, implementsReplacesDocs, augmentsExtendsReplacesDocs, maxLines, minLines, mode } = settings; utils.isIteratingFunction = () => { return !iteratingAll || ['MethodDefinition', 'ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression'].includes(node && node.type); }; utils.isVirtualFunction = () => { return iteratingAll && utils.hasATag(['callback', 'function', 'func', 'method']); }; utils.stringify = (tagBlock, specRewire) => { return (0, _commentParser.stringify)(specRewire ? rewireSpecs(tagBlock) : tagBlock); }; utils.reportJSDoc = (msg, tag, handler, specRewire, data) => { report(msg, handler ? fixer => { handler(); const replacement = utils.stringify(jsdoc, specRewire); return fixer.replaceText(jsdocNode, replacement); } : null, tag, data); }; utils.getRegexFromString = (str, requiredFlags) => { return _jsdocUtils.default.getRegexFromString(str, requiredFlags); }; utils.getTagDescription = tg => { const descriptions = []; tg.source.some(({ tokens: { end, lineEnd, postDelimiter, tag, postTag, name, type, description } }) => { const desc = (tag && postTag || !tag && !name && !type && postDelimiter || '' // Remove space ).slice(1) + (description || '') + (lineEnd || ''); if (end) { if (desc) { descriptions.push(desc); } return true; } descriptions.push(desc); return false; }); return descriptions.join('\n'); }; utils.getDescription = () => { const descriptions = []; let lastDescriptionLine = 0; jsdoc.source.some(({ tokens: { description, tag, end } }, idx) => { if (idx && (tag || end)) { lastDescriptionLine = idx - 1; return true; } if (idx || description) { descriptions.push(description); } return false; }); return { description: descriptions.join('\n'), lastDescriptionLine }; }; utils.changeTag = (tag, ...tokens) => { tag.source.forEach((src, idx) => { src.tokens = { ...src.tokens, ...tokens[idx] }; }); }; utils.setTag = (tag, tokens) => { tag.source = [{ // Or tag.source[0].number? number: tag.line, tokens: seedTokens({ delimiter: '*', postDelimiter: ' ', start: indent + ' ', tag: '@' + tag.tag, ...tokens }) }]; }; utils.removeTag = idx => { return utils.removeTagItem(idx); }; utils.removeTagItem = (tagIndex, tagSourceOffset = 0) => { const { source: tagSource } = jsdoc.tags[tagIndex]; let lastIndex; const firstNumber = jsdoc.source[0].number; tagSource.some(({ number }, tagIdx) => { const sourceIndex = jsdoc.source.findIndex(({ number: srcNumber, tokens: { end } }) => { return number === srcNumber && !end; }); // istanbul ignore else if (sourceIndex > -1) { let spliceCount = 1; tagSource.slice(tagIdx + 1).some(({ tokens: { tag, end } }) => { if (!tag && !end) { spliceCount++; return false; } return true; }); jsdoc.source.splice(sourceIndex + tagSourceOffset, spliceCount - tagSourceOffset); tagSource.splice(tagIdx + tagSourceOffset, spliceCount - tagSourceOffset); lastIndex = sourceIndex; return true; } // istanbul ignore next return false; }); jsdoc.source.slice(lastIndex).forEach((src, idx) => { src.number = firstNumber + lastIndex + idx; }); }; utils.addTag = targetTagName => { var _jsdoc$tags$source$0$, _jsdoc$tags, _jsdoc$tags$source$; const number = ((_jsdoc$tags$source$0$ = (_jsdoc$tags = jsdoc.tags[jsdoc.tags.length - 1]) === null || _jsdoc$tags === void 0 ? void 0 : (_jsdoc$tags$source$ = _jsdoc$tags.source[0]) === null || _jsdoc$tags$source$ === void 0 ? void 0 : _jsdoc$tags$source$.number) !== null && _jsdoc$tags$source$0$ !== void 0 ? _jsdoc$tags$source$0$ : 0) + 1; jsdoc.source.splice(number, 0, { number, source: '', tokens: seedTokens({ delimiter: '*', postDelimiter: ' ', start: indent + ' ', tag: `@${targetTagName}` }) }); jsdoc.source.slice(number + 1).forEach(src => { src.number++; }); }; utils.seedTokens = seedTokens; utils.emptyTokens = tokens => { ['start', 'postDelimiter', 'tag', 'type', 'postType', 'postTag', 'name', 'postName', 'description', 'end', 'lineEnd'].forEach(prop => { tokens[prop] = ''; }); }; utils.addLine = (sourceIndex, tokens) => { var _jsdoc$source; const number = (((_jsdoc$source = jsdoc.source[sourceIndex - 1]) === null || _jsdoc$source === void 0 ? void 0 : _jsdoc$source.number) || 0) + 1; jsdoc.source.splice(sourceIndex, 0, { number, source: '', tokens: seedTokens(tokens) }); // If necessary, we can rewire the tags (misnamed method) // rewireSource(jsdoc); }; utils.addLines = (tagIndex, tagSourceOffset, numLines) => { const { source: tagSource } = jsdoc.tags[tagIndex]; let lastIndex; const firstNumber = jsdoc.source[0].number; tagSource.some(({ number }) => { const makeLine = () => { return { number, source: '', tokens: seedTokens({ delimiter: '*', start: indent + ' ' }) }; }; const makeLines = () => { return Array.from({ length: numLines }, makeLine); }; const sourceIndex = jsdoc.source.findIndex(({ number: srcNumber, tokens: { end } }) => { return number === srcNumber && !end; }); // istanbul ignore else if (sourceIndex > -1) { const lines = makeLines(); jsdoc.source.splice(sourceIndex + tagSourceOffset, 0, ...lines); // tagSource.splice(tagIdx + 1, 0, ...makeLines()); lastIndex = sourceIndex; return true; } // istanbul ignore next return false; }); jsdoc.source.slice(lastIndex).forEach((src, idx) => { src.number = firstNumber + lastIndex + idx; }); }; utils.makeMultiline = () => { const { source: [{ tokens }] } = jsdoc; const { postDelimiter, description, lineEnd, tag, name, type } = tokens; let { tokens: { postName, postTag, postType } } = jsdoc.source[0]; // Strip trailing leftovers from single line ending if (!description) { if (postName) { postName = ''; } else if (postType) { postType = ''; // eslint-disable-next-line max-len, no-inline-comments } else /* istanbul ignore else -- `comment-parser` prevents empty blocks currently per https://github.com/syavorsky/comment-parser/issues/128 */ if (postTag) { postTag = ''; } } utils.emptyTokens(tokens); utils.addLine(1, { delimiter: '*', // If a description were present, it may have whitespace attached // due to being at the end of the single line description: description.trimEnd(), name, postDelimiter, postName, postTag, postType, start: indent + ' ', tag, type }); utils.addLine(2, { end: '*/', lineEnd, start: indent + ' ' }); }; utils.flattenRoots = params => { return _jsdocUtils.default.flattenRoots(params); }; utils.getFunctionParameterNames = useDefaultObjectProperties => { return _jsdocUtils.default.getFunctionParameterNames(node, useDefaultObjectProperties); }; utils.hasParams = () => { return _jsdocUtils.default.hasParams(node); }; utils.isGenerator = () => { return node && (node.generator || node.type === 'MethodDefinition' && node.value.generator || ['ExportNamedDeclaration', 'ExportDefaultDeclaration'].includes(node.type) && node.declaration.generator); }; utils.isConstructor = () => { return _jsdocUtils.default.isConstructor(node); }; utils.getJsdocTagsDeep = tagName => { const name = utils.getPreferredTagName({ tagName }); if (!name) { return false; } return _jsdocUtils.default.getJsdocTagsDeep(jsdoc, name); }; utils.getPreferredTagName = ({ tagName, skipReportingBlockedTag = false, allowObjectReturn = false, defaultMessage = `Unexpected tag \`@${tagName}\`` }) => { const ret = _jsdocUtils.default.getPreferredTagName(context, mode, tagName, tagNamePreference); const isObject = ret && typeof ret === 'object'; if (utils.hasTag(tagName) && (ret === false || isObject && !ret.replacement)) { if (skipReportingBlockedTag) { return { blocked: true, tagName }; } const message = isObject && ret.message || defaultMessage; report(message, null, utils.getTags(tagName)[0]); return false; } return isObject && !allowObjectReturn ? ret.replacement : ret; }; utils.isValidTag = (name, definedTags) => { return _jsdocUtils.default.isValidTag(context, mode, name, definedTags); }; utils.hasATag = names => { return _jsdocUtils.default.hasATag(jsdoc, names); }; utils.hasTag = name => { return _jsdocUtils.default.hasTag(jsdoc, name); }; utils.comparePaths = name => { return _jsdocUtils.default.comparePaths(name); }; utils.dropPathSegmentQuotes = name => { return _jsdocUtils.default.dropPathSegmentQuotes(name); }; utils.avoidDocs = () => { var _context$options$0$ex, _context$options$; if (ignoreReplacesDocs !== false && (utils.hasTag('ignore') || utils.classHasTag('ignore')) || overrideReplacesDocs !== false && (utils.hasTag('override') || utils.classHasTag('override')) || implementsReplacesDocs !== false && (utils.hasTag('implements') || utils.classHasTag('implements')) || augmentsExtendsReplacesDocs && (utils.hasATag(['augments', 'extends']) || utils.classHasTag('augments') || utils.classHasTag('extends'))) { return true; } if (_jsdocUtils.default.exemptSpeciaMethods(jsdoc, node, context, ruleConfig.meta.schema)) { return true; } const exemptedBy = (_context$options$0$ex = (_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.exemptedBy) !== null && _context$options$0$ex !== void 0 ? _context$options$0$ex : ['inheritDoc', ...(mode === 'closure' ? [] : ['inheritdoc'])]; if (exemptedBy.length && utils.getPresentTags(exemptedBy).length) { return true; } return false; }; ['tagMightHaveNamePosition', 'tagMightHaveTypePosition'].forEach(method => { utils[method] = (tagName, otherModeMaps) => { const result = _jsdocUtils.default[method](tagName); if (result) { return true; } if (!otherModeMaps) { return false; } const otherResult = otherModeMaps.some(otherModeMap => { return _jsdocUtils.default[method](tagName, otherModeMap); }); return otherResult ? { otherMode: true } : false; }; }); ['tagMustHaveNamePosition', 'tagMustHaveTypePosition', 'tagMissingRequiredTypeOrNamepath'].forEach(method => { utils[method] = (tagName, otherModeMaps) => { const result = _jsdocUtils.default[method](tagName); if (!result) { return false; } // if (!otherModeMaps) { return true; } const otherResult = otherModeMaps.every(otherModeMap => { return _jsdocUtils.default[method](tagName, otherModeMap); }); return otherResult ? true : { otherMode: false }; }; }); ['isNamepathDefiningTag', 'tagMightHaveNamepath'].forEach(method => { utils[method] = tagName => { return _jsdocUtils.default[method](tagName); }; }); utils.getTagStructureForMode = mde => { return _jsdocUtils.default.getTagStructureForMode(mde, settings.structuredTags); }; utils.hasDefinedTypeTag = tag => { return _jsdocUtils.default.hasDefinedTypeTag(tag); }; utils.hasValueOrExecutorHasNonEmptyResolveValue = anyPromiseAsReturn => { return _jsdocUtils.default.hasValueOrExecutorHasNonEmptyResolveValue(node, anyPromiseAsReturn); }; utils.hasYieldValue = () => { if (['ExportNamedDeclaration', 'ExportDefaultDeclaration'].includes(node.type)) { return _jsdocUtils.default.hasYieldValue(node.declaration); } return _jsdocUtils.default.hasYieldValue(node); }; utils.hasYieldReturnValue = () => { return _jsdocUtils.default.hasYieldValue(node, true); }; utils.hasThrowValue = () => { return _jsdocUtils.default.hasThrowValue(node); }; utils.isAsync = () => { return node.async; }; utils.getTags = tagName => { return utils.filterTags(item => { return item.tag === tagName; }); }; utils.getPresentTags = tagList => { return utils.filterTags(tag => { return tagList.includes(tag.tag); }); }; utils.filterTags = filter => { return _jsdocUtils.default.filterTags(jsdoc.tags, filter); }; utils.getTagsByType = tags => { return _jsdocUtils.default.getTagsByType(context, mode, tags, tagNamePreference); }; utils.hasOptionTag = tagName => { var _context$options$2; const { tags } = (_context$options$2 = context.options[0]) !== null && _context$options$2 !== void 0 ? _context$options$2 : {}; return Boolean(tags && tags.includes(tagName)); }; utils.getClassNode = () => { return [...ancestors, node].reverse().find(parent => { return parent && ['ClassDeclaration', 'ClassExpression'].includes(parent.type); }) || null; }; utils.getClassJsdoc = () => { const classNode = utils.getClassNode(); if (!classNode) { return null; } const classJsdocNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, classNode, { maxLines, minLines }); if (classJsdocNode) { const indnt = ' '.repeat(classJsdocNode.loc.start.column); return (0, _jsdoccomment.parseComment)(classJsdocNode, indnt); } return null; }; utils.classHasTag = tagName => { const classJsdoc = utils.getClassJsdoc(); return Boolean(classJsdoc) && _jsdocUtils.default.hasTag(classJsdoc, tagName); }; utils.forEachPreferredTag = (tagName, arrayHandler, skipReportingBlockedTag = false) => { const targetTagName = utils.getPreferredTagName({ skipReportingBlockedTag, tagName }); if (!targetTagName || skipReportingBlockedTag && targetTagName && typeof targetTagName === 'object') { return; } const matchingJsdocTags = _lodash.default.filter(jsdoc.tags, { tag: targetTagName }); matchingJsdocTags.forEach(matchingJsdocTag => { arrayHandler(matchingJsdocTag, targetTagName); }); }; return utils; }; const getSettings = context => { var _context$settings$jsd, _context$settings$jsd2, _context$settings$jsd3, _context$settings$jsd4, _context$settings$jsd5, _context$settings$jsd6, _context$settings$jsd7, _context$settings$jsd8, _context$settings$jsd9, _context$settings$jsd10, _context$settings$jsd11, _context$settings$jsd12, _context$settings$jsd13, _context$settings$jsd14, _context$settings$jsd15, _context$settings$jsd16, _context$settings$jsd17, _context$settings$jsd18; /* eslint-disable sort-keys-fix/sort-keys-fix */ const settings = { // All rules ignorePrivate: Boolean((_context$settings$jsd = context.settings.jsdoc) === null || _context$settings$jsd === void 0 ? void 0 : _context$settings$jsd.ignorePrivate), ignoreInternal: Boolean((_context$settings$jsd2 = context.settings.jsdoc) === null || _context$settings$jsd2 === void 0 ? void 0 : _context$settings$jsd2.ignoreInternal), maxLines: Number((_context$settings$jsd3 = (_context$settings$jsd4 = context.settings.jsdoc) === null || _context$settings$jsd4 === void 0 ? void 0 : _context$settings$jsd4.maxLines) !== null && _context$settings$jsd3 !== void 0 ? _context$settings$jsd3 : 1), minLines: Number((_context$settings$jsd5 = (_context$settings$jsd6 = context.settings.jsdoc) === null || _context$settings$jsd6 === void 0 ? void 0 : _context$settings$jsd6.minLines) !== null && _context$settings$jsd5 !== void 0 ? _context$settings$jsd5 : 0), // `check-tag-names` and many returns/param rules tagNamePreference: (_context$settings$jsd7 = (_context$settings$jsd8 = context.settings.jsdoc) === null || _context$settings$jsd8 === void 0 ? void 0 : _context$settings$jsd8.tagNamePreference) !== null && _context$settings$jsd7 !== void 0 ? _context$settings$jsd7 : {}, // `check-types` and `no-undefined-types` preferredTypes: (_context$settings$jsd9 = (_context$settings$jsd10 = context.settings.jsdoc) === null || _context$settings$jsd10 === void 0 ? void 0 : _context$settings$jsd10.preferredTypes) !== null && _context$settings$jsd9 !== void 0 ? _context$settings$jsd9 : {}, // `check-types`, `no-undefined-types`, `valid-types` structuredTags: (_context$settings$jsd11 = (_context$settings$jsd12 = context.settings.jsdoc) === null || _context$settings$jsd12 === void 0 ? void 0 : _context$settings$jsd12.structuredTags) !== null && _context$settings$jsd11 !== void 0 ? _context$settings$jsd11 : {}, // `require-param`, `require-description`, `require-example`, // `require-returns`, `require-throw`, `require-yields` overrideReplacesDocs: (_context$settings$jsd13 = context.settings.jsdoc) === null || _context$settings$jsd13 === void 0 ? void 0 : _context$settings$jsd13.overrideReplacesDocs, ignoreReplacesDocs: (_context$settings$jsd14 = context.settings.jsdoc) === null || _context$settings$jsd14 === void 0 ? void 0 : _context$settings$jsd14.ignoreReplacesDocs, implementsReplacesDocs: (_context$settings$jsd15 = context.settings.jsdoc) === null || _context$settings$jsd15 === void 0 ? void 0 : _context$settings$jsd15.implementsReplacesDocs, augmentsExtendsReplacesDocs: (_context$settings$jsd16 = context.settings.jsdoc) === null || _context$settings$jsd16 === void 0 ? void 0 : _context$settings$jsd16.augmentsExtendsReplacesDocs, // Many rules, e.g., `check-tag-names` mode: (_context$settings$jsd17 = (_context$settings$jsd18 = context.settings.jsdoc) === null || _context$settings$jsd18 === void 0 ? void 0 : _context$settings$jsd18.mode) !== null && _context$settings$jsd17 !== void 0 ? _context$settings$jsd17 : context.parserPath.includes('@typescript-eslint') ? 'typescript' : 'jsdoc' }; /* eslint-enable sort-keys-fix/sort-keys-fix */ _jsdocUtils.default.setTagStructure(settings.mode); try { _jsdocUtils.default.overrideTagStructure(settings.structuredTags); } catch (error) { context.report({ loc: { start: { column: 1, line: 1 } }, message: error.message }); return false; } return settings; }; /** * Create the report function * * @param {object} context * @param {object} commentNode */ exports.getSettings = getSettings; const makeReport = (context, commentNode) => { const report = (message, fix = null, jsdocLoc = null, data = null) => { let loc; if (jsdocLoc) { if (!('line' in jsdocLoc)) { jsdocLoc.line = jsdocLoc.source[0].number; } const lineNumber = commentNode.loc.start.line + jsdocLoc.line; loc = { end: { line: lineNumber }, start: { line: lineNumber } }; if (jsdocLoc.column) { const colNumber = commentNode.loc.start.column + jsdocLoc.column; loc.end.column = colNumber; loc.start.column = colNumber; } } context.report({ data, fix, loc, message, node: commentNode }); }; return report; }; /** * @typedef {ReturnType} Utils * @typedef {ReturnType} Settings * @typedef {( * arg: { * context: object, * sourceCode: object, * indent: string, * jsdoc: object, * jsdocNode: object, * node: object | null, * report: ReturnType, * settings: Settings, * utils: Utils, * } * ) => any } JsdocVisitor */ const iterate = (info, indent, jsdoc, ruleConfig, context, lines, jsdocNode, node, settings, sourceCode, iterator, state, iteratingAll) => { const report = makeReport(context, jsdocNode); const utils = getUtils(node, jsdoc, jsdocNode, settings, report, context, iteratingAll, ruleConfig, indent); if (!ruleConfig.checkInternal && settings.ignoreInternal && utils.hasTag('internal')) { return; } if (!ruleConfig.checkPrivate && settings.ignorePrivate && (utils.hasTag('private') || _lodash.default.filter(jsdoc.tags, { tag: 'access' }).some(({ description }) => { return description === 'private'; }))) { return; } iterator({ context, globalState, indent, info, iteratingAll, jsdoc, jsdocNode, node, report, settings, sourceCode, state, utils }); }; const getIndentAndJSDoc = function (lines, jsdocNode) { const sourceLine = lines[jsdocNode.loc.start.line - 1]; const indnt = sourceLine.charAt(0).repeat(jsdocNode.loc.start.column); const jsdc = (0, _jsdoccomment.parseComment)(jsdocNode, indnt); return [indnt, jsdc]; }; /** * Create an eslint rule that iterates over all JSDocs, regardless of whether * they are attached to a function-like node. * * @param {JsdocVisitor} iterator * @param {{meta: any}} ruleConfig * @param contexts * @param {boolean} additiveContexts */ const iterateAllJsdocs = (iterator, ruleConfig, contexts, additiveContexts) => { const trackedJsdocs = []; let handler; let settings; const callIterator = (context, node, jsdocNodes, state, lastCall) => { const sourceCode = context.getSourceCode(); const { lines } = sourceCode; const utils = getBasicUtils(context, settings); jsdocNodes.forEach(jsdocNode => { if (!/^\/\*\*\s/.test(sourceCode.getText(jsdocNode))) { return; } const [indent, jsdoc] = getIndentAndJSDoc(lines, jsdocNode); if (additiveContexts) { contexts.forEach(({ comment }, idx) => { if (comment && handler(comment, jsdoc) === false) { return; } iterate({ comment, lastIndex: idx, selector: node === null || node === void 0 ? void 0 : node.type }, indent, jsdoc, ruleConfig, context, lines, jsdocNode, node, settings, sourceCode, iterator, state, true); }); return; } let lastComment; let lastIndex; if (contexts && contexts.every(({ comment }, idx) => { lastComment = comment; lastIndex = idx; return comment && handler(comment, jsdoc) === false; })) { return; } iterate(lastComment ? { comment: lastComment, lastIndex, selector: node === null || node === void 0 ? void 0 : node.type } : { lastIndex, selector: node === null || node === void 0 ? void 0 : node.type }, indent, jsdoc, ruleConfig, context, lines, jsdocNode, node, settings, sourceCode, iterator, state, true); }); if (lastCall && ruleConfig.exit) { ruleConfig.exit({ context, state, utils }); } }; return { create(context) { const sourceCode = context.getSourceCode(); settings = getSettings(context); if (!settings) { return {}; } if (contexts) { handler = (0, _jsdoccomment.commentHandler)(settings); } const state = {}; return { '*:not(Program)'(node) { const reducedNode = (0, _jsdoccomment.getReducedASTNode)(node, sourceCode); if (node !== reducedNode) { return; } const commentNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, node, settings); if (trackedJsdocs.includes(commentNode)) { return; } if (!commentNode) { if (ruleConfig.nonComment) { ruleConfig.nonComment({ node, state }); } return; } trackedJsdocs.push(commentNode); callIterator(context, node, [commentNode], state); }, 'Program:exit'() { const allComments = sourceCode.getAllComments(); const untrackedJSdoc = allComments.filter(node => { return !trackedJsdocs.includes(node); }); callIterator(context, null, untrackedJSdoc, state, true); } }; }, meta: ruleConfig.meta }; }; /** * Create an eslint rule that iterates over all JSDocs, regardless of whether * they are attached to a function-like node. * * @param {JsdocVisitor} iterator * @param {{meta: any}} ruleConfig */ const checkFile = (iterator, ruleConfig) => { return { create(context) { const sourceCode = context.getSourceCode(); const settings = getSettings(context); if (!settings) { return {}; } return { 'Program:exit'() { const allComments = sourceCode.getAllComments(); const { lines } = sourceCode; const utils = getBasicUtils(context, settings); iterator({ allComments, context, lines, makeReport, settings, sourceCode, utils }); } }; }, meta: ruleConfig.meta }; }; /** * @param {JsdocVisitor} iterator * @param {{ * meta: any, * contextDefaults?: true | string[], * contextSelected?: true, * iterateAllJsdocs?: true, * }} ruleConfig */ function iterateJsdoc(iterator, ruleConfig) { var _ruleConfig$meta; const metaType = ruleConfig === null || ruleConfig === void 0 ? void 0 : (_ruleConfig$meta = ruleConfig.meta) === null || _ruleConfig$meta === void 0 ? void 0 : _ruleConfig$meta.type; if (!metaType || !['problem', 'suggestion', 'layout'].includes(metaType)) { throw new TypeError('Rule must include `meta.type` option (with value "problem", "suggestion", or "layout")'); } if (typeof iterator !== 'function') { throw new TypeError('The iterator argument must be a function.'); } if (ruleConfig.checkFile) { return checkFile(iterator, ruleConfig); } if (ruleConfig.iterateAllJsdocs) { return iterateAllJsdocs(iterator, ruleConfig); } return { /** * The entrypoint for the JSDoc rule. * * @param {*} context * a reference to the context which hold all important information * like settings and the sourcecode to check. * @returns {object} * a list with parser callback function. */ create(context) { const settings = getSettings(context); if (!settings) { return {}; } let contexts; if (ruleConfig.contextDefaults || ruleConfig.contextSelected || ruleConfig.matchContext) { var _context$options$3, _contexts, _contexts2; contexts = ruleConfig.matchContext && (_context$options$3 = context.options[0]) !== null && _context$options$3 !== void 0 && _context$options$3.match ? context.options[0].match : _jsdocUtils.default.enforcedContexts(context, ruleConfig.contextDefaults); if (contexts) { contexts = contexts.map(obj => { if (typeof obj === 'object' && !obj.context) { return { ...obj, context: 'any' }; } return obj; }); } const hasPlainAny = (_contexts = contexts) === null || _contexts === void 0 ? void 0 : _contexts.includes('any'); const hasObjectAny = !hasPlainAny && ((_contexts2 = contexts) === null || _contexts2 === void 0 ? void 0 : _contexts2.find(ctxt => { return (ctxt === null || ctxt === void 0 ? void 0 : ctxt.context) === 'any'; })); if (hasPlainAny || hasObjectAny) { return iterateAllJsdocs(iterator, ruleConfig, hasObjectAny ? contexts : null, ruleConfig.matchContext).create(context); } } const sourceCode = context.getSourceCode(); const { lines } = sourceCode; const state = {}; const checkJsdoc = (info, handler, node) => { const jsdocNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, node, settings); if (!jsdocNode) { return; } const [indent, jsdoc] = getIndentAndJSDoc(lines, jsdocNode); if ( // Note, `handler` should already be bound in its first argument // with these only to be called after the value of // `comment` handler && handler(jsdoc) === false) { return; } iterate(info, indent, jsdoc, ruleConfig, context, lines, jsdocNode, node, settings, sourceCode, iterator, state); }; let contextObject = {}; if (contexts && (ruleConfig.contextDefaults || ruleConfig.contextSelected || ruleConfig.matchContext)) { contextObject = _jsdocUtils.default.getContextObject(contexts, checkJsdoc, (0, _jsdoccomment.commentHandler)(settings)); } else { ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression'].forEach(prop => { contextObject[prop] = checkJsdoc.bind(null, { selector: prop }, null); }); } if (ruleConfig.exit) { contextObject['Program:exit'] = () => { ruleConfig.exit({ context, state }); }; } return contextObject; }, meta: ruleConfig.meta }; } //# sourceMappingURL=iterateJsdoc.js.map