eslint-plugin-jsdoc
Version:
JSDoc linting rules for ESLint.
211 lines (195 loc) • 5.91 kB
JavaScript
import iterateJsdoc from '../iterateJsdoc.js';
export default iterateJsdoc(({
context,
jsdoc,
utils,
}) => {
const [
mainCircumstance,
{
tags = null,
} = {},
] = context.options;
const tgs = /**
* @type {null|"any"|{[key: string]: "always"|"never"}}
*/ (tags);
/**
* @param {import('@es-joy/jsdoccomment').JsdocTagWithInline} jsdocTag
* @param {string} targetTagName
* @param {"always"|"never"} [circumstance]
* @returns {void}
*/
const checkHyphens = (jsdocTag, targetTagName, circumstance = mainCircumstance) => {
const always = !circumstance || circumstance === 'always';
const desc = /** @type {string} */ (utils.getTagDescription(jsdocTag));
if (!desc.trim()) {
return;
}
const startsWithHyphen = (/^\s*-/v).test(desc);
const hyphenNewline = (/^\s*-\n/v).test(desc);
let lines = 0;
for (const {
tokens,
} of jsdocTag.source) {
if (tokens.description) {
break;
}
lines++;
}
if (always && !hyphenNewline) {
if (!startsWithHyphen) {
let fixIt = true;
for (const {
tokens,
} of jsdocTag.source) {
if (tokens.description) {
tokens.description = tokens.description.replace(
/^(\s*)/v, '$1- ',
);
break;
}
// Linebreak after name since has no description
if (tokens.name) {
fixIt = false;
break;
}
}
if (fixIt) {
utils.reportJSDoc(
`There must be a hyphen before @${targetTagName} description.`,
{
line: jsdocTag.source[0].number + lines,
},
() => {},
);
}
}
} else if (startsWithHyphen) {
utils.reportJSDoc(
always ?
`There must be no hyphen followed by newline after the @${targetTagName} name.` :
`There must be no hyphen before @${targetTagName} description.`,
{
line: jsdocTag.source[0].number + lines,
},
() => {
for (const {
tokens,
} of jsdocTag.source) {
if (tokens.description) {
tokens.description = tokens.description.replace(
/^\s*-\s*/v, '',
);
if (hyphenNewline) {
tokens.postName = '';
}
break;
}
}
},
true,
);
}
};
utils.forEachPreferredTag('param', checkHyphens);
if (tgs) {
const tagEntries = Object.entries(tgs);
for (const [
tagName,
circumstance,
] of tagEntries) {
if (tagName === '*') {
const preferredParamTag = utils.getPreferredTagName({
tagName: 'param',
});
for (const {
tag,
} of jsdoc.tags) {
if (tag === preferredParamTag || tagEntries.some(([
tagNme,
]) => {
return tagNme !== '*' && tagNme === tag;
})) {
continue;
}
utils.forEachPreferredTag(tag, (jsdocTag, targetTagName) => {
checkHyphens(
jsdocTag,
targetTagName,
/** @type {"always"|"never"} */ (circumstance),
);
});
}
continue;
}
utils.forEachPreferredTag(tagName, (jsdocTag, targetTagName) => {
checkHyphens(
jsdocTag,
targetTagName,
/** @type {"always"|"never"} */ (circumstance),
);
});
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires a hyphen before the `@param` description (and optionally before `@property` descriptions).',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-hyphen-before-param-description.md#repos-sticky-header',
},
fixable: 'code',
schema: [
{
description: `If the string is \`"always"\` then a problem is raised when there is no hyphen
before the description. If it is \`"never"\` then a problem is raised when there
is a hyphen before the description. The default value is \`"always"\`.
Even if hyphens are set to "always" appear after the tag name, they will
actually be forbidden in the event that they are followed immediately by
the end of a line (this will otherwise cause Visual Studio Code to display
incorrectly).`,
enum: [
'always', 'never',
],
type: 'string',
},
{
additionalProperties: false,
description: `The options object may have the following property to indicate behavior for
other tags besides the \`\` tag (or the \`\` tag if so set).`,
properties: {
tags: {
anyOf: [
{
patternProperties: {
'.*': {
enum: [
'always', 'never',
],
type: 'string',
},
},
type: 'object',
},
{
enum: [
'any',
],
type: 'string',
},
],
description: `Object whose keys indicate different tags to check for the
presence or absence of hyphens; the key value should be "always" or "never",
indicating how hyphens are to be applied, e.g., \`{property: 'never'}\`
to ensure \`\` never uses hyphens. A key can also be set as \`*\`, e.g.,
\`'*': 'always'\` to apply hyphen checking to any tag (besides the preferred
\`\` tag which follows the main string option setting and besides any
other \`tags\` entries).`,
},
},
type: 'object',
},
],
type: 'layout',
},
});