Initial import with skill sheet working

This commit is contained in:
2024-12-04 00:11:23 +01:00
commit 9050c80ab4
4488 changed files with 671048 additions and 0 deletions

View File

@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const accessLevels = ['package', 'private', 'protected', 'public'];
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('access', (jsdocParameter, targetTagName) => {
const desc = jsdocParameter.name + ' ' + jsdocParameter.description;
if (!accessLevels.includes(desc.trim())) {
report(`Missing valid JSDoc @${targetTagName} level.`, null, jsdocParameter);
}
});
const accessLength = utils.getTags('access').length;
const individualTagLength = utils.getPresentTags(accessLevels).length;
if (accessLength && individualTagLength) {
report('The @access tag may not be used with specific access-control tags (@package, @private, @protected, or @public).');
}
if (accessLength > 1 || individualTagLength > 1) {
report('At most one access-control tag may be present on a jsdoc block.');
}
}, {
checkPrivate: true,
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that `@access` tags have a valid value.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-access.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkAccess.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"checkAccess.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","accessLevels","_default","exports","iterateJsdoc","report","utils","forEachPreferredTag","jsdocParameter","targetTagName","desc","name","description","includes","trim","accessLength","getTags","length","individualTagLength","getPresentTags","checkPrivate","iterateAllJsdocs","meta","docs","url","type","module"],"sources":["../../src/rules/checkAccess.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nconst accessLevels = [\n 'package', 'private', 'protected', 'public',\n];\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('access', (jsdocParameter, targetTagName) => {\n const desc = jsdocParameter.name + ' ' + jsdocParameter.description;\n\n if (!accessLevels.includes(desc.trim())) {\n report(\n `Missing valid JSDoc @${targetTagName} level.`,\n null,\n jsdocParameter,\n );\n }\n });\n const accessLength = utils.getTags('access').length;\n const individualTagLength = utils.getPresentTags(accessLevels).length;\n if (accessLength && individualTagLength) {\n report(\n 'The @access tag may not be used with specific access-control tags (@package, @private, @protected, or @public).',\n );\n }\n\n if (accessLength > 1 || individualTagLength > 1) {\n report(\n 'At most one access-control tag may be present on a jsdoc block.',\n );\n }\n}, {\n checkPrivate: true,\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Checks that `@access` tags have a valid value.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-access.md#repos-sticky-header',\n },\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C,MAAMG,YAAY,GAAG,CACnB,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAC5C;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAH,OAAA,GAEa,IAAAI,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJA,KAAK,CAACC,mBAAmB,CAAC,QAAQ,EAAE,CAACC,cAAc,EAAEC,aAAa,KAAK;IACrE,MAAMC,IAAI,GAAGF,cAAc,CAACG,IAAI,GAAG,GAAG,GAAGH,cAAc,CAACI,WAAW;IAEnE,IAAI,CAACX,YAAY,CAACY,QAAQ,CAACH,IAAI,CAACI,IAAI,CAAC,CAAC,CAAC,EAAE;MACvCT,MAAM,CACJ,wBAAwBI,aAAa,SAAS,EAC9C,IAAI,EACJD,cACF,CAAC;IACH;EACF,CAAC,CAAC;EACF,MAAMO,YAAY,GAAGT,KAAK,CAACU,OAAO,CAAC,QAAQ,CAAC,CAACC,MAAM;EACnD,MAAMC,mBAAmB,GAAGZ,KAAK,CAACa,cAAc,CAAClB,YAAY,CAAC,CAACgB,MAAM;EACrE,IAAIF,YAAY,IAAIG,mBAAmB,EAAE;IACvCb,MAAM,CACJ,iHACF,CAAC;EACH;EAEA,IAAIU,YAAY,GAAG,CAAC,IAAIG,mBAAmB,GAAG,CAAC,EAAE;IAC/Cb,MAAM,CACJ,iEACF,CAAC;EACH;AACF,CAAC,EAAE;EACDe,YAAY,EAAE,IAAI;EAClBC,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJX,WAAW,EAAE,gDAAgD;MAC7DY,GAAG,EAAE;IACP,CAAC;IACDC,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAAvB,OAAA,GAAAA,OAAA,CAAAH,OAAA","ignoreList":[]}

View File

@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} string
* @returns {string}
*/
const trimStart = string => {
return string.replace(/^\s+/u, '');
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
jsdocNode,
report,
indent
}) => {
// `indent` is whitespace from line 1 (`/**`), so slice and account for "/".
const indentLevel = indent.length + 1;
const sourceLines = sourceCode.getText(jsdocNode).split('\n').slice(1).map(line => {
return line.split('*')[0];
}).filter(line => {
return !trimStart(line).length;
});
/** @type {import('eslint').Rule.ReportFixer} */
const fix = fixer => {
const replacement = sourceCode.getText(jsdocNode).split('\n').map((line, index) => {
// Ignore the first line and all lines not starting with `*`
const ignored = !index || trimStart(line.split('*')[0]).length;
return ignored ? line : `${indent} ${trimStart(line)}`;
}).join('\n');
return fixer.replaceText(jsdocNode, replacement);
};
sourceLines.some((line, lineNum) => {
if (line.length !== indentLevel) {
report('Expected JSDoc block to be aligned.', fix, {
line: lineNum + 1
});
return true;
}
return false;
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid alignment of JSDoc block asterisks.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-alignment.md#repos-sticky-header'
},
fixable: 'code',
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkAlignment.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"checkAlignment.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","trimStart","string","replace","_default","exports","iterateJsdoc","sourceCode","jsdocNode","report","indent","indentLevel","length","sourceLines","getText","split","slice","map","line","filter","fix","fixer","replacement","index","ignored","join","replaceText","some","lineNum","iterateAllJsdocs","meta","docs","description","url","fixable","type","module"],"sources":["../../src/rules/checkAlignment.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\n/**\n * @param {string} string\n * @returns {string}\n */\nconst trimStart = (string) => {\n return string.replace(/^\\s+/u, '');\n};\n\nexport default iterateJsdoc(({\n sourceCode,\n jsdocNode,\n report,\n indent,\n}) => {\n // `indent` is whitespace from line 1 (`/**`), so slice and account for \"/\".\n const indentLevel = indent.length + 1;\n const sourceLines = sourceCode.getText(jsdocNode).split('\\n')\n .slice(1)\n .map((line) => {\n return line.split('*')[0];\n })\n .filter((line) => {\n return !trimStart(line).length;\n });\n\n /** @type {import('eslint').Rule.ReportFixer} */\n const fix = (fixer) => {\n const replacement = sourceCode.getText(jsdocNode).split('\\n')\n .map((line, index) => {\n // Ignore the first line and all lines not starting with `*`\n const ignored = !index || trimStart(line.split('*')[0]).length;\n\n return ignored ? line : `${indent} ${trimStart(line)}`;\n })\n .join('\\n');\n\n return fixer.replaceText(jsdocNode, replacement);\n };\n\n sourceLines.some((line, lineNum) => {\n if (line.length !== indentLevel) {\n report('Expected JSDoc block to be aligned.', fix, {\n line: lineNum + 1,\n });\n\n return true;\n }\n\n return false;\n });\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Reports invalid alignment of JSDoc block asterisks.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-alignment.md#repos-sticky-header',\n },\n fixable: 'code',\n type: 'layout',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C;AACA;AACA;AACA;AACA,MAAMG,SAAS,GAAIC,MAAM,IAAK;EAC5B,OAAOA,MAAM,CAACC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;AACpC,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAL,OAAA,GAEa,IAAAM,qBAAY,EAAC,CAAC;EAC3BC,UAAU;EACVC,SAAS;EACTC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ;EACA,MAAMC,WAAW,GAAGD,MAAM,CAACE,MAAM,GAAG,CAAC;EACrC,MAAMC,WAAW,GAAGN,UAAU,CAACO,OAAO,CAACN,SAAS,CAAC,CAACO,KAAK,CAAC,IAAI,CAAC,CAC1DC,KAAK,CAAC,CAAC,CAAC,CACRC,GAAG,CAAEC,IAAI,IAAK;IACb,OAAOA,IAAI,CAACH,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;EAC3B,CAAC,CAAC,CACDI,MAAM,CAAED,IAAI,IAAK;IAChB,OAAO,CAACjB,SAAS,CAACiB,IAAI,CAAC,CAACN,MAAM;EAChC,CAAC,CAAC;;EAEJ;EACA,MAAMQ,GAAG,GAAIC,KAAK,IAAK;IACrB,MAAMC,WAAW,GAAGf,UAAU,CAACO,OAAO,CAACN,SAAS,CAAC,CAACO,KAAK,CAAC,IAAI,CAAC,CAC1DE,GAAG,CAAC,CAACC,IAAI,EAAEK,KAAK,KAAK;MACpB;MACA,MAAMC,OAAO,GAAG,CAACD,KAAK,IAAItB,SAAS,CAACiB,IAAI,CAACH,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAACH,MAAM;MAE9D,OAAOY,OAAO,GAAGN,IAAI,GAAG,GAAGR,MAAM,IAAIT,SAAS,CAACiB,IAAI,CAAC,EAAE;IACxD,CAAC,CAAC,CACDO,IAAI,CAAC,IAAI,CAAC;IAEb,OAAOJ,KAAK,CAACK,WAAW,CAAClB,SAAS,EAAEc,WAAW,CAAC;EAClD,CAAC;EAEDT,WAAW,CAACc,IAAI,CAAC,CAACT,IAAI,EAAEU,OAAO,KAAK;IAClC,IAAIV,IAAI,CAACN,MAAM,KAAKD,WAAW,EAAE;MAC/BF,MAAM,CAAC,qCAAqC,EAAEW,GAAG,EAAE;QACjDF,IAAI,EAAEU,OAAO,GAAG;MAClB,CAAC,CAAC;MAEF,OAAO,IAAI;IACb;IAEA,OAAO,KAAK;EACd,CAAC,CAAC;AACJ,CAAC,EAAE;EACDC,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,qDAAqD;MAClEC,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAA/B,OAAA,GAAAA,OAAA,CAAAL,OAAA","ignoreList":[]}

View File

@ -0,0 +1,512 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _eslint = _interopRequireWildcard(require("eslint"));
var _semver = _interopRequireDefault(require("semver"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// Todo: When replace `CLIEngine` with `ESLint` when feature set complete per https://github.com/eslint/eslint/issues/14745
// https://github.com/eslint/eslint/blob/master/docs/user-guide/migrating-to-7.0.0.md#-the-cliengine-class-has-been-deprecated
const {
// @ts-expect-error Older ESLint
CLIEngine
} = _eslint.default;
const zeroBasedLineIndexAdjust = -1;
const likelyNestedJSDocIndentSpace = 1;
const preTagSpaceLength = 1;
// If a space is present, we should ignore it
const firstLinePrefixLength = preTagSpaceLength;
const hasCaptionRegex = /^\s*<caption>([\s\S]*?)<\/caption>/u;
/**
* @param {string} str
* @returns {string}
*/
const escapeStringRegexp = str => {
return str.replaceAll(/[.*+?^${}()|[\]\\]/gu, '\\$&');
};
/**
* @param {string} str
* @param {string} ch
* @returns {import('../iterateJsdoc.js').Integer}
*/
const countChars = (str, ch) => {
return (str.match(new RegExp(escapeStringRegexp(ch), 'gu')) || []).length;
};
/** @type {import('eslint').Linter.RulesRecord} */
const defaultMdRules = {
// "always" newline rule at end unlikely in sample code
'eol-last': 0,
// Wouldn't generally expect example paths to resolve relative to JS file
'import/no-unresolved': 0,
// Snippets likely too short to always include import/export info
'import/unambiguous': 0,
'jsdoc/require-file-overview': 0,
// The end of a multiline comment would end the comment the example is in.
'jsdoc/require-jsdoc': 0,
// Unlikely to have inadvertent debugging within examples
'no-console': 0,
// Often wish to start `@example` code after newline; also may use
// empty lines for spacing
'no-multiple-empty-lines': 0,
// Many variables in examples will be `undefined`
'no-undef': 0,
// Common to define variables for clarity without always using them
'no-unused-vars': 0,
// See import/no-unresolved
'node/no-missing-import': 0,
'node/no-missing-require': 0,
// Can generally look nicer to pad a little even if code imposes more stringency
'padded-blocks': 0
};
/** @type {import('eslint').Linter.RulesRecord} */
const defaultExpressionRules = {
...defaultMdRules,
'chai-friendly/no-unused-expressions': 'off',
'no-empty-function': 'off',
'no-new': 'off',
'no-unused-expressions': 'off',
quotes: ['error', 'double'],
semi: ['error', 'never'],
strict: 'off'
};
/**
* @param {string} text
* @returns {[
* import('../iterateJsdoc.js').Integer,
* import('../iterateJsdoc.js').Integer
* ]}
*/
const getLinesCols = text => {
const matchLines = countChars(text, '\n');
const colDelta = matchLines ? text.slice(text.lastIndexOf('\n') + 1).length : text.length;
return [matchLines, colDelta];
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils,
context,
globalState
}) => {
if (_semver.default.gte(_eslint.ESLint.version, '8.0.0')) {
report('This rule does not work for ESLint 8+; you should disable this rule and use' + 'the processor mentioned in the docs.', null, {
column: 1,
line: 1
});
return;
}
if (!globalState.has('checkExamples-matchingFileName')) {
globalState.set('checkExamples-matchingFileName', new Map());
}
const matchingFileNameMap = /** @type {Map<string, string>} */
globalState.get('checkExamples-matchingFileName');
const options = context.options[0] || {};
let {
exampleCodeRegex = null,
rejectExampleCodeRegex = null
} = options;
const {
checkDefaults = false,
checkParams = false,
checkProperties = false,
noDefaultExampleRules = false,
checkEslintrc = true,
matchingFileName = null,
matchingFileNameDefaults = null,
matchingFileNameParams = null,
matchingFileNameProperties = null,
paddedIndent = 0,
baseConfig = {},
configFile,
allowInlineConfig = true,
reportUnusedDisableDirectives = true,
captionRequired = false
} = options;
// Make this configurable?
/**
* @type {never[]}
*/
const rulePaths = [];
const mdRules = noDefaultExampleRules ? undefined : defaultMdRules;
const expressionRules = noDefaultExampleRules ? undefined : defaultExpressionRules;
if (exampleCodeRegex) {
exampleCodeRegex = utils.getRegexFromString(exampleCodeRegex);
}
if (rejectExampleCodeRegex) {
rejectExampleCodeRegex = utils.getRegexFromString(rejectExampleCodeRegex);
}
/**
* @param {{
* filename: string,
* defaultFileName: string|undefined,
* source: string,
* targetTagName: string,
* rules?: import('eslint').Linter.RulesRecord|undefined,
* lines?: import('../iterateJsdoc.js').Integer,
* cols?: import('../iterateJsdoc.js').Integer,
* skipInit?: boolean,
* sources?: {
* nonJSPrefacingCols: import('../iterateJsdoc.js').Integer,
* nonJSPrefacingLines: import('../iterateJsdoc.js').Integer,
* string: string,
* }[],
* tag?: import('comment-parser').Spec & {
* line?: import('../iterateJsdoc.js').Integer,
* }|{
* line: import('../iterateJsdoc.js').Integer,
* }
* }} cfg
*/
const checkSource = ({
filename,
defaultFileName,
rules = expressionRules,
lines = 0,
cols = 0,
skipInit,
source,
targetTagName,
sources = [],
tag = {
line: 0
}
}) => {
if (!skipInit) {
sources.push({
nonJSPrefacingCols: cols,
nonJSPrefacingLines: lines,
string: source
});
}
// Todo: Make fixable
/**
* @param {{
* nonJSPrefacingCols: import('../iterateJsdoc.js').Integer,
* nonJSPrefacingLines: import('../iterateJsdoc.js').Integer,
* string: string
* }} cfg
*/
const checkRules = function ({
nonJSPrefacingCols,
nonJSPrefacingLines,
string
}) {
const cliConfig = {
allowInlineConfig,
baseConfig,
configFile,
reportUnusedDisableDirectives,
rulePaths,
rules,
useEslintrc: checkEslintrc
};
const cliConfigStr = JSON.stringify(cliConfig);
const src = paddedIndent ? string.replaceAll(new RegExp(`(^|\n) {${paddedIndent}}(?!$)`, 'gu'), '\n') : string;
// Programmatic ESLint API: https://eslint.org/docs/developer-guide/nodejs-api
const fileNameMapKey = filename ? 'a' + cliConfigStr + filename : 'b' + cliConfigStr + defaultFileName;
const file = filename || defaultFileName;
let cliFile;
if (matchingFileNameMap.has(fileNameMapKey)) {
cliFile = matchingFileNameMap.get(fileNameMapKey);
} else {
const cli = new CLIEngine(cliConfig);
let config;
if (filename || checkEslintrc) {
config = cli.getConfigForFile(file);
}
// We need a new instance to ensure that the rules that may only
// be available to `file` (if it has its own `.eslintrc`),
// will be defined.
cliFile = new CLIEngine({
allowInlineConfig,
baseConfig: {
...baseConfig,
...config
},
configFile,
reportUnusedDisableDirectives,
rulePaths,
rules,
useEslintrc: false
});
matchingFileNameMap.set(fileNameMapKey, cliFile);
}
const {
results: [{
messages
}]
} = cliFile.executeOnText(src);
if (!('line' in tag)) {
tag.line = tag.source[0].number;
}
// NOTE: `tag.line` can be 0 if of form `/** @tag ... */`
const codeStartLine =
/**
* @type {import('comment-parser').Spec & {
* line: import('../iterateJsdoc.js').Integer,
* }}
*/
tag.line + nonJSPrefacingLines;
const codeStartCol = likelyNestedJSDocIndentSpace;
for (const {
message,
line,
column,
severity,
ruleId
} of messages) {
const startLine = codeStartLine + line + zeroBasedLineIndexAdjust;
const startCol = codeStartCol + (
// This might not work for line 0, but line 0 is unlikely for examples
line <= 1 ? nonJSPrefacingCols + firstLinePrefixLength : preTagSpaceLength) + column;
report('@' + targetTagName + ' ' + (severity === 2 ? 'error' : 'warning') + (ruleId ? ' (' + ruleId + ')' : '') + ': ' + message, null, {
column: startCol,
line: startLine
});
}
};
for (const targetSource of sources) {
checkRules(targetSource);
}
};
/**
*
* @param {string} filename
* @param {string} [ext] Since `eslint-plugin-markdown` v2, and
* ESLint 7, this is the default which other JS-fenced rules will used.
* Formerly "md" was the default.
* @returns {{defaultFileName: string|undefined, filename: string}}
*/
const getFilenameInfo = (filename, ext = 'md/*.js') => {
let defaultFileName;
if (!filename) {
const jsFileName = context.getFilename();
if (typeof jsFileName === 'string' && jsFileName.includes('.')) {
defaultFileName = jsFileName.replace(/\.[^.]*$/u, `.${ext}`);
} else {
defaultFileName = `dummy.${ext}`;
}
}
return {
defaultFileName,
filename
};
};
if (checkDefaults) {
const filenameInfo = getFilenameInfo(matchingFileNameDefaults, 'jsdoc-defaults');
utils.forEachPreferredTag('default', (tag, targetTagName) => {
if (!tag.description.trim()) {
return;
}
checkSource({
source: `(${utils.getTagDescription(tag)})`,
targetTagName,
...filenameInfo
});
});
}
if (checkParams) {
const filenameInfo = getFilenameInfo(matchingFileNameParams, 'jsdoc-params');
utils.forEachPreferredTag('param', (tag, targetTagName) => {
if (!tag.default || !tag.default.trim()) {
return;
}
checkSource({
source: `(${tag.default})`,
targetTagName,
...filenameInfo
});
});
}
if (checkProperties) {
const filenameInfo = getFilenameInfo(matchingFileNameProperties, 'jsdoc-properties');
utils.forEachPreferredTag('property', (tag, targetTagName) => {
if (!tag.default || !tag.default.trim()) {
return;
}
checkSource({
source: `(${tag.default})`,
targetTagName,
...filenameInfo
});
});
}
const tagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'example'
});
if (!utils.hasTag(tagName)) {
return;
}
const matchingFilenameInfo = getFilenameInfo(matchingFileName);
utils.forEachPreferredTag('example', (tag, targetTagName) => {
let source = /** @type {string} */utils.getTagDescription(tag);
const match = source.match(hasCaptionRegex);
if (captionRequired && (!match || !match[1].trim())) {
report('Caption is expected for examples.', null, tag);
}
source = source.replace(hasCaptionRegex, '');
const [lines, cols] = match ? getLinesCols(match[0]) : [0, 0];
if (exampleCodeRegex && !exampleCodeRegex.test(source) || rejectExampleCodeRegex && rejectExampleCodeRegex.test(source)) {
return;
}
const sources = [];
let skipInit = false;
if (exampleCodeRegex) {
let nonJSPrefacingCols = 0;
let nonJSPrefacingLines = 0;
let startingIndex = 0;
let lastStringCount = 0;
let exampleCode;
exampleCodeRegex.lastIndex = 0;
while ((exampleCode = exampleCodeRegex.exec(source)) !== null) {
const {
index,
'0': n0,
'1': n1
} = exampleCode;
// Count anything preceding user regex match (can affect line numbering)
const preMatch = source.slice(startingIndex, index);
const [preMatchLines, colDelta] = getLinesCols(preMatch);
let nonJSPreface;
let nonJSPrefaceLineCount;
if (n1) {
const idx = n0.indexOf(n1);
nonJSPreface = n0.slice(0, idx);
nonJSPrefaceLineCount = countChars(nonJSPreface, '\n');
} else {
nonJSPreface = '';
nonJSPrefaceLineCount = 0;
}
nonJSPrefacingLines += lastStringCount + preMatchLines + nonJSPrefaceLineCount;
// Ignore `preMatch` delta if newlines here
if (nonJSPrefaceLineCount) {
const charsInLastLine = nonJSPreface.slice(nonJSPreface.lastIndexOf('\n') + 1).length;
nonJSPrefacingCols += charsInLastLine;
} else {
nonJSPrefacingCols += colDelta + nonJSPreface.length;
}
const string = n1 || n0;
sources.push({
nonJSPrefacingCols,
nonJSPrefacingLines,
string
});
startingIndex = exampleCodeRegex.lastIndex;
lastStringCount = countChars(string, '\n');
if (!exampleCodeRegex.global) {
break;
}
}
skipInit = true;
}
checkSource({
cols,
lines,
rules: mdRules,
skipInit,
source,
sources,
tag,
targetTagName,
...matchingFilenameInfo
});
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Ensures that (JavaScript) examples within JSDoc adhere to ESLint rules.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-examples.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
allowInlineConfig: {
default: true,
type: 'boolean'
},
baseConfig: {
type: 'object'
},
captionRequired: {
default: false,
type: 'boolean'
},
checkDefaults: {
default: false,
type: 'boolean'
},
checkEslintrc: {
default: true,
type: 'boolean'
},
checkParams: {
default: false,
type: 'boolean'
},
checkProperties: {
default: false,
type: 'boolean'
},
configFile: {
type: 'string'
},
exampleCodeRegex: {
type: 'string'
},
matchingFileName: {
type: 'string'
},
matchingFileNameDefaults: {
type: 'string'
},
matchingFileNameParams: {
type: 'string'
},
matchingFileNameProperties: {
type: 'string'
},
noDefaultExampleRules: {
default: false,
type: 'boolean'
},
paddedIndent: {
default: 0,
type: 'integer'
},
rejectExampleCodeRegex: {
type: 'string'
},
reportUnusedDisableDirectives: {
default: true,
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkExamples.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} str
* @param {string[]} excludeTags
* @returns {string}
*/
const maskExcludedContent = (str, excludeTags) => {
const regContent = new RegExp(`([ \\t]+\\*)[ \\t]@(?:${excludeTags.join('|')})(?=[ \\n])([\\w|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*@\\w+\\s|\\/))`, 'gu');
return str.replace(regContent, (_match, margin, code) => {
return (margin + '\n').repeat(code.match(/\n/gu).length);
});
};
/**
* @param {string} str
* @returns {string}
*/
const maskCodeBlocks = str => {
const regContent = /([ \t]+\*)[ \t]```[^\n]*?([\w|\W]*?\n)(?=[ \t]*\*(?:[ \t]*(?:```|@\w+\s)|\/))/gu;
return str.replaceAll(regContent, (_match, margin, code) => {
return (margin + '\n').repeat(code.match(/\n/gu).length);
});
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
jsdocNode,
report,
context
}) => {
const options = context.options[0] || {};
const /** @type {{excludeTags: string[]}} */{
excludeTags = ['example']
} = options;
const reg = /^(?:\/?\**|[ \t]*)\*[ \t]{2}/gmu;
const textWithoutCodeBlocks = maskCodeBlocks(sourceCode.getText(jsdocNode));
const text = excludeTags.length ? maskExcludedContent(textWithoutCodeBlocks, excludeTags) : textWithoutCodeBlocks;
if (reg.test(text)) {
const lineBreaks = text.slice(0, reg.lastIndex).match(/\n/gu) || [];
report('There must be no indentation.', null, {
line: lineBreaks.length
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid padding inside JSDoc blocks.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-indentation.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
excludeTags: {
items: {
pattern: '^\\S+$',
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkIndentation.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"checkIndentation.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","maskExcludedContent","str","excludeTags","regContent","RegExp","join","replace","_match","margin","code","repeat","match","length","maskCodeBlocks","replaceAll","_default","exports","iterateJsdoc","sourceCode","jsdocNode","report","context","options","reg","textWithoutCodeBlocks","getText","text","test","lineBreaks","slice","lastIndex","line","iterateAllJsdocs","meta","docs","description","url","schema","additionalProperties","properties","items","pattern","type","module"],"sources":["../../src/rules/checkIndentation.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\n/**\n * @param {string} str\n * @param {string[]} excludeTags\n * @returns {string}\n */\nconst maskExcludedContent = (str, excludeTags) => {\n const regContent = new RegExp(`([ \\\\t]+\\\\*)[ \\\\t]@(?:${excludeTags.join('|')})(?=[ \\\\n])([\\\\w|\\\\W]*?\\\\n)(?=[ \\\\t]*\\\\*(?:[ \\\\t]*@\\\\w+\\\\s|\\\\/))`, 'gu');\n\n return str.replace(regContent, (_match, margin, code) => {\n return (margin + '\\n').repeat(code.match(/\\n/gu).length);\n });\n};\n\n/**\n * @param {string} str\n * @returns {string}\n */\nconst maskCodeBlocks = (str) => {\n const regContent = /([ \\t]+\\*)[ \\t]```[^\\n]*?([\\w|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*(?:```|@\\w+\\s)|\\/))/gu;\n\n return str.replaceAll(regContent, (_match, margin, code) => {\n return (margin + '\\n').repeat(code.match(/\\n/gu).length);\n });\n};\n\nexport default iterateJsdoc(({\n sourceCode,\n jsdocNode,\n report,\n context,\n}) => {\n const options = context.options[0] || {};\n const /** @type {{excludeTags: string[]}} */ {\n excludeTags = [\n 'example',\n ],\n } = options;\n\n const reg = /^(?:\\/?\\**|[ \\t]*)\\*[ \\t]{2}/gmu;\n const textWithoutCodeBlocks = maskCodeBlocks(sourceCode.getText(jsdocNode));\n const text = excludeTags.length ? maskExcludedContent(textWithoutCodeBlocks, excludeTags) : textWithoutCodeBlocks;\n\n if (reg.test(text)) {\n const lineBreaks = text.slice(0, reg.lastIndex).match(/\\n/gu) || [];\n report('There must be no indentation.', null, {\n line: lineBreaks.length,\n });\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Reports invalid padding inside JSDoc blocks.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-indentation.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n excludeTags: {\n items: {\n pattern: '^\\\\S+$',\n type: 'string',\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'layout',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C;AACA;AACA;AACA;AACA;AACA,MAAMG,mBAAmB,GAAGA,CAACC,GAAG,EAAEC,WAAW,KAAK;EAChD,MAAMC,UAAU,GAAG,IAAIC,MAAM,CAAC,yBAAyBF,WAAW,CAACG,IAAI,CAAC,GAAG,CAAC,kEAAkE,EAAE,IAAI,CAAC;EAErJ,OAAOJ,GAAG,CAACK,OAAO,CAACH,UAAU,EAAE,CAACI,MAAM,EAAEC,MAAM,EAAEC,IAAI,KAAK;IACvD,OAAO,CAACD,MAAM,GAAG,IAAI,EAAEE,MAAM,CAACD,IAAI,CAACE,KAAK,CAAC,MAAM,CAAC,CAACC,MAAM,CAAC;EAC1D,CAAC,CAAC;AACJ,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMC,cAAc,GAAIZ,GAAG,IAAK;EAC9B,MAAME,UAAU,GAAG,iFAAiF;EAEpG,OAAOF,GAAG,CAACa,UAAU,CAACX,UAAU,EAAE,CAACI,MAAM,EAAEC,MAAM,EAAEC,IAAI,KAAK;IAC1D,OAAO,CAACD,MAAM,GAAG,IAAI,EAAEE,MAAM,CAACD,IAAI,CAACE,KAAK,CAAC,MAAM,CAAC,CAACC,MAAM,CAAC;EAC1D,CAAC,CAAC;AACJ,CAAC;AAAC,IAAAG,QAAA,GAAAC,OAAA,CAAAjB,OAAA,GAEa,IAAAkB,qBAAY,EAAC,CAAC;EAC3BC,UAAU;EACVC,SAAS;EACTC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ,MAAMC,OAAO,GAAGD,OAAO,CAACC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;EACxC,MAAM,sCAAuC;IAC3CpB,WAAW,GAAG,CACZ,SAAS;EAEb,CAAC,GAAGoB,OAAO;EAEX,MAAMC,GAAG,GAAG,iCAAiC;EAC7C,MAAMC,qBAAqB,GAAGX,cAAc,CAACK,UAAU,CAACO,OAAO,CAACN,SAAS,CAAC,CAAC;EAC3E,MAAMO,IAAI,GAAGxB,WAAW,CAACU,MAAM,GAAGZ,mBAAmB,CAACwB,qBAAqB,EAAEtB,WAAW,CAAC,GAAGsB,qBAAqB;EAEjH,IAAID,GAAG,CAACI,IAAI,CAACD,IAAI,CAAC,EAAE;IAClB,MAAME,UAAU,GAAGF,IAAI,CAACG,KAAK,CAAC,CAAC,EAAEN,GAAG,CAACO,SAAS,CAAC,CAACnB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;IACnES,MAAM,CAAC,+BAA+B,EAAE,IAAI,EAAE;MAC5CW,IAAI,EAAEH,UAAU,CAAChB;IACnB,CAAC,CAAC;EACJ;AACF,CAAC,EAAE;EACDoB,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,8CAA8C;MAC3DC,GAAG,EAAE;IACP,CAAC;IACDC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVrC,WAAW,EAAE;UACXsC,KAAK,EAAE;YACLC,OAAO,EAAE,QAAQ;YACjBC,IAAI,EAAE;UACR,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAA3B,OAAA,GAAAA,OAAA,CAAAjB,OAAA","ignoreList":[]}

View File

@ -0,0 +1,321 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _alignTransform = _interopRequireDefault(require("../alignTransform.cjs"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _commentParser = require("comment-parser");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const {
flow: commentFlow
} = _commentParser.transforms;
/**
* @typedef {{
* postDelimiter: import('../iterateJsdoc.js').Integer,
* postHyphen: import('../iterateJsdoc.js').Integer,
* postName: import('../iterateJsdoc.js').Integer,
* postTag: import('../iterateJsdoc.js').Integer,
* postType: import('../iterateJsdoc.js').Integer,
* }} CustomSpacings
*/
/**
* @param {import('../iterateJsdoc.js').Utils} utils
* @param {import('comment-parser').Spec & {
* line: import('../iterateJsdoc.js').Integer
* }} tag
* @param {CustomSpacings} customSpacings
*/
const checkNotAlignedPerTag = (utils, tag, customSpacings) => {
/*
start +
delimiter +
postDelimiter +
tag +
postTag +
type +
postType +
name +
postName +
description +
end +
lineEnd
*/
/**
* @typedef {"tag"|"type"|"name"|"description"} ContentProp
*/
/** @type {("postDelimiter"|"postTag"|"postType"|"postName")[]} */
let spacerProps;
/** @type {ContentProp[]} */
let contentProps;
const mightHaveNamepath = utils.tagMightHaveNamepath(tag.tag);
if (mightHaveNamepath) {
spacerProps = ['postDelimiter', 'postTag', 'postType', 'postName'];
contentProps = ['tag', 'type', 'name', 'description'];
} else {
spacerProps = ['postDelimiter', 'postTag', 'postType'];
contentProps = ['tag', 'type', 'description'];
}
const {
tokens
} = tag.source[0];
/**
* @param {import('../iterateJsdoc.js').Integer} idx
* @param {(notRet: boolean, contentProp: ContentProp) => void} [callbck]
*/
const followedBySpace = (idx, callbck) => {
const nextIndex = idx + 1;
return spacerProps.slice(nextIndex).some((spacerProp, innerIdx) => {
const contentProp = contentProps[nextIndex + innerIdx];
const spacePropVal = tokens[spacerProp];
const ret = spacePropVal;
if (callbck) {
callbck(!ret, contentProp);
}
return ret && (callbck || !contentProp);
});
};
const postHyphenSpacing = (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postHyphen) ?? 1;
const exactHyphenSpacing = new RegExp(`^\\s*-\\s{${postHyphenSpacing},${postHyphenSpacing}}(?!\\s)`, 'u');
const hasNoHyphen = !/^\s*-(?!$)(?=\s)/u.test(tokens.description);
const hasExactHyphenSpacing = exactHyphenSpacing.test(tokens.description);
// If checking alignment on multiple lines, need to check other `source`
// items
// Go through `post*` spacing properties and exit to indicate problem if
// extra spacing detected
const ok = !spacerProps.some((spacerProp, idx) => {
const contentProp = contentProps[idx];
const contentPropVal = tokens[contentProp];
const spacerPropVal = tokens[spacerProp];
const spacing = (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings[spacerProp]) || 1;
// There will be extra alignment if...
// 1. The spaces don't match the space it should have (1 or custom spacing) OR
return spacerPropVal.length !== spacing && spacerPropVal.length !== 0 ||
// 2. There is a (single) space, no immediate content, and yet another
// space is found subsequently (not separated by intervening content)
spacerPropVal && !contentPropVal && followedBySpace(idx);
}) && (hasNoHyphen || hasExactHyphenSpacing);
if (ok) {
return;
}
const fix = () => {
for (const [idx, spacerProp] of spacerProps.entries()) {
const contentProp = contentProps[idx];
const contentPropVal = tokens[contentProp];
if (contentPropVal) {
const spacing = (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings[spacerProp]) || 1;
tokens[spacerProp] = ''.padStart(spacing, ' ');
followedBySpace(idx, (hasSpace, contentPrp) => {
if (hasSpace) {
tokens[contentPrp] = '';
}
});
} else {
tokens[spacerProp] = '';
}
}
if (!hasExactHyphenSpacing) {
const hyphenSpacing = /^\s*-\s+/u;
tokens.description = tokens.description.replace(hyphenSpacing, '-' + ''.padStart(postHyphenSpacing, ' '));
}
utils.setTag(tag, tokens);
};
utils.reportJSDoc('Expected JSDoc block lines to not be aligned.', tag, fix, true);
};
/**
* @param {object} cfg
* @param {CustomSpacings} cfg.customSpacings
* @param {string} cfg.indent
* @param {import('comment-parser').Block} cfg.jsdoc
* @param {import('eslint').Rule.Node & {
* range: [number, number]
* }} cfg.jsdocNode
* @param {boolean} cfg.preserveMainDescriptionPostDelimiter
* @param {import('../iterateJsdoc.js').Report} cfg.report
* @param {string[]} cfg.tags
* @param {import('../iterateJsdoc.js').Utils} cfg.utils
* @param {string} cfg.wrapIndent
* @param {boolean} cfg.disableWrapIndent
* @returns {void}
*/
const checkAlignment = ({
customSpacings,
indent,
jsdoc,
jsdocNode,
preserveMainDescriptionPostDelimiter,
report,
tags,
utils,
wrapIndent,
disableWrapIndent
}) => {
const transform = commentFlow((0, _alignTransform.default)({
customSpacings,
indent,
preserveMainDescriptionPostDelimiter,
tags,
wrapIndent,
disableWrapIndent
}));
const transformedJsdoc = transform(jsdoc);
const comment = '/*' +
/**
* @type {import('eslint').Rule.Node & {
* range: [number, number], value: string
* }}
*/
jsdocNode.value + '*/';
const formatted = utils.stringify(transformedJsdoc).trimStart();
if (comment !== formatted) {
report('Expected JSDoc block lines to be aligned.', /** @type {import('eslint').Rule.ReportFixer} */fixer => {
return fixer.replaceText(jsdocNode, formatted);
});
}
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
indent,
jsdoc,
jsdocNode,
report,
context,
utils
}) => {
const {
tags: applicableTags = ['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return'],
preserveMainDescriptionPostDelimiter,
customSpacings,
wrapIndent = '',
disableWrapIndent = false
} = context.options[1] || {};
if (context.options[0] === 'always') {
// Skip if it contains only a single line.
if (!(
/**
* @type {import('eslint').Rule.Node & {
* range: [number, number], value: string
* }}
*/
jsdocNode.value.includes('\n'))) {
return;
}
checkAlignment({
customSpacings,
indent,
jsdoc,
jsdocNode,
preserveMainDescriptionPostDelimiter,
report,
tags: applicableTags,
utils,
wrapIndent,
disableWrapIndent
});
return;
}
const foundTags = utils.getPresentTags(applicableTags);
if (context.options[0] !== 'any') {
for (const tag of foundTags) {
checkNotAlignedPerTag(utils,
/**
* @type {import('comment-parser').Spec & {
* line: import('../iterateJsdoc.js').Integer
* }}
*/
tag, customSpacings);
}
}
for (const tag of foundTags) {
if (tag.source.length > 1) {
let idx = 0;
for (const {
tokens
// Avoid the tag line
} of tag.source.slice(1)) {
idx++;
if (!tokens.description ||
// Avoid first lines after multiline type
tokens.type || tokens.name) {
continue;
}
// Don't include a single separating space/tab
if (!disableWrapIndent && tokens.postDelimiter.slice(1) !== wrapIndent) {
utils.reportJSDoc('Expected wrap indent', {
line: tag.source[0].number + idx
}, () => {
tokens.postDelimiter = tokens.postDelimiter.charAt(0) + wrapIndent;
});
return;
}
}
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid alignment of JSDoc block lines.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-line-alignment.md#repos-sticky-header'
},
fixable: 'whitespace',
schema: [{
enum: ['always', 'never', 'any'],
type: 'string'
}, {
additionalProperties: false,
properties: {
customSpacings: {
additionalProperties: false,
properties: {
postDelimiter: {
type: 'integer'
},
postHyphen: {
type: 'integer'
},
postName: {
type: 'integer'
},
postTag: {
type: 'integer'
},
postType: {
type: 'integer'
}
}
},
preserveMainDescriptionPostDelimiter: {
default: false,
type: 'boolean'
},
tags: {
items: {
type: 'string'
},
type: 'array'
},
wrapIndent: {
type: 'string'
},
disableWrapIndent: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkLineAlignment.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,329 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} targetTagName
* @param {boolean} allowExtraTrailingParamDocs
* @param {boolean} checkDestructured
* @param {boolean} checkRestProperty
* @param {RegExp} checkTypesRegex
* @param {boolean} disableExtraPropertyReporting
* @param {boolean} disableMissingParamChecks
* @param {boolean} enableFixer
* @param {import('../jsdocUtils.js').ParamNameInfo[]} functionParameterNames
* @param {import('comment-parser').Block} jsdoc
* @param {import('../iterateJsdoc.js').Utils} utils
* @param {import('../iterateJsdoc.js').Report} report
* @returns {boolean}
*/
const validateParameterNames = (targetTagName, allowExtraTrailingParamDocs, checkDestructured, checkRestProperty, checkTypesRegex, disableExtraPropertyReporting, disableMissingParamChecks, enableFixer, functionParameterNames, jsdoc, utils, report) => {
const paramTags = Object.entries(jsdoc.tags).filter(([, tag]) => {
return tag.tag === targetTagName;
});
const paramTagsNonNested = paramTags.filter(([, tag]) => {
return !tag.name.includes('.');
});
let dotted = 0;
let thisOffset = 0;
// eslint-disable-next-line complexity
return paramTags.some(([, tag], index) => {
/** @type {import('../iterateJsdoc.js').Integer} */
let tagsIndex;
const dupeTagInfo = paramTags.find(([tgsIndex, tg], idx) => {
tagsIndex = Number(tgsIndex);
return tg.name === tag.name && idx !== index;
});
if (dupeTagInfo) {
utils.reportJSDoc(`Duplicate @${targetTagName} "${tag.name}"`, dupeTagInfo[1], enableFixer ? () => {
utils.removeTag(tagsIndex);
} : null);
return true;
}
if (tag.name.includes('.')) {
dotted++;
return false;
}
let functionParameterName = functionParameterNames[index - dotted + thisOffset];
if (functionParameterName === 'this' && tag.name.trim() !== 'this') {
++thisOffset;
functionParameterName = functionParameterNames[index - dotted + thisOffset];
}
if (!functionParameterName) {
if (allowExtraTrailingParamDocs) {
return false;
}
report(`@${targetTagName} "${tag.name}" does not match an existing function parameter.`, null, tag);
return true;
}
if (typeof functionParameterName === 'object' && 'name' in functionParameterName && Array.isArray(functionParameterName.name)) {
const actualName = tag.name.trim();
const expectedName = functionParameterName.name[index];
if (actualName === expectedName) {
thisOffset--;
return false;
}
report(`Expected @${targetTagName} name to be "${expectedName}". Got "${actualName}".`, null, tag);
return true;
}
if (Array.isArray(functionParameterName)) {
if (!checkDestructured) {
return false;
}
if (tag.type && tag.type.search(checkTypesRegex) === -1) {
return false;
}
const [parameterName, {
names: properties,
hasPropertyRest,
rests,
annotationParamName
}] =
/**
* @type {[string | undefined, import('../jsdocUtils.js').FlattendRootInfo & {
* annotationParamName?: string | undefined;
}]} */
functionParameterName;
if (annotationParamName !== undefined) {
const name = tag.name.trim();
if (name !== annotationParamName) {
report(`@${targetTagName} "${name}" does not match parameter name "${annotationParamName}"`, null, tag);
}
}
const tagName = parameterName === undefined ? tag.name.trim() : parameterName;
const expectedNames = properties.map(name => {
return `${tagName}.${name}`;
});
const actualNames = paramTags.map(([, paramTag]) => {
return paramTag.name.trim();
});
const actualTypes = paramTags.map(([, paramTag]) => {
return paramTag.type;
});
const missingProperties = [];
/** @type {string[]} */
const notCheckingNames = [];
for (const [idx, name] of expectedNames.entries()) {
if (notCheckingNames.some(notCheckingName => {
return name.startsWith(notCheckingName);
})) {
continue;
}
const actualNameIdx = actualNames.findIndex(actualName => {
return utils.comparePaths(name)(actualName);
});
if (actualNameIdx === -1) {
if (!checkRestProperty && rests[idx]) {
continue;
}
const missingIndex = actualNames.findIndex(actualName => {
return utils.pathDoesNotBeginWith(name, actualName);
});
const line = tag.source[0].number - 1 + (missingIndex > -1 ? missingIndex : actualNames.length);
missingProperties.push({
name,
tagPlacement: {
line: line === 0 ? 1 : line
}
});
} else if (actualTypes[actualNameIdx].search(checkTypesRegex) === -1 && actualTypes[actualNameIdx] !== '') {
notCheckingNames.push(name);
}
}
const hasMissing = missingProperties.length;
if (hasMissing) {
for (const {
tagPlacement,
name: missingProperty
} of missingProperties) {
report(`Missing @${targetTagName} "${missingProperty}"`, null, tagPlacement);
}
}
if (!hasPropertyRest || checkRestProperty) {
/** @type {[string, import('comment-parser').Spec][]} */
const extraProperties = [];
for (const [idx, name] of actualNames.entries()) {
const match = name.startsWith(tag.name.trim() + '.');
if (match && !expectedNames.some(utils.comparePaths(name)) && !utils.comparePaths(name)(tag.name) && (!disableExtraPropertyReporting || properties.some(prop => {
return prop.split('.').length >= name.split('.').length - 1;
}))) {
extraProperties.push([name, paramTags[idx][1]]);
}
}
if (extraProperties.length) {
for (const [extraProperty, tg] of extraProperties) {
report(`@${targetTagName} "${extraProperty}" does not exist on ${tag.name}`, null, tg);
}
return true;
}
}
return hasMissing;
}
let funcParamName;
if (typeof functionParameterName === 'object') {
const {
name
} = functionParameterName;
funcParamName = name;
} else {
funcParamName = functionParameterName;
}
if (funcParamName !== tag.name.trim()) {
// Todo: Improve for array or object child items
const actualNames = paramTagsNonNested.map(([, {
name
}]) => {
return name.trim();
});
const expectedNames = functionParameterNames.map((item, idx) => {
var _item$;
if (
/**
* @type {[string|undefined, (import('../jsdocUtils.js').FlattendRootInfo & {
* annotationParamName?: string,
})]} */
item !== null && item !== void 0 && (_item$ = item[1]) !== null && _item$ !== void 0 && _item$.names) {
return actualNames[idx];
}
return item;
}).filter(item => {
return item !== 'this';
});
// When disableMissingParamChecks is true tag names can be omitted.
// Report when the tag names do not match the expected names or they are used out of order.
if (disableMissingParamChecks) {
const usedExpectedNames = expectedNames.map(a => a === null || a === void 0 ? void 0 : a.toString()).filter(expectedName => expectedName && actualNames.includes(expectedName));
const usedInOrder = actualNames.every((actualName, idx) => actualName === usedExpectedNames[idx]);
if (usedInOrder) {
return false;
}
}
report(`Expected @${targetTagName} names to be "${expectedNames.map(expectedName => {
return typeof expectedName === 'object' && 'name' in expectedName && expectedName.restElement ? '...' + expectedName.name : expectedName;
}).join(', ')}". Got "${actualNames.join(', ')}".`, null, tag);
return true;
}
return false;
});
};
/**
* @param {string} targetTagName
* @param {boolean} _allowExtraTrailingParamDocs
* @param {{
* name: string,
* idx: import('../iterateJsdoc.js').Integer
* }[]} jsdocParameterNames
* @param {import('comment-parser').Block} jsdoc
* @param {Function} report
* @returns {boolean}
*/
const validateParameterNamesDeep = (targetTagName, _allowExtraTrailingParamDocs, jsdocParameterNames, jsdoc, report) => {
/** @type {string} */
let lastRealParameter;
return jsdocParameterNames.some(({
name: jsdocParameterName,
idx
}) => {
const isPropertyPath = jsdocParameterName.includes('.');
if (isPropertyPath) {
if (!lastRealParameter) {
report(`@${targetTagName} path declaration ("${jsdocParameterName}") appears before any real parameter.`, null, jsdoc.tags[idx]);
return true;
}
let pathRootNodeName = jsdocParameterName.slice(0, jsdocParameterName.indexOf('.'));
if (pathRootNodeName.endsWith('[]')) {
pathRootNodeName = pathRootNodeName.slice(0, -2);
}
if (pathRootNodeName !== lastRealParameter) {
report(`@${targetTagName} path declaration ("${jsdocParameterName}") root node name ("${pathRootNodeName}") ` + `does not match previous real parameter name ("${lastRealParameter}").`, null, jsdoc.tags[idx]);
return true;
}
} else {
lastRealParameter = jsdocParameterName;
}
return false;
});
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
utils
}) => {
const {
allowExtraTrailingParamDocs,
checkDestructured = true,
checkRestProperty = false,
checkTypesPattern = '/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/',
enableFixer = false,
useDefaultObjectProperties = false,
disableExtraPropertyReporting = false,
disableMissingParamChecks = false
} = context.options[0] || {};
const checkTypesRegex = utils.getRegexFromString(checkTypesPattern);
const jsdocParameterNamesDeep = utils.getJsdocTagsDeep('param');
if (!jsdocParameterNamesDeep || !jsdocParameterNamesDeep.length) {
return;
}
const functionParameterNames = utils.getFunctionParameterNames(useDefaultObjectProperties);
const targetTagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'param'
});
const isError = validateParameterNames(targetTagName, allowExtraTrailingParamDocs, checkDestructured, checkRestProperty, checkTypesRegex, disableExtraPropertyReporting, disableMissingParamChecks, enableFixer, functionParameterNames, jsdoc, utils, report);
if (isError || !checkDestructured) {
return;
}
validateParameterNamesDeep(targetTagName, allowExtraTrailingParamDocs, jsdocParameterNamesDeep, jsdoc, report);
}, {
contextDefaults: ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'TSDeclareFunction',
// Add this to above defaults
'TSMethodSignature'],
meta: {
docs: {
description: 'Ensures that parameter names in JSDoc match those in the function declaration.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-param-names.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
allowExtraTrailingParamDocs: {
type: 'boolean'
},
checkDestructured: {
type: 'boolean'
},
checkRestProperty: {
type: 'boolean'
},
checkTypesPattern: {
type: 'string'
},
disableExtraPropertyReporting: {
type: 'boolean'
},
disableMissingParamChecks: {
type: 'boolean'
},
enableFixer: {
type: 'boolean'
},
useDefaultObjectProperties: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkParamNames.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,116 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} targetTagName
* @param {boolean} enableFixer
* @param {import('comment-parser').Block} jsdoc
* @param {import('../iterateJsdoc.js').Utils} utils
* @returns {boolean}
*/
const validatePropertyNames = (targetTagName, enableFixer, jsdoc, utils) => {
const propertyTags = Object.entries(jsdoc.tags).filter(([, tag]) => {
return tag.tag === targetTagName;
});
return propertyTags.some(([, tag], index) => {
/** @type {import('../iterateJsdoc.js').Integer} */
let tagsIndex;
const dupeTagInfo = propertyTags.find(([tgsIndex, tg], idx) => {
tagsIndex = Number(tgsIndex);
return tg.name === tag.name && idx !== index;
});
if (dupeTagInfo) {
utils.reportJSDoc(`Duplicate @${targetTagName} "${tag.name}"`, dupeTagInfo[1], enableFixer ? () => {
utils.removeTag(tagsIndex);
} : null);
return true;
}
return false;
});
};
/**
* @param {string} targetTagName
* @param {{
* idx: number;
* name: string;
* type: string;
* }[]} jsdocPropertyNames
* @param {import('comment-parser').Block} jsdoc
* @param {Function} report
*/
const validatePropertyNamesDeep = (targetTagName, jsdocPropertyNames, jsdoc, report) => {
/** @type {string} */
let lastRealProperty;
return jsdocPropertyNames.some(({
name: jsdocPropertyName,
idx
}) => {
const isPropertyPath = jsdocPropertyName.includes('.');
if (isPropertyPath) {
if (!lastRealProperty) {
report(`@${targetTagName} path declaration ("${jsdocPropertyName}") appears before any real property.`, null, jsdoc.tags[idx]);
return true;
}
let pathRootNodeName = jsdocPropertyName.slice(0, jsdocPropertyName.indexOf('.'));
if (pathRootNodeName.endsWith('[]')) {
pathRootNodeName = pathRootNodeName.slice(0, -2);
}
if (pathRootNodeName !== lastRealProperty) {
report(`@${targetTagName} path declaration ("${jsdocPropertyName}") root node name ("${pathRootNodeName}") ` + `does not match previous real property name ("${lastRealProperty}").`, null, jsdoc.tags[idx]);
return true;
}
} else {
lastRealProperty = jsdocPropertyName;
}
return false;
});
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
utils
}) => {
const {
enableFixer = false
} = context.options[0] || {};
const jsdocPropertyNamesDeep = utils.getJsdocTagsDeep('property');
if (!jsdocPropertyNamesDeep || !jsdocPropertyNamesDeep.length) {
return;
}
const targetTagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'property'
});
const isError = validatePropertyNames(targetTagName, enableFixer, jsdoc, utils);
if (isError) {
return;
}
validatePropertyNamesDeep(targetTagName, jsdocPropertyNamesDeep, jsdoc, report);
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Ensures that property names in JSDoc are not duplicated on the same block and that nested properties have defined roots.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-property-names.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
enableFixer: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkPropertyNames.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
report,
settings
}) => {
const {
mode
} = settings;
// Don't check for "permissive" and "closure"
if (mode === 'jsdoc' || mode === 'typescript') {
for (const tag of jsdoc.tags) {
if (tag.type.slice(-1) === '=') {
report('Syntax should not be Google Closure Compiler style.', null, tag);
break;
}
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports against syntax not valid for the mode (e.g., Google Closure Compiler in non-Closure mode).',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-syntax.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkSyntax.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"checkSyntax.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","jsdoc","report","settings","mode","tag","tags","type","slice","iterateAllJsdocs","meta","docs","description","url","module"],"sources":["../../src/rules/checkSyntax.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n jsdoc,\n report,\n settings,\n}) => {\n const {\n mode,\n } = settings;\n\n // Don't check for \"permissive\" and \"closure\"\n if (mode === 'jsdoc' || mode === 'typescript') {\n for (const tag of jsdoc.tags) {\n if (tag.type.slice(-1) === '=') {\n report('Syntax should not be Google Closure Compiler style.', null, tag);\n break;\n }\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Reports against syntax not valid for the mode (e.g., Google Closure Compiler in non-Closure mode).',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-syntax.md#repos-sticky-header',\n },\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,KAAK;EACLC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ,MAAM;IACJC;EACF,CAAC,GAAGD,QAAQ;;EAEZ;EACA,IAAIC,IAAI,KAAK,OAAO,IAAIA,IAAI,KAAK,YAAY,EAAE;IAC7C,KAAK,MAAMC,GAAG,IAAIJ,KAAK,CAACK,IAAI,EAAE;MAC5B,IAAID,GAAG,CAACE,IAAI,CAACC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;QAC9BN,MAAM,CAAC,qDAAqD,EAAE,IAAI,EAAEG,GAAG,CAAC;QACxE;MACF;IACF;EACF;AACF,CAAC,EAAE;EACDI,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,oGAAoG;MACjHC,GAAG,EAAE;IACP,CAAC;IACDN,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAO,MAAA,CAAAf,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,215 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _escapeStringRegexp = _interopRequireDefault(require("escape-string-regexp"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/
const jsxTagNames = new Set(['jsx', 'jsxFrag', 'jsxImportSource', 'jsxRuntime']);
const typedTagsAlwaysUnnecessary = new Set(['augments', 'callback', 'class', 'enum', 'implements', 'private', 'property', 'protected', 'public', 'readonly', 'this', 'type', 'typedef']);
const typedTagsNeedingName = new Set(['template']);
const typedTagsUnnecessaryOutsideDeclare = new Set(['abstract', 'access', 'class', 'constant', 'constructs', 'default', 'enum', 'export', 'exports', 'function', 'global', 'inherits', 'instance', 'interface', 'member', 'memberof', 'memberOf', 'method', 'mixes', 'mixin', 'module', 'name', 'namespace', 'override', 'property', 'requires', 'static', 'this']);
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
jsdoc,
report,
utils,
context,
node,
settings,
jsdocNode
}) => {
const
/**
* @type {{
* definedTags: string[],
* enableFixer: boolean,
* jsxTags: boolean,
* typed: boolean
}} */
{
definedTags = [],
enableFixer = true,
jsxTags,
typed
} = context.options[0] || {};
/** @type {(string|undefined)[]} */
let definedPreferredTags = [];
const {
tagNamePreference,
structuredTags
} = settings;
const definedStructuredTags = Object.keys(structuredTags);
const definedNonPreferredTags = Object.keys(tagNamePreference);
if (definedNonPreferredTags.length) {
definedPreferredTags = Object.values(tagNamePreference).map(preferredTag => {
if (typeof preferredTag === 'string') {
// May become an empty string but will be filtered out below
return preferredTag;
}
if (!preferredTag) {
return undefined;
}
if (typeof preferredTag !== 'object') {
utils.reportSettings('Invalid `settings.jsdoc.tagNamePreference`. Values must be falsy, a string, or an object.');
}
return preferredTag.replacement;
}).filter(Boolean);
}
/**
* @param {import('eslint').Rule.Node} subNode
* @returns {boolean}
*/
const isInAmbientContext = subNode => {
return subNode.type === 'Program' ? context.getFilename().endsWith('.d.ts') : Boolean( /** @type {import('@typescript-eslint/types').TSESTree.VariableDeclaration} */subNode.declare) || isInAmbientContext(subNode.parent);
};
/**
* @param {import('comment-parser').Spec} jsdocTag
* @returns {boolean}
*/
const tagIsRedundantWhenTyped = jsdocTag => {
var _node$parent;
if (!typedTagsUnnecessaryOutsideDeclare.has(jsdocTag.tag)) {
return false;
}
if (jsdocTag.tag === 'default') {
return false;
}
if (node === null) {
return false;
}
if (context.getFilename().endsWith('.d.ts') && ['Program', null, undefined].includes(node === null || node === void 0 || (_node$parent = node.parent) === null || _node$parent === void 0 ? void 0 : _node$parent.type)) {
return false;
}
if (isInAmbientContext( /** @type {import('eslint').Rule.Node} */node)) {
return false;
}
return true;
};
/**
* @param {string} message
* @param {import('comment-parser').Spec} jsdocTag
* @param {import('../iterateJsdoc.js').Integer} tagIndex
* @param {Partial<import('comment-parser').Tokens>} [additionalTagChanges]
* @returns {void}
*/
const reportWithTagRemovalFixer = (message, jsdocTag, tagIndex, additionalTagChanges) => {
utils.reportJSDoc(message, jsdocTag, enableFixer ? () => {
if (jsdocTag.description.trim()) {
utils.changeTag(jsdocTag, {
postType: '',
type: '',
...additionalTagChanges
});
} else {
utils.removeTag(tagIndex, {
removeEmptyBlock: true
});
}
} : null, true);
};
/**
* @param {import('comment-parser').Spec} jsdocTag
* @param {import('../iterateJsdoc.js').Integer} tagIndex
* @returns {boolean}
*/
const checkTagForTypedValidity = (jsdocTag, tagIndex) => {
if (typedTagsAlwaysUnnecessary.has(jsdocTag.tag)) {
reportWithTagRemovalFixer(`'@${jsdocTag.tag}' is redundant when using a type system.`, jsdocTag, tagIndex, {
postTag: '',
tag: ''
});
return true;
}
if (tagIsRedundantWhenTyped(jsdocTag)) {
reportWithTagRemovalFixer(`'@${jsdocTag.tag}' is redundant outside of ambient (\`declare\`/\`.d.ts\`) contexts when using a type system.`, jsdocTag, tagIndex);
return true;
}
if (typedTagsNeedingName.has(jsdocTag.tag) && !jsdocTag.name) {
reportWithTagRemovalFixer(`'@${jsdocTag.tag}' without a name is redundant when using a type system.`, jsdocTag, tagIndex);
return true;
}
return false;
};
for (let tagIndex = 0; tagIndex < jsdoc.tags.length; tagIndex += 1) {
const jsdocTag = jsdoc.tags[tagIndex];
const tagName = jsdocTag.tag;
if (jsxTags && jsxTagNames.has(tagName)) {
continue;
}
if (typed && checkTagForTypedValidity(jsdocTag, tagIndex)) {
continue;
}
const validTags = [...definedTags, ...( /** @type {string[]} */definedPreferredTags), ...definedNonPreferredTags, ...definedStructuredTags, ...(typed ? typedTagsNeedingName : [])];
if (utils.isValidTag(tagName, validTags)) {
let preferredTagName = utils.getPreferredTagName({
allowObjectReturn: true,
defaultMessage: `Blacklisted tag found (\`@${tagName}\`)`,
tagName
});
if (!preferredTagName) {
continue;
}
let message;
if (typeof preferredTagName === 'object') {
({
message,
replacement: preferredTagName
} = /** @type {{message: string; replacement?: string | undefined;}} */
preferredTagName);
}
if (!message) {
message = `Invalid JSDoc tag (preference). Replace "${tagName}" JSDoc tag with "${preferredTagName}".`;
}
if (preferredTagName !== tagName) {
report(message, fixer => {
const replacement = sourceCode.getText(jsdocNode).replace(new RegExp(`@${(0, _escapeStringRegexp.default)(tagName)}\\b`, 'u'), `@${preferredTagName}`);
return fixer.replaceText(jsdocNode, replacement);
}, jsdocTag);
}
} else {
report(`Invalid JSDoc tag name "${tagName}".`, null, jsdocTag);
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid block tag names.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-tag-names.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
definedTags: {
items: {
type: 'string'
},
type: 'array'
},
enableFixer: {
type: 'boolean'
},
jsxTags: {
type: 'boolean'
},
typed: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkTagNames.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,173 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
utils,
node,
settings,
report
}) => {
const {
mode
} = settings;
const templateTags = utils.getTags('template');
const usedNames = new Set();
/**
* @param {string} potentialType
*/
const checkForUsedTypes = potentialType => {
let parsedType;
try {
parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode);
} catch {
return;
}
(0, _jsdoccomment.traverse)(parsedType, nde => {
const {
type,
value
} = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
usedNames.add(value);
}
});
};
const checkParamsAndReturnsTags = () => {
const paramName = /** @type {string} */utils.getPreferredTagName({
tagName: 'param'
});
const paramTags = utils.getTags(paramName);
for (const paramTag of paramTags) {
checkForUsedTypes(paramTag.type);
}
const returnsName = /** @type {string} */utils.getPreferredTagName({
tagName: 'returns'
});
const returnsTags = utils.getTags(returnsName);
for (const returnsTag of returnsTags) {
checkForUsedTypes(returnsTag.type);
}
};
const checkTemplateTags = () => {
for (const tag of templateTags) {
const {
name
} = tag;
const names = name.split(/,\s*/);
for (const name of names) {
if (!usedNames.has(name)) {
report(`@template ${name} not in use`, null, tag);
}
}
}
};
/**
* @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration|
* import('@typescript-eslint/types').TSESTree.ClassDeclaration|
* import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|
* import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration
* @param {boolean} [checkParamsAndReturns]
*/
const checkParameters = (aliasDeclaration, checkParamsAndReturns) => {
/* c8 ignore next -- Guard */
const {
params
} = aliasDeclaration.typeParameters ?? {
params: []
};
for (const {
name: {
name
}
} of params) {
usedNames.add(name);
}
if (checkParamsAndReturns) {
checkParamsAndReturnsTags();
}
checkTemplateTags();
};
const handleTypeAliases = () => {
var _nde$declaration;
const nde = /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node;
if (!nde) {
return;
}
switch (nde.type) {
case 'ExportDefaultDeclaration':
case 'ExportNamedDeclaration':
switch ((_nde$declaration = nde.declaration) === null || _nde$declaration === void 0 ? void 0 : _nde$declaration.type) {
case 'FunctionDeclaration':
checkParameters(nde.declaration, true);
break;
case 'ClassDeclaration':
case 'TSTypeAliasDeclaration':
case 'TSInterfaceDeclaration':
checkParameters(nde.declaration);
break;
}
break;
case 'FunctionDeclaration':
checkParameters(nde, true);
break;
case 'ClassDeclaration':
case 'TSTypeAliasDeclaration':
case 'TSInterfaceDeclaration':
checkParameters(nde);
break;
}
};
const callbackTags = utils.getTags('callback');
const functionTags = utils.getTags('function');
if (callbackTags.length || functionTags.length) {
checkParamsAndReturnsTags();
checkTemplateTags();
return;
}
const typedefTags = utils.getTags('typedef');
if (!typedefTags.length || typedefTags.length >= 2) {
handleTypeAliases();
return;
}
const potentialTypedefType = typedefTags[0].type;
checkForUsedTypes(potentialTypedefType);
const propertyName = /** @type {string} */utils.getPreferredTagName({
tagName: 'property'
});
const propertyTags = utils.getTags(propertyName);
for (const propertyTag of propertyTags) {
checkForUsedTypes(propertyTag.type);
}
for (const tag of templateTags) {
const {
name
} = tag;
const names = name.split(/,\s*/);
for (const name of names) {
if (!usedNames.has(name)) {
report(`@template ${name} not in use`, null, tag);
}
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that any `@template` names are actually used in the connected `@typedef` or type alias.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-template.md#repos-sticky-header'
},
schema: [],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkTemplateNames.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,396 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _jsdoccomment = require("@es-joy/jsdoccomment");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const strictNativeTypes = ['undefined', 'null', 'boolean', 'number', 'bigint', 'string', 'symbol', 'object', 'Array', 'Function', 'Date', 'RegExp'];
/**
* Adjusts the parent type node `meta` for generic matches (or type node
* `type` for `JsdocTypeAny`) and sets the type node `value`.
* @param {string} type The actual type
* @param {string} preferred The preferred type
* @param {boolean} isGenericMatch
* @param {string} typeNodeName
* @param {import('jsdoc-type-pratt-parser').NonRootResult} node
* @param {import('jsdoc-type-pratt-parser').NonRootResult|undefined} parentNode
* @returns {void}
*/
const adjustNames = (type, preferred, isGenericMatch, typeNodeName, node, parentNode) => {
let ret = preferred;
if (isGenericMatch) {
const parentMeta = /** @type {import('jsdoc-type-pratt-parser').GenericResult} */parentNode.meta;
if (preferred === '[]') {
parentMeta.brackets = 'square';
parentMeta.dot = false;
ret = 'Array';
} else {
const dotBracketEnd = preferred.match(/\.(?:<>)?$/u);
if (dotBracketEnd) {
parentMeta.brackets = 'angle';
parentMeta.dot = true;
ret = preferred.slice(0, -dotBracketEnd[0].length);
} else {
const bracketEnd = preferred.endsWith('<>');
if (bracketEnd) {
parentMeta.brackets = 'angle';
parentMeta.dot = false;
ret = preferred.slice(0, -2);
} else if ((parentMeta === null || parentMeta === void 0 ? void 0 : parentMeta.brackets) === 'square' && (typeNodeName === '[]' || typeNodeName === 'Array')) {
parentMeta.brackets = 'angle';
parentMeta.dot = false;
}
}
}
} else if (type === 'JsdocTypeAny') {
node.type = 'JsdocTypeName';
}
/** @type {import('jsdoc-type-pratt-parser').NameResult} */
node.value = ret.replace(/(?:\.|<>|\.<>|\[\])$/u, '');
// For bare pseudo-types like `<>`
if (!ret) {
/** @type {import('jsdoc-type-pratt-parser').NameResult} */node.value = typeNodeName;
}
};
/**
* @param {boolean} [upperCase]
* @returns {string}
*/
const getMessage = upperCase => {
return 'Use object shorthand or index signatures instead of ' + '`' + (upperCase ? 'O' : 'o') + 'bject`, e.g., `{[key: string]: string}`';
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdocNode,
sourceCode,
report,
utils,
settings,
context
}) => {
const jsdocTagsWithPossibleType = utils.filterTags(tag => {
return Boolean(utils.tagMightHaveTypePosition(tag.tag));
});
const
/**
* @type {{
* preferredTypes: import('../iterateJsdoc.js').PreferredTypes,
* structuredTags: import('../iterateJsdoc.js').StructuredTags,
* mode: import('../jsdocUtils.js').ParserMode
* }}
*/
{
preferredTypes: preferredTypesOriginal,
structuredTags,
mode
} = settings;
const injectObjectPreferredTypes = !('Object' in preferredTypesOriginal || 'object' in preferredTypesOriginal || 'object.<>' in preferredTypesOriginal || 'Object.<>' in preferredTypesOriginal || 'object<>' in preferredTypesOriginal);
/**
* @type {{
* message: string,
* replacement: false
* }}
*/
const info = {
message: getMessage(),
replacement: false
};
/**
* @type {{
* message: string,
* replacement: false
* }}
*/
const infoUC = {
message: getMessage(true),
replacement: false
};
/** @type {import('../iterateJsdoc.js').PreferredTypes} */
const typeToInject = mode === 'typescript' ? {
Object: 'object',
'object.<>': info,
'Object.<>': infoUC,
'object<>': info,
'Object<>': infoUC
} : {
Object: 'object',
'object.<>': 'Object<>',
'Object.<>': 'Object<>',
'object<>': 'Object<>'
};
/** @type {import('../iterateJsdoc.js').PreferredTypes} */
const preferredTypes = {
...(injectObjectPreferredTypes ? typeToInject : {}),
...preferredTypesOriginal
};
const
/**
* @type {{
* noDefaults: boolean,
* unifyParentAndChildTypeChecks: boolean,
* exemptTagContexts: ({
* tag: string,
* types: true|string[]
* })[]
* }}
*/
{
noDefaults,
unifyParentAndChildTypeChecks,
exemptTagContexts = []
} = context.options[0] || {};
/**
* Gets information about the preferred type: whether there is a matching
* preferred type, what the type is, and whether it is a match to a generic.
* @param {string} _type Not currently in use
* @param {string} typeNodeName
* @param {import('jsdoc-type-pratt-parser').NonRootResult|undefined} parentNode
* @param {string|undefined} property
* @returns {[hasMatchingPreferredType: boolean, typeName: string, isGenericMatch: boolean]}
*/
const getPreferredTypeInfo = (_type, typeNodeName, parentNode, property) => {
let hasMatchingPreferredType = false;
let isGenericMatch = false;
let typeName = typeNodeName;
const isNameOfGeneric = parentNode !== undefined && parentNode.type === 'JsdocTypeGeneric' && property === 'left';
if (unifyParentAndChildTypeChecks || isNameOfGeneric) {
var _parentNode$meta, _parentNode$meta2;
const brackets = /** @type {import('jsdoc-type-pratt-parser').GenericResult} */parentNode === null || parentNode === void 0 || (_parentNode$meta = parentNode.meta) === null || _parentNode$meta === void 0 ? void 0 : _parentNode$meta.brackets;
const dot = /** @type {import('jsdoc-type-pratt-parser').GenericResult} */parentNode === null || parentNode === void 0 || (_parentNode$meta2 = parentNode.meta) === null || _parentNode$meta2 === void 0 ? void 0 : _parentNode$meta2.dot;
if (brackets === 'angle') {
const checkPostFixes = dot ? ['.', '.<>'] : ['<>'];
isGenericMatch = checkPostFixes.some(checkPostFix => {
if ((preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[typeNodeName + checkPostFix]) !== undefined) {
typeName += checkPostFix;
return true;
}
return false;
});
}
if (!isGenericMatch && property && /** @type {import('jsdoc-type-pratt-parser').NonRootResult} */parentNode.type === 'JsdocTypeGeneric') {
const checkPostFixes = dot ? ['.', '.<>'] : [brackets === 'angle' ? '<>' : '[]'];
isGenericMatch = checkPostFixes.some(checkPostFix => {
if ((preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[checkPostFix]) !== undefined) {
typeName = checkPostFix;
return true;
}
return false;
});
}
}
const directNameMatch = (preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[typeNodeName]) !== undefined && !Object.values(preferredTypes).includes(typeNodeName);
const unifiedSyntaxParentMatch = property && directNameMatch && unifyParentAndChildTypeChecks;
isGenericMatch = isGenericMatch || Boolean(unifiedSyntaxParentMatch);
hasMatchingPreferredType = isGenericMatch || directNameMatch && !property;
return [hasMatchingPreferredType, typeName, isGenericMatch];
};
/**
* Iterates strict types to see if any should be added to `invalidTypes` (and
* the the relevant strict type returned as the new preferred type).
* @param {string} typeNodeName
* @param {string|undefined} preferred
* @param {import('jsdoc-type-pratt-parser').NonRootResult|undefined} parentNode
* @param {(string|false|undefined)[][]} invalidTypes
* @returns {string|undefined} The `preferred` type string, optionally changed
*/
const checkNativeTypes = (typeNodeName, preferred, parentNode, invalidTypes) => {
let changedPreferred = preferred;
for (const strictNativeType of strictNativeTypes) {
var _parentNode$elements, _parentNode$left, _parentNode$left2;
if (strictNativeType === 'object' && (
// This is not set to remap with exact type match (e.g.,
// `object: 'Object'`), so can ignore (including if circular)
!(preferredTypes !== null && preferredTypes !== void 0 && preferredTypes[typeNodeName]) ||
// Although present on `preferredTypes` for remapping, this is a
// parent object without a parent match (and not
// `unifyParentAndChildTypeChecks`) and we don't want
// `object<>` given TypeScript issue https://github.com/microsoft/TypeScript/issues/20555
/**
* @type {import('jsdoc-type-pratt-parser').GenericResult}
*/
parentNode !== null && parentNode !== void 0 && (_parentNode$elements = parentNode.elements) !== null && _parentNode$elements !== void 0 && _parentNode$elements.length && (
/**
* @type {import('jsdoc-type-pratt-parser').GenericResult}
*/
(parentNode === null || parentNode === void 0 || (_parentNode$left = parentNode.left) === null || _parentNode$left === void 0 ? void 0 : _parentNode$left.type) === 'JsdocTypeName' &&
/**
* @type {import('jsdoc-type-pratt-parser').GenericResult}
*/
(parentNode === null || parentNode === void 0 || (_parentNode$left2 = parentNode.left) === null || _parentNode$left2 === void 0 ? void 0 : _parentNode$left2.value) === 'Object'))) {
continue;
}
if (strictNativeType !== typeNodeName && strictNativeType.toLowerCase() === typeNodeName.toLowerCase() && (
// Don't report if user has own map for a strict native type
!preferredTypes || (preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[strictNativeType]) === undefined)) {
changedPreferred = strictNativeType;
invalidTypes.push([typeNodeName, changedPreferred]);
break;
}
}
return changedPreferred;
};
/**
* Collect invalid type info.
* @param {string} type
* @param {string} value
* @param {string} tagName
* @param {string} nameInTag
* @param {number} idx
* @param {string|undefined} property
* @param {import('jsdoc-type-pratt-parser').NonRootResult} node
* @param {import('jsdoc-type-pratt-parser').NonRootResult|undefined} parentNode
* @param {(string|false|undefined)[][]} invalidTypes
* @returns {void}
*/
const getInvalidTypes = (type, value, tagName, nameInTag, idx, property, node, parentNode, invalidTypes) => {
let typeNodeName = type === 'JsdocTypeAny' ? '*' : value;
const [hasMatchingPreferredType, typeName, isGenericMatch] = getPreferredTypeInfo(type, typeNodeName, parentNode, property);
let preferred;
let types;
if (hasMatchingPreferredType) {
const preferredSetting = preferredTypes[typeName];
typeNodeName = typeName === '[]' ? typeName : typeNodeName;
if (!preferredSetting) {
invalidTypes.push([typeNodeName]);
} else if (typeof preferredSetting === 'string') {
preferred = preferredSetting;
invalidTypes.push([typeNodeName, preferred]);
} else if (preferredSetting && typeof preferredSetting === 'object') {
const nextItem = preferredSetting.skipRootChecking && jsdocTagsWithPossibleType[idx + 1];
if (!nextItem || !nextItem.name.startsWith(`${nameInTag}.`)) {
preferred = preferredSetting.replacement;
invalidTypes.push([typeNodeName, preferred, preferredSetting.message]);
}
} else {
utils.reportSettings('Invalid `settings.jsdoc.preferredTypes`. Values must be falsy, a string, or an object.');
return;
}
} else if (Object.entries(structuredTags).some(([tag, {
type: typs
}]) => {
types = typs;
return tag === tagName && Array.isArray(types) && !types.includes(typeNodeName);
})) {
invalidTypes.push([typeNodeName, types]);
} else if (!noDefaults && type === 'JsdocTypeName') {
preferred = checkNativeTypes(typeNodeName, preferred, parentNode, invalidTypes);
}
// For fixer
if (preferred) {
adjustNames(type, preferred, isGenericMatch, typeNodeName, node, parentNode);
}
};
for (const [idx, jsdocTag] of jsdocTagsWithPossibleType.entries()) {
/** @type {(string|false|undefined)[][]} */
const invalidTypes = [];
let typeAst;
try {
typeAst = mode === 'permissive' ? (0, _jsdoccomment.tryParse)(jsdocTag.type) : (0, _jsdoccomment.parse)(jsdocTag.type, mode);
} catch {
continue;
}
const {
tag: tagName,
name: nameInTag
} = jsdocTag;
(0, _jsdoccomment.traverse)(typeAst, (node, parentNode, property) => {
const {
type,
value
} =
/**
* @type {import('jsdoc-type-pratt-parser').NameResult}
*/
node;
if (!['JsdocTypeName', 'JsdocTypeAny'].includes(type)) {
return;
}
getInvalidTypes(type, value, tagName, nameInTag, idx, property, node, parentNode, invalidTypes);
});
if (invalidTypes.length) {
const fixedType = (0, _jsdoccomment.stringify)(typeAst);
/**
* @type {import('eslint').Rule.ReportFixer}
*/
const fix = fixer => {
return fixer.replaceText(jsdocNode, sourceCode.getText(jsdocNode).replace(`{${jsdocTag.type}}`, `{${fixedType}}`));
};
for (const [badType, preferredType = '', msg] of invalidTypes) {
const tagValue = jsdocTag.name ? ` "${jsdocTag.name}"` : '';
if (exemptTagContexts.some(({
tag,
types
}) => {
return tag === tagName && (types === true || types.includes(jsdocTag.type));
})) {
continue;
}
report(msg || `Invalid JSDoc @${tagName}${tagValue} type "${badType}"` + (preferredType ? '; ' : '.') + (preferredType ? `prefer: ${JSON.stringify(preferredType)}.` : ''), preferredType ? fix : null, jsdocTag, msg ? {
tagName,
tagValue
} : undefined);
}
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid types.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-types.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
exemptTagContexts: {
items: {
additionalProperties: false,
properties: {
tag: {
type: 'string'
},
types: {
oneOf: [{
type: 'boolean'
}, {
items: {
type: 'string'
},
type: 'array'
}]
}
},
type: 'object'
},
type: 'array'
},
noDefaults: {
type: 'boolean'
},
unifyParentAndChildTypeChecks: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkTypes.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,154 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _nodePath = require("node:path");
var _nodeUrl = require("node:url");
var _synckit = require("synckit");
var _semver = _interopRequireDefault(require("semver"));
var _spdxExpressionParse = _interopRequireDefault(require("spdx-expression-parse"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const _dirname = (0, _nodePath.dirname)((0, _nodeUrl.fileURLToPath)(require('url').pathToFileURL(__filename).toString()));
const pathName = (0, _nodePath.join)(_dirname, '../import-worker.mjs');
const allowedKinds = new Set(['class', 'constant', 'event', 'external', 'file', 'function', 'member', 'mixin', 'module', 'namespace', 'typedef']);
var _default = exports.default = (0, _iterateJsdoc.default)(({
utils,
report,
context,
settings
}) => {
const options = context.options[0] || {};
const {
allowedLicenses = null,
allowedAuthors = null,
numericOnlyVariation = false,
licensePattern = '/([^\n\r]*)/gu'
} = options;
utils.forEachPreferredTag('version', (jsdocParameter, targetTagName) => {
const version = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!version) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (!_semver.default.valid(version)) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}".`, null, jsdocParameter);
}
});
utils.forEachPreferredTag('kind', (jsdocParameter, targetTagName) => {
const kind = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!kind) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (!allowedKinds.has(kind)) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}"; ` + `must be one of: ${[...allowedKinds].join(', ')}.`, null, jsdocParameter);
}
});
if (numericOnlyVariation) {
utils.forEachPreferredTag('variation', (jsdocParameter, targetTagName) => {
const variation = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!variation) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (!Number.isInteger(Number(variation)) || Number(variation) <= 0) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}".`, null, jsdocParameter);
}
});
}
utils.forEachPreferredTag('since', (jsdocParameter, targetTagName) => {
const version = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!version) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (!_semver.default.valid(version)) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}".`, null, jsdocParameter);
}
});
utils.forEachPreferredTag('license', (jsdocParameter, targetTagName) => {
const licenseRegex = utils.getRegexFromString(licensePattern, 'g');
const matches = /** @type {string} */utils.getTagDescription(jsdocParameter).matchAll(licenseRegex);
let positiveMatch = false;
for (const match of matches) {
const license = match[1] || match[0];
if (license) {
positiveMatch = true;
}
if (!license.trim()) {
// Avoid reporting again as empty match
if (positiveMatch) {
return;
}
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (allowedLicenses) {
if (allowedLicenses !== true && !allowedLicenses.includes(license)) {
report(`Invalid JSDoc @${targetTagName}: "${license}"; expected one of ${allowedLicenses.join(', ')}.`, null, jsdocParameter);
}
} else {
try {
(0, _spdxExpressionParse.default)(license);
} catch {
report(`Invalid JSDoc @${targetTagName}: "${license}"; expected SPDX expression: https://spdx.org/licenses/.`, null, jsdocParameter);
}
}
}
});
if (settings.mode === 'typescript') {
utils.forEachPreferredTag('import', tag => {
const {
type,
name,
description
} = tag;
const typePart = type ? `{${type}} ` : '';
const imprt = 'import ' + (description ? `${typePart}${name} ${description}` : `${typePart}${name}`);
const getImports = (0, _synckit.createSyncFn)(pathName);
if (!getImports(imprt)) {
report(`Bad @import tag`, null, tag);
}
});
}
utils.forEachPreferredTag('author', (jsdocParameter, targetTagName) => {
const author = /** @type {string} */utils.getTagDescription(jsdocParameter).trim();
if (!author) {
report(`Missing JSDoc @${targetTagName} value.`, null, jsdocParameter);
} else if (allowedAuthors && !allowedAuthors.includes(author)) {
report(`Invalid JSDoc @${targetTagName}: "${utils.getTagDescription(jsdocParameter)}"; expected one of ${allowedAuthors.join(', ')}.`, null, jsdocParameter);
}
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'This rule checks the values for a handful of tags: `@version`, `@since`, `@license` and `@author`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-values.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
allowedAuthors: {
items: {
type: 'string'
},
type: 'array'
},
allowedLicenses: {
anyOf: [{
items: {
type: 'string'
},
type: 'array'
}, {
type: 'boolean'
}]
},
licensePattern: {
type: 'string'
},
numericOnlyVariation: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=checkValues.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,312 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireWildcard(require("../iterateJsdoc.cjs"));
var _jsdocUtils = require("../jsdocUtils.cjs");
var _jsdoccomment = require("@es-joy/jsdoccomment");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
/** @type {import('eslint').Rule.RuleModule} */
var _default = exports.default = {
create(context) {
/**
* @typedef {import('eslint').AST.Token | import('estree').Comment | {
* type: import('eslint').AST.TokenType|"Line"|"Block"|"Shebang",
* range: [number, number],
* value: string
* }} Token
*/
/**
* @callback AddComment
* @param {boolean|undefined} inlineCommentBlock
* @param {Token} comment
* @param {string} indent
* @param {number} lines
* @param {import('eslint').Rule.RuleFixer} fixer
*/
/* c8 ignore next -- Fallback to deprecated method */
const {
sourceCode = context.getSourceCode()
} = context;
const settings = (0, _iterateJsdoc.getSettings)(context);
if (!settings) {
return {};
}
const {
contexts = settings.contexts || [],
contextsAfter = ( /** @type {string[]} */[]),
contextsBeforeAndAfter = ['VariableDeclarator', 'TSPropertySignature', 'PropertyDefinition'],
enableFixer = true,
enforceJsdocLineStyle = 'multi',
lineOrBlockStyle = 'both',
allowedPrefixes = ['@ts-', 'istanbul ', 'c8 ', 'v8 ', 'eslint', 'prettier-']
} = context.options[0] ?? {};
let reportingNonJsdoc = false;
/**
* @param {string} messageId
* @param {import('estree').Comment|Token} comment
* @param {import('eslint').Rule.Node} node
* @param {import('eslint').Rule.ReportFixer} fixer
*/
const report = (messageId, comment, node, fixer) => {
var _comment$loc, _comment$loc2;
const loc = {
end: {
column: 0,
/* c8 ignore next 2 -- Guard */
// @ts-expect-error Ok
line: ((_comment$loc = comment.loc) === null || _comment$loc === void 0 || (_comment$loc = _comment$loc.start) === null || _comment$loc === void 0 ? void 0 : _comment$loc.line) ?? 1
},
start: {
column: 0,
/* c8 ignore next 2 -- Guard */
// @ts-expect-error Ok
line: ((_comment$loc2 = comment.loc) === null || _comment$loc2 === void 0 || (_comment$loc2 = _comment$loc2.start) === null || _comment$loc2 === void 0 ? void 0 : _comment$loc2.line) ?? 1
}
};
context.report({
fix: enableFixer ? fixer : null,
loc,
messageId,
node
});
};
/**
* @param {import('eslint').Rule.Node} node
* @param {import('eslint').AST.Token | import('estree').Comment | {
* type: import('eslint').AST.TokenType|"Line"|"Block"|"Shebang",
* range: [number, number],
* value: string
* }} comment
* @param {AddComment} addComment
* @param {import('../iterateJsdoc.js').Context[]} ctxts
*/
const getFixer = (node, comment, addComment, ctxts) => {
return /** @type {import('eslint').Rule.ReportFixer} */fixer => {
// Default to one line break if the `minLines`/`maxLines` settings allow
const lines = settings.minLines === 0 && settings.maxLines >= 1 ? 1 : settings.minLines;
let baseNode =
/**
* @type {import('@typescript-eslint/types').TSESTree.Node|import('eslint').Rule.Node}
*/
(0, _jsdoccomment.getReducedASTNode)(node, sourceCode);
const decorator = (0, _jsdoccomment.getDecorator)( /** @type {import('eslint').Rule.Node} */
baseNode);
if (decorator) {
baseNode = /** @type {import('@typescript-eslint/types').TSESTree.Decorator} */
decorator;
}
const indent = (0, _jsdocUtils.getIndent)({
text: sourceCode.getText( /** @type {import('eslint').Rule.Node} */baseNode, /** @type {import('eslint').AST.SourceLocation} */
( /** @type {import('eslint').Rule.Node} */baseNode.loc).start.column)
});
const {
inlineCommentBlock
} =
/**
* @type {{
* context: string,
* inlineCommentBlock: boolean,
* minLineCount: import('../iterateJsdoc.js').Integer
* }[]}
*/
ctxts.find(contxt => {
if (typeof contxt === 'string') {
return false;
}
const {
context: ctxt
} = contxt;
return ctxt === node.type;
}) || {};
return addComment(inlineCommentBlock, comment, indent, lines, fixer);
};
};
/**
* @param {import('eslint').AST.Token | import('estree').Comment | {
* type: import('eslint').AST.TokenType|"Line"|"Block"|"Shebang",
* range: [number, number],
* value: string
* }} comment
* @param {import('eslint').Rule.Node} node
* @param {AddComment} addComment
* @param {import('../iterateJsdoc.js').Context[]} ctxts
*/
const reportings = (comment, node, addComment, ctxts) => {
const fixer = getFixer(node, comment, addComment, ctxts);
if (comment.type === 'Block') {
if (lineOrBlockStyle === 'line') {
return;
}
report('blockCommentsJsdocStyle', comment, node, fixer);
return;
}
if (comment.type === 'Line') {
if (lineOrBlockStyle === 'block') {
return;
}
report('lineCommentsJsdocStyle', comment, node, fixer);
}
};
/**
* @type {import('../iterateJsdoc.js').CheckJsdoc}
*/
const checkNonJsdoc = (_info, _handler, node) => {
const comment = (0, _jsdoccomment.getNonJsdocComment)(sourceCode, node, settings);
if (!comment || /** @type {string[]} */
allowedPrefixes.some(prefix => {
return comment.value.trimStart().startsWith(prefix);
})) {
return;
}
reportingNonJsdoc = true;
/** @type {AddComment} */
const addComment = (inlineCommentBlock, comment, indent, lines, fixer) => {
const insertion = (inlineCommentBlock || enforceJsdocLineStyle === 'single' ? `/** ${comment.value.trim()} ` : `/**\n${indent}*${comment.value.trimEnd()}\n${indent}`) + `*/${'\n'.repeat((lines || 1) - 1)}`;
return fixer.replaceText( /** @type {import('eslint').AST.Token} */
comment, insertion);
};
reportings(comment, node, addComment, contexts);
};
/**
* @param {import('eslint').Rule.Node} node
* @param {import('../iterateJsdoc.js').Context[]} ctxts
*/
const checkNonJsdocAfter = (node, ctxts) => {
const comment = (0, _jsdoccomment.getFollowingComment)(sourceCode, node);
if (!comment || comment.value.startsWith('*') || /** @type {string[]} */
allowedPrefixes.some(prefix => {
return comment.value.trimStart().startsWith(prefix);
})) {
return;
}
/** @type {AddComment} */
const addComment = (inlineCommentBlock, comment, indent, lines, fixer) => {
const insertion = (inlineCommentBlock || enforceJsdocLineStyle === 'single' ? `/** ${comment.value.trim()} ` : `/**\n${indent}*${comment.value.trimEnd()}\n${indent}`) + `*/${'\n'.repeat((lines || 1) - 1)}${lines ? `\n${indent.slice(1)}` : ' '}`;
return [fixer.remove( /** @type {import('eslint').AST.Token} */
comment), fixer.insertTextBefore(node.type === 'VariableDeclarator' ? node.parent : node, insertion)];
};
reportings(comment, node, addComment, ctxts);
};
// Todo: add contexts to check after (and handle if want both before and after)
return {
...(0, _jsdocUtils.getContextObject)((0, _jsdocUtils.enforcedContexts)(context, true, settings), checkNonJsdoc),
...(0, _jsdocUtils.getContextObject)(contextsAfter, (_info, _handler, node) => {
checkNonJsdocAfter(node, contextsAfter);
}),
...(0, _jsdocUtils.getContextObject)(contextsBeforeAndAfter, (_info, _handler, node) => {
checkNonJsdoc({}, null, node);
if (!reportingNonJsdoc) {
checkNonJsdocAfter(node, contextsBeforeAndAfter);
}
})
};
},
meta: {
fixable: 'code',
messages: {
blockCommentsJsdocStyle: 'Block comments should be JSDoc-style.',
lineCommentsJsdocStyle: 'Line comments should be JSDoc-style.'
},
docs: {
description: 'Converts non-JSDoc comments preceding or following nodes into JSDoc ones',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/convert-to-jsdoc-comments.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
allowedPrefixes: {
type: 'array',
items: {
type: 'string'
}
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
context: {
type: 'string'
},
inlineCommentBlock: {
type: 'boolean'
}
},
type: 'object'
}]
},
type: 'array'
},
contextsAfter: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
context: {
type: 'string'
},
inlineCommentBlock: {
type: 'boolean'
}
},
type: 'object'
}]
},
type: 'array'
},
contextsBeforeAndAfter: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
context: {
type: 'string'
},
inlineCommentBlock: {
type: 'boolean'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
type: 'boolean'
},
enforceJsdocLineStyle: {
type: 'string',
enum: ['multi', 'single']
},
lineOrBlockStyle: {
type: 'string',
enum: ['block', 'line', 'both']
}
},
type: 'object'
}],
type: 'suggestion'
}
};
module.exports = exports.default;
//# sourceMappingURL=convertToJsdocComments.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const defaultEmptyTags = new Set(['abstract', 'async', 'generator', 'global', 'hideconstructor', 'ignore', 'inner', 'instance', 'override', 'readonly',
// jsdoc doesn't use this form in its docs, but allow for compatibility with
// TypeScript which allows and Closure which requires
'inheritDoc',
// jsdoc doesn't use but allow for TypeScript
'internal', 'overload']);
const emptyIfNotClosure = new Set(['package', 'private', 'protected', 'public', 'static',
// Closure doesn't allow with this casing
'inheritdoc']);
const emptyIfClosure = new Set(['interface']);
var _default = exports.default = (0, _iterateJsdoc.default)(({
settings,
jsdoc,
utils
}) => {
const emptyTags = utils.filterTags(({
tag: tagName
}) => {
return defaultEmptyTags.has(tagName) || utils.hasOptionTag(tagName) && jsdoc.tags.some(({
tag
}) => {
return tag === tagName;
}) || settings.mode === 'closure' && emptyIfClosure.has(tagName) || settings.mode !== 'closure' && emptyIfNotClosure.has(tagName);
});
for (const tag of emptyTags) {
const content = tag.name || tag.description || tag.type;
if (content.trim()) {
const fix = () => {
// By time of call in fixer, `tag` will have `line` added
utils.setTag(
/**
* @type {import('comment-parser').Spec & {
* line: import('../iterateJsdoc.js').Integer
* }}
*/
tag);
};
utils.reportJSDoc(`@${tag.tag} should be empty.`, tag, fix, true);
}
}
}, {
checkInternal: true,
checkPrivate: true,
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Expects specific tags to be empty of any content.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/empty-tags.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
tags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=emptyTags.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"emptyTags.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","defaultEmptyTags","Set","emptyIfNotClosure","emptyIfClosure","_default","exports","iterateJsdoc","settings","jsdoc","utils","emptyTags","filterTags","tag","tagName","has","hasOptionTag","tags","some","mode","content","name","description","type","trim","fix","setTag","reportJSDoc","checkInternal","checkPrivate","iterateAllJsdocs","meta","docs","url","fixable","schema","additionalProperties","properties","items","module"],"sources":["../../src/rules/emptyTags.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nconst defaultEmptyTags = new Set([\n 'abstract', 'async', 'generator', 'global', 'hideconstructor',\n 'ignore', 'inner', 'instance', 'override', 'readonly',\n\n // jsdoc doesn't use this form in its docs, but allow for compatibility with\n // TypeScript which allows and Closure which requires\n 'inheritDoc',\n\n // jsdoc doesn't use but allow for TypeScript\n 'internal',\n 'overload',\n]);\n\nconst emptyIfNotClosure = new Set([\n 'package', 'private', 'protected', 'public', 'static',\n\n // Closure doesn't allow with this casing\n 'inheritdoc',\n]);\n\nconst emptyIfClosure = new Set([\n 'interface',\n]);\n\nexport default iterateJsdoc(({\n settings,\n jsdoc,\n utils,\n}) => {\n const emptyTags = utils.filterTags(({\n tag: tagName,\n }) => {\n return defaultEmptyTags.has(tagName) ||\n utils.hasOptionTag(tagName) && jsdoc.tags.some(({\n tag,\n }) => {\n return tag === tagName;\n }) ||\n settings.mode === 'closure' && emptyIfClosure.has(tagName) ||\n settings.mode !== 'closure' && emptyIfNotClosure.has(tagName);\n });\n\n for (const tag of emptyTags) {\n const content = tag.name || tag.description || tag.type;\n if (content.trim()) {\n const fix = () => {\n // By time of call in fixer, `tag` will have `line` added\n utils.setTag(\n /**\n * @type {import('comment-parser').Spec & {\n * line: import('../iterateJsdoc.js').Integer\n * }}\n */ (tag),\n );\n };\n\n utils.reportJSDoc(`@${tag.tag} should be empty.`, tag, fix, true);\n }\n }\n}, {\n checkInternal: true,\n checkPrivate: true,\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Expects specific tags to be empty of any content.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/empty-tags.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n tags: {\n items: {\n type: 'string',\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C,MAAMG,gBAAgB,GAAG,IAAIC,GAAG,CAAC,CAC/B,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAC7D,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU;AAErD;AACA;AACA,YAAY;AAEZ;AACA,UAAU,EACV,UAAU,CACX,CAAC;AAEF,MAAMC,iBAAiB,GAAG,IAAID,GAAG,CAAC,CAChC,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ;AAErD;AACA,YAAY,CACb,CAAC;AAEF,MAAME,cAAc,GAAG,IAAIF,GAAG,CAAC,CAC7B,WAAW,CACZ,CAAC;AAAC,IAAAG,QAAA,GAAAC,OAAA,CAAAN,OAAA,GAEY,IAAAO,qBAAY,EAAC,CAAC;EAC3BC,QAAQ;EACRC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAMC,SAAS,GAAGD,KAAK,CAACE,UAAU,CAAC,CAAC;IAClCC,GAAG,EAAEC;EACP,CAAC,KAAK;IACJ,OAAOb,gBAAgB,CAACc,GAAG,CAACD,OAAO,CAAC,IAClCJ,KAAK,CAACM,YAAY,CAACF,OAAO,CAAC,IAAIL,KAAK,CAACQ,IAAI,CAACC,IAAI,CAAC,CAAC;MAC9CL;IACF,CAAC,KAAK;MACJ,OAAOA,GAAG,KAAKC,OAAO;IACxB,CAAC,CAAC,IACFN,QAAQ,CAACW,IAAI,KAAK,SAAS,IAAIf,cAAc,CAACW,GAAG,CAACD,OAAO,CAAC,IAC1DN,QAAQ,CAACW,IAAI,KAAK,SAAS,IAAIhB,iBAAiB,CAACY,GAAG,CAACD,OAAO,CAAC;EACjE,CAAC,CAAC;EAEF,KAAK,MAAMD,GAAG,IAAIF,SAAS,EAAE;IAC3B,MAAMS,OAAO,GAAGP,GAAG,CAACQ,IAAI,IAAIR,GAAG,CAACS,WAAW,IAAIT,GAAG,CAACU,IAAI;IACvD,IAAIH,OAAO,CAACI,IAAI,CAAC,CAAC,EAAE;MAClB,MAAMC,GAAG,GAAGA,CAAA,KAAM;QAChB;QACAf,KAAK,CAACgB,MAAM;QACV;AACV;AACA;AACA;AACA;QAAeb,GACP,CAAC;MACH,CAAC;MAEDH,KAAK,CAACiB,WAAW,CAAC,IAAId,GAAG,CAACA,GAAG,mBAAmB,EAAEA,GAAG,EAAEY,GAAG,EAAE,IAAI,CAAC;IACnE;EACF;AACF,CAAC,EAAE;EACDG,aAAa,EAAE,IAAI;EACnBC,YAAY,EAAE,IAAI;EAClBC,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJV,WAAW,EAAE,mDAAmD;MAChEW,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVpB,IAAI,EAAE;UACJqB,KAAK,EAAE;YACLf,IAAI,EAAE;UACR,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAgB,MAAA,CAAAjC,OAAA,GAAAA,OAAA,CAAAN,OAAA","ignoreList":[]}

View File

@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
const iteratingFunction = utils.isIteratingFunction();
if (iteratingFunction) {
if (utils.hasATag(['class', 'constructor']) || utils.isConstructor()) {
return;
}
} else if (!utils.isVirtualFunction()) {
return;
}
utils.forEachPreferredTag('implements', tag => {
report('@implements used on a non-constructor function', null, tag);
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Reports an issue with any non-constructor function using `@implements`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/implements-on-classes.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=implementsOnClasses.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"implementsOnClasses.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","report","utils","iteratingFunction","isIteratingFunction","hasATag","isConstructor","isVirtualFunction","forEachPreferredTag","tag","contextDefaults","meta","docs","description","url","schema","additionalProperties","properties","contexts","items","anyOf","type","comment","context","module"],"sources":["../../src/rules/implementsOnClasses.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n const iteratingFunction = utils.isIteratingFunction();\n\n if (iteratingFunction) {\n if (utils.hasATag([\n 'class',\n 'constructor',\n ]) ||\n utils.isConstructor()\n ) {\n return;\n }\n } else if (!utils.isVirtualFunction()) {\n return;\n }\n\n utils.forEachPreferredTag('implements', (tag) => {\n report('@implements used on a non-constructor function', null, tag);\n });\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'Reports an issue with any non-constructor function using `@implements`.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/implements-on-classes.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ,MAAMC,iBAAiB,GAAGD,KAAK,CAACE,mBAAmB,CAAC,CAAC;EAErD,IAAID,iBAAiB,EAAE;IACrB,IAAID,KAAK,CAACG,OAAO,CAAC,CAChB,OAAO,EACP,aAAa,CACd,CAAC,IACAH,KAAK,CAACI,aAAa,CAAC,CAAC,EACrB;MACA;IACF;EACF,CAAC,MAAM,IAAI,CAACJ,KAAK,CAACK,iBAAiB,CAAC,CAAC,EAAE;IACrC;EACF;EAEAL,KAAK,CAACM,mBAAmB,CAAC,YAAY,EAAGC,GAAG,IAAK;IAC/CR,MAAM,CAAC,gDAAgD,EAAE,IAAI,EAAEQ,GAAG,CAAC;EACrE,CAAC,CAAC;AACJ,CAAC,EAAE;EACDC,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,yEAAyE;MACtFC,GAAG,EAAE;IACP,CAAC;IACDC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEC,IAAI,EAAE;YACR,CAAC,EACD;cACEL,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVK,OAAO,EAAE;kBACPD,IAAI,EAAE;gBACR,CAAC;gBACDE,OAAO,EAAE;kBACPF,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAG,MAAA,CAAAzB,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,106 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _fs = require("fs");
var _nodeModule = require("node:module");
var _path = require("path");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @type {Set<string>|null}
*/
let deps;
const setDeps = function () {
try {
const pkg = JSON.parse(
// @ts-expect-error It's ok
(0, _fs.readFileSync)((0, _path.join)(process.cwd(), './package.json')));
deps = new Set([...(pkg.dependencies ? /* c8 ignore next 2 */
Object.keys(pkg.dependencies) : []), ...(pkg.devDependencies ? /* c8 ignore next 2 */
Object.keys(pkg.devDependencies) : [])]);
/* c8 ignore next -- our package.json exists */
} catch (error) {
/* c8 ignore next -- our package.json exists */
deps = null;
/* c8 ignore next 4 -- our package.json exists */
/* eslint-disable no-console -- Inform user */
console.log(error);
/* eslint-enable no-console -- Inform user */
}
};
const moduleCheck = new Map();
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
settings,
utils
}) => {
if (deps === undefined) {
setDeps();
}
/* c8 ignore next 3 -- our package.json exists */
if (deps === null) {
return;
}
const {
mode
} = settings;
for (const tag of jsdoc.tags) {
let typeAst;
try {
typeAst = mode === 'permissive' ? (0, _jsdoccomment.tryParse)(tag.type) : (0, _jsdoccomment.parse)(tag.type, mode);
} catch {
continue;
}
// eslint-disable-next-line no-loop-func -- Safe
(0, _jsdoccomment.traverse)(typeAst, nde => {
/* c8 ignore next 3 -- TS guard */
if (deps === null) {
return;
}
if (nde.type === 'JsdocTypeImport') {
let mod = nde.element.value.replace(/^(@[^/]+\/[^/]+|[^/]+).*$/u, '$1');
if (/^[./]/u.test(mod)) {
return;
}
if ((0, _nodeModule.isBuiltin)(mod)) {
// mod = '@types/node';
// moduleCheck.set(mod, !deps.has(mod));
return;
} else if (!moduleCheck.has(mod)) {
let pkg;
try {
pkg = JSON.parse(
// @ts-expect-error It's ok
(0, _fs.readFileSync)((0, _path.join)(process.cwd(), 'node_modules', mod, './package.json')));
} catch {
// Ignore
}
if (!pkg || !pkg.types && !pkg.typings) {
mod = `@types/${mod}`;
}
moduleCheck.set(mod, !deps.has(mod));
}
if (moduleCheck.get(mod)) {
utils.reportJSDoc('import points to package which is not found in dependencies', tag);
}
}
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports if JSDoc `import()` statements point to a package which is not listed in `dependencies` or `devDependencies`',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/imports-as-dependencies.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=importsAsDependencies.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,148 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _areDocsInformative = require("are-docs-informative");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const defaultAliases = {
a: ['an', 'our']
};
const defaultUselessWords = ['a', 'an', 'i', 'in', 'of', 's', 'the'];
/* eslint-disable complexity -- Temporary */
/**
* @param {import('eslint').Rule.Node|import('@typescript-eslint/types').TSESTree.Node|null|undefined} node
* @returns {string[]}
*/
const getNamesFromNode = node => {
switch (node === null || node === void 0 ? void 0 : node.type) {
case 'AccessorProperty':
case 'MethodDefinition':
case 'PropertyDefinition':
case 'TSAbstractAccessorProperty':
case 'TSAbstractMethodDefinition':
case 'TSAbstractPropertyDefinition':
return [...getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */node.parent.parent), ...getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.key)];
case 'ExportDefaultDeclaration':
case 'ExportNamedDeclaration':
return getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.ExportNamedDeclaration} */
node.declaration);
case 'ClassDeclaration':
case 'ClassExpression':
case 'FunctionDeclaration':
case 'FunctionExpression':
case 'TSModuleDeclaration':
case 'TSMethodSignature':
case 'TSDeclareFunction':
case 'TSEnumDeclaration':
case 'TSEnumMember':
case 'TSInterfaceDeclaration':
case 'TSTypeAliasDeclaration':
return getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.ClassDeclaration} */
node.id);
case 'Identifier':
return [node.name];
case 'Property':
return getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.key);
case 'VariableDeclaration':
return getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.declarations[0]);
case 'VariableDeclarator':
return [...getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.id), ...getNamesFromNode( /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node.init)].filter(Boolean);
default:
return [];
}
};
/* eslint-enable complexity -- Temporary */
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
node,
report,
utils
}) => {
const /** @type {{aliases: {[key: string]: string[]}, excludedTags: string[], uselessWords: string[]}} */{
aliases = defaultAliases,
excludedTags = [],
uselessWords = defaultUselessWords
} = context.options[0] || {};
const nodeNames = getNamesFromNode(node);
/**
* @param {string} text
* @param {string} extraName
* @returns {boolean}
*/
const descriptionIsRedundant = (text, extraName = '') => {
const textTrimmed = text.trim();
return Boolean(textTrimmed) && !(0, _areDocsInformative.areDocsInformative)(textTrimmed, [extraName, nodeNames].filter(Boolean).join(' '), {
aliases,
uselessWords
});
};
const {
description,
lastDescriptionLine
} = utils.getDescription();
let descriptionReported = false;
for (const tag of jsdoc.tags) {
if (excludedTags.includes(tag.tag)) {
continue;
}
if (descriptionIsRedundant(tag.description, tag.name)) {
utils.reportJSDoc('This tag description only repeats the name it describes.', tag);
}
descriptionReported ||= tag.description === description && /** @type {import('comment-parser').Spec & {line: import('../iterateJsdoc.js').Integer}} */
tag.line === lastDescriptionLine;
}
if (!descriptionReported && descriptionIsRedundant(description)) {
report('This description only repeats the name it describes.');
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'This rule reports doc comments that only restate their attached name.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/informative-docs.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
aliases: {
patternProperties: {
'.*': {
items: {
type: 'string'
},
type: 'array'
}
}
},
excludedTags: {
items: {
type: 'string'
},
type: 'array'
},
uselessWords: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=informativeDocs.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,229 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// If supporting Node >= 10, we could loosen the default to this for the
// initial letter: \\p{Upper}
const matchDescriptionDefault = '^\n?([A-Z`\\d_][\\s\\S]*[.?!`]\\s*)?$';
/**
* @param {string} value
* @param {string} userDefault
* @returns {string}
*/
const stringOrDefault = (value, userDefault) => {
return typeof value === 'string' ? value : userDefault || matchDescriptionDefault;
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
report,
context,
utils
}) => {
const {
mainDescription,
matchDescription,
message,
nonemptyTags = true,
tags = {}
} = context.options[0] || {};
/**
* @param {string} desc
* @param {import('comment-parser').Spec} [tag]
* @returns {void}
*/
const validateDescription = (desc, tag) => {
let mainDescriptionMatch = mainDescription;
let errorMessage = message;
if (typeof mainDescription === 'object') {
mainDescriptionMatch = mainDescription.match;
errorMessage = mainDescription.message;
}
if (mainDescriptionMatch === false && (!tag || !Object.prototype.hasOwnProperty.call(tags, tag.tag))) {
return;
}
let tagValue = mainDescriptionMatch;
if (tag) {
const tagName = tag.tag;
if (typeof tags[tagName] === 'object') {
tagValue = tags[tagName].match;
errorMessage = tags[tagName].message;
} else {
tagValue = tags[tagName];
}
}
const regex = utils.getRegexFromString(stringOrDefault(tagValue, matchDescription));
if (!regex.test(desc)) {
report(errorMessage || 'JSDoc description does not satisfy the regex pattern.', null, tag || {
// Add one as description would typically be into block
line: jsdoc.source[0].number + 1
});
}
};
const {
description
} = utils.getDescription();
if (description) {
validateDescription(description);
}
/**
* @param {string} tagName
* @returns {boolean}
*/
const hasNoTag = tagName => {
return !tags[tagName];
};
for (const tag of ['description', 'summary', 'file', 'classdesc']) {
utils.forEachPreferredTag(tag, (matchingJsdocTag, targetTagName) => {
const desc = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();
if (hasNoTag(targetTagName)) {
validateDescription(desc, matchingJsdocTag);
}
}, true);
}
if (nonemptyTags) {
for (const tag of ['copyright', 'example', 'see', 'todo']) {
utils.forEachPreferredTag(tag, (matchingJsdocTag, targetTagName) => {
const desc = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();
if (hasNoTag(targetTagName) && !/.+/u.test(desc)) {
report('JSDoc description must not be empty.', null, matchingJsdocTag);
}
});
}
}
if (!Object.keys(tags).length) {
return;
}
/**
* @param {string} tagName
* @returns {boolean}
*/
const hasOptionTag = tagName => {
return Boolean(tags[tagName]);
};
const whitelistedTags = utils.filterTags(({
tag: tagName
}) => {
return hasOptionTag(tagName);
});
const {
tagsWithNames,
tagsWithoutNames
} = utils.getTagsByType(whitelistedTags);
tagsWithNames.some(tag => {
const desc = /** @type {string} */utils.getTagDescription(tag).replace(/^[- ]*/u, '').trim();
return validateDescription(desc, tag);
});
tagsWithoutNames.some(tag => {
const desc = (tag.name + ' ' + utils.getTagDescription(tag)).trim();
return validateDescription(desc, tag);
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Enforces a regular expression pattern on descriptions.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/match-description.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
mainDescription: {
oneOf: [{
format: 'regex',
type: 'string'
}, {
type: 'boolean'
}, {
additionalProperties: false,
properties: {
match: {
oneOf: [{
format: 'regex',
type: 'string'
}, {
type: 'boolean'
}]
},
message: {
type: 'string'
}
},
type: 'object'
}]
},
matchDescription: {
format: 'regex',
type: 'string'
},
message: {
type: 'string'
},
nonemptyTags: {
type: 'boolean'
},
tags: {
patternProperties: {
'.*': {
oneOf: [{
format: 'regex',
type: 'string'
}, {
enum: [true],
type: 'boolean'
}, {
additionalProperties: false,
properties: {
match: {
oneOf: [{
format: 'regex',
type: 'string'
}, {
enum: [true],
type: 'boolean'
}]
},
message: {
type: 'string'
}
},
type: 'object'
}]
}
},
type: 'object'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=matchDescription.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,128 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// eslint-disable-next-line complexity
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
info: {
lastIndex
},
utils
}) => {
const {
match
} = context.options[0] || {};
if (!match) {
report('Rule `no-restricted-syntax` is missing a `match` option.');
return;
}
const {
allowName,
disallowName,
replacement,
tags = ['*']
} = match[( /** @type {import('../iterateJsdoc.js').Integer} */lastIndex)];
const allowNameRegex = allowName && utils.getRegexFromString(allowName);
const disallowNameRegex = disallowName && utils.getRegexFromString(disallowName);
let applicableTags = jsdoc.tags;
if (!tags.includes('*')) {
applicableTags = utils.getPresentTags(tags);
}
let reported = false;
for (const tag of applicableTags) {
const allowed = !allowNameRegex || allowNameRegex.test(tag.name);
const disallowed = disallowNameRegex && disallowNameRegex.test(tag.name);
const hasRegex = allowNameRegex || disallowNameRegex;
if (hasRegex && allowed && !disallowed) {
continue;
}
if (!hasRegex && reported) {
continue;
}
const fixer = () => {
for (const src of tag.source) {
if (src.tokens.name) {
src.tokens.name = src.tokens.name.replace(disallowNameRegex, replacement);
break;
}
}
};
let {
message
} = match[( /** @type {import('../iterateJsdoc.js').Integer} */lastIndex)];
if (!message) {
if (hasRegex) {
message = disallowed ? `Only allowing names not matching \`${disallowNameRegex}\` but found "${tag.name}".` : `Only allowing names matching \`${allowNameRegex}\` but found "${tag.name}".`;
} else {
message = `Prohibited context for "${tag.name}".`;
}
}
utils.reportJSDoc(message, hasRegex ? tag : null,
// We could match up
disallowNameRegex && replacement !== undefined ? fixer : null, false, {
// Could also supply `context`, `comment`, `tags`
allowName,
disallowName,
name: tag.name
});
if (!hasRegex) {
reported = true;
}
}
}, {
matchContext: true,
meta: {
docs: {
description: 'Reports the name portion of a JSDoc tag if matching or not matching a given regular expression.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/match-name.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
match: {
additionalProperties: false,
items: {
properties: {
allowName: {
type: 'string'
},
comment: {
type: 'string'
},
context: {
type: 'string'
},
disallowName: {
type: 'string'
},
message: {
type: 'string'
},
tags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
},
type: 'array'
}
},
required: ['match'],
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=matchName.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,237 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils
}) => {
const {
allowMultipleTags = true,
noFinalLineText = true,
noZeroLineText = true,
noSingleLineBlocks = false,
singleLineTags = ['lends', 'type'],
noMultilineBlocks = false,
minimumLengthForMultiline = Number.POSITIVE_INFINITY,
multilineTags = ['*']
} = context.options[0] || {};
const {
source: [{
tokens
}]
} = jsdoc;
const {
description,
tag
} = tokens;
const sourceLength = jsdoc.source.length;
/**
* @param {string} tagName
* @returns {boolean}
*/
const isInvalidSingleLine = tagName => {
return noSingleLineBlocks && (!tagName || !singleLineTags.includes(tagName) && !singleLineTags.includes('*'));
};
if (sourceLength === 1) {
if (!isInvalidSingleLine(tag.slice(1))) {
return;
}
const fixer = () => {
utils.makeMultiline();
};
utils.reportJSDoc('Single line blocks are not permitted by your configuration.', null, fixer, true);
return;
}
const lineChecks = () => {
if (noZeroLineText && (tag || description)) {
const fixer = () => {
const line = {
...tokens
};
utils.emptyTokens(tokens);
const {
tokens: {
delimiter,
start
}
} = jsdoc.source[1];
utils.addLine(1, {
...line,
delimiter,
start
});
};
utils.reportJSDoc('Should have no text on the "0th" line (after the `/**`).', null, fixer);
return;
}
const finalLine = jsdoc.source[jsdoc.source.length - 1];
const finalLineTokens = finalLine.tokens;
if (noFinalLineText && finalLineTokens.description.trim()) {
const fixer = () => {
const line = {
...finalLineTokens
};
line.description = line.description.trimEnd();
const {
delimiter
} = line;
for (const prop of ['delimiter', 'postDelimiter', 'tag', 'type', 'lineEnd', 'postType', 'postTag', 'name', 'postName', 'description']) {
finalLineTokens[(
/**
* @type {"delimiter"|"postDelimiter"|"tag"|"type"|
* "lineEnd"|"postType"|"postTag"|"name"|
* "postName"|"description"}
*/
prop)] = '';
}
utils.addLine(jsdoc.source.length - 1, {
...line,
delimiter,
end: ''
});
};
utils.reportJSDoc('Should have no text on the final line (before the `*/`).', null, fixer);
}
};
if (noMultilineBlocks) {
if (jsdoc.tags.length && (multilineTags.includes('*') || utils.hasATag(multilineTags))) {
lineChecks();
return;
}
if (jsdoc.description.length >= minimumLengthForMultiline) {
lineChecks();
return;
}
if (noSingleLineBlocks && (!jsdoc.tags.length || !utils.filterTags(({
tag: tg
}) => {
return !isInvalidSingleLine(tg);
}).length)) {
utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but fixing would result in a single ' + 'line block which you have prohibited with `noSingleLineBlocks`.');
return;
}
if (jsdoc.tags.length > 1) {
if (!allowMultipleTags) {
utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but the block has multiple tags.');
return;
}
} else if (jsdoc.tags.length === 1 && jsdoc.description.trim()) {
if (!allowMultipleTags) {
utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but the block has a description with a tag.');
return;
}
} else {
const fixer = () => {
jsdoc.source = [{
number: 1,
source: '',
tokens: jsdoc.source.reduce((obj, {
tokens: {
description: desc,
tag: tg,
type: typ,
name: nme,
lineEnd,
postType,
postName,
postTag
}
}) => {
if (typ) {
obj.type = typ;
}
if (tg && typ && nme) {
obj.postType = postType;
}
if (nme) {
obj.name += nme;
}
if (nme && desc) {
obj.postName = postName;
}
obj.description += desc;
const nameOrDescription = obj.description || obj.name;
if (nameOrDescription && nameOrDescription.slice(-1) !== ' ') {
obj.description += ' ';
}
obj.lineEnd = lineEnd;
// Already filtered for multiple tags
obj.tag += tg;
if (tg) {
obj.postTag = postTag || ' ';
}
return obj;
}, utils.seedTokens({
delimiter: '/**',
end: '*/',
postDelimiter: ' '
}))
}];
};
utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration.', null, fixer);
return;
}
}
lineChecks();
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Controls how and whether jsdoc blocks can be expressed as single or multiple line blocks.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/multiline-blocks.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
allowMultipleTags: {
type: 'boolean'
},
minimumLengthForMultiline: {
type: 'integer'
},
multilineTags: {
anyOf: [{
enum: ['*'],
type: 'string'
}, {
items: {
type: 'string'
},
type: 'array'
}]
},
noFinalLineText: {
type: 'boolean'
},
noMultilineBlocks: {
type: 'boolean'
},
noSingleLineBlocks: {
type: 'boolean'
},
noZeroLineText: {
type: 'boolean'
},
singleLineTags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=multilineBlocks.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,87 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _commentParser = require("comment-parser");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// Neither a single nor 3+ asterisks are valid jsdoc per
// https://jsdoc.app/about-getting-started.html#adding-documentation-comments-to-your-code
const commentRegexp = /^\/\*(?!\*)/u;
const extraAsteriskCommentRegexp = /^\/\*{3,}/u;
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
sourceCode,
allComments,
makeReport
}) => {
const [{
ignore = ['ts-check', 'ts-expect-error', 'ts-ignore', 'ts-nocheck'],
preventAllMultiAsteriskBlocks = false
} = {}] = context.options;
let extraAsterisks = false;
const nonJsdocNodes = /** @type {import('estree').Node[]} */allComments.filter(comment => {
const commentText = sourceCode.getText(comment);
let sliceIndex = 2;
if (!commentRegexp.test(commentText)) {
var _extraAsteriskComment;
const multiline = (_extraAsteriskComment = extraAsteriskCommentRegexp.exec(commentText)) === null || _extraAsteriskComment === void 0 ? void 0 : _extraAsteriskComment[0];
if (!multiline) {
return false;
}
sliceIndex = multiline.length;
extraAsterisks = true;
if (preventAllMultiAsteriskBlocks) {
return true;
}
}
const tags = ((0, _commentParser.parse)(`${commentText.slice(0, 2)}*${commentText.slice(sliceIndex)}`)[0] || {}).tags ?? [];
return tags.length && !tags.some(({
tag
}) => {
return ignore.includes(tag);
});
});
if (!nonJsdocNodes.length) {
return;
}
for (const node of nonJsdocNodes) {
const report = /** @type {import('../iterateJsdoc.js').MakeReport} */makeReport(context, node);
// eslint-disable-next-line no-loop-func
const fix = /** @type {import('eslint').Rule.ReportFixer} */fixer => {
const text = sourceCode.getText(node);
return fixer.replaceText(node, extraAsterisks ? text.replace(extraAsteriskCommentRegexp, '/**') : text.replace('/*', '/**'));
};
report('Expected JSDoc-like comment to begin with two asterisks.', fix);
}
}, {
checkFile: true,
meta: {
docs: {
description: 'This rule checks for multi-line-style comments which fail to meet the criteria of a jsdoc block.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-bad-blocks.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
ignore: {
items: {
type: 'string'
},
type: 'array'
},
preventAllMultiAsteriskBlocks: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=noBadBlocks.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const anyWhitespaceLines = /^\s*$/u;
const atLeastTwoLinesWhitespace = /^[ \t]*\n[ \t]*\n\s*$/u;
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
utils
}) => {
const {
description,
descriptions,
lastDescriptionLine
} = utils.getDescription();
const regex = jsdoc.tags.length ? anyWhitespaceLines : atLeastTwoLinesWhitespace;
if (descriptions.length && regex.test(description)) {
if (jsdoc.tags.length) {
utils.reportJSDoc('There should be no blank lines in block descriptions followed by tags.', {
line: lastDescriptionLine
}, () => {
utils.setBlockDescription(() => {
// Remove all lines
return [];
});
});
} else {
utils.reportJSDoc('There should be no extra blank lines in block descriptions not followed by tags.', {
line: lastDescriptionLine
}, () => {
utils.setBlockDescription((info, seedTokens) => {
return [
// Keep the starting line
{
number: 0,
source: '',
tokens: seedTokens({
...info,
description: ''
})
}];
});
});
}
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Detects and removes extra lines of a blank block description',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-block-descriptions.md#repos-sticky-header'
},
fixable: 'whitespace',
schema: [],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=noBlankBlockDescriptions.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noBlankBlockDescriptions.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","anyWhitespaceLines","atLeastTwoLinesWhitespace","_default","exports","iterateJsdoc","jsdoc","utils","description","descriptions","lastDescriptionLine","getDescription","regex","tags","length","test","reportJSDoc","line","setBlockDescription","info","seedTokens","number","source","tokens","iterateAllJsdocs","meta","docs","url","fixable","schema","type","module"],"sources":["../../src/rules/noBlankBlockDescriptions.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nconst anyWhitespaceLines = /^\\s*$/u;\nconst atLeastTwoLinesWhitespace = /^[ \\t]*\\n[ \\t]*\\n\\s*$/u;\n\nexport default iterateJsdoc(({\n jsdoc,\n utils,\n}) => {\n const {\n description,\n descriptions,\n lastDescriptionLine,\n } = utils.getDescription();\n\n const regex = jsdoc.tags.length ?\n anyWhitespaceLines :\n atLeastTwoLinesWhitespace;\n\n if (descriptions.length && regex.test(description)) {\n if (jsdoc.tags.length) {\n utils.reportJSDoc(\n 'There should be no blank lines in block descriptions followed by tags.',\n {\n line: lastDescriptionLine,\n },\n () => {\n utils.setBlockDescription(() => {\n // Remove all lines\n return [];\n });\n },\n );\n } else {\n utils.reportJSDoc(\n 'There should be no extra blank lines in block descriptions not followed by tags.',\n {\n line: lastDescriptionLine,\n },\n () => {\n utils.setBlockDescription((info, seedTokens) => {\n return [\n // Keep the starting line\n {\n number: 0,\n source: '',\n tokens: seedTokens({\n ...info,\n description: '',\n }),\n },\n ];\n });\n },\n );\n }\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Detects and removes extra lines of a blank block description',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-block-descriptions.md#repos-sticky-header',\n },\n fixable: 'whitespace',\n schema: [],\n type: 'layout',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C,MAAMG,kBAAkB,GAAG,QAAQ;AACnC,MAAMC,yBAAyB,GAAG,wBAAwB;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAJ,OAAA,GAE5C,IAAAK,qBAAY,EAAC,CAAC;EAC3BC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,MAAM;IACJC,WAAW;IACXC,YAAY;IACZC;EACF,CAAC,GAAGH,KAAK,CAACI,cAAc,CAAC,CAAC;EAE1B,MAAMC,KAAK,GAAGN,KAAK,CAACO,IAAI,CAACC,MAAM,GAC7Bb,kBAAkB,GAClBC,yBAAyB;EAE3B,IAAIO,YAAY,CAACK,MAAM,IAAIF,KAAK,CAACG,IAAI,CAACP,WAAW,CAAC,EAAE;IAClD,IAAIF,KAAK,CAACO,IAAI,CAACC,MAAM,EAAE;MACrBP,KAAK,CAACS,WAAW,CACf,wEAAwE,EACxE;QACEC,IAAI,EAAEP;MACR,CAAC,EACD,MAAM;QACJH,KAAK,CAACW,mBAAmB,CAAC,MAAM;UAC9B;UACA,OAAO,EAAE;QACX,CAAC,CAAC;MACJ,CACF,CAAC;IACH,CAAC,MAAM;MACLX,KAAK,CAACS,WAAW,CACf,kFAAkF,EAClF;QACEC,IAAI,EAAEP;MACR,CAAC,EACD,MAAM;QACJH,KAAK,CAACW,mBAAmB,CAAC,CAACC,IAAI,EAAEC,UAAU,KAAK;UAC9C,OAAO;UACL;UACA;YACEC,MAAM,EAAE,CAAC;YACTC,MAAM,EAAE,EAAE;YACVC,MAAM,EAAEH,UAAU,CAAC;cACjB,GAAGD,IAAI;cACPX,WAAW,EAAE;YACf,CAAC;UACH,CAAC,CACF;QACH,CAAC,CAAC;MACJ,CACF,CAAC;IACH;EACF;AACF,CAAC,EAAE;EACDgB,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJlB,WAAW,EAAE,8DAA8D;MAC3EmB,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,YAAY;IACrBC,MAAM,EAAE,EAAE;IACVC,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAA3B,OAAA,GAAAA,OAAA,CAAAJ,OAAA","ignoreList":[]}

View File

@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils
}) => {
if (jsdoc.tags.length) {
return;
}
const {
description,
lastDescriptionLine
} = utils.getDescription();
if (description.trim()) {
return;
}
const {
enableFixer
} = context.options[0] || {};
utils.reportJSDoc('No empty blocks', {
line: lastDescriptionLine
}, enableFixer ? () => {
jsdoc.source.splice(0, jsdoc.source.length);
} : null);
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Removes empty blocks with nothing but possibly line breaks',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-blocks.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
enableFixer: {
type: 'boolean'
}
}
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noBlankBlocks.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noBlankBlocks.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","jsdoc","utils","tags","length","description","lastDescriptionLine","getDescription","trim","enableFixer","options","reportJSDoc","line","source","splice","iterateAllJsdocs","meta","docs","url","fixable","schema","additionalProperties","properties","type","module"],"sources":["../../src/rules/noBlankBlocks.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n jsdoc,\n utils,\n}) => {\n if (jsdoc.tags.length) {\n return;\n }\n\n const {\n description,\n lastDescriptionLine,\n } = utils.getDescription();\n if (description.trim()) {\n return;\n }\n\n const {\n enableFixer,\n } = context.options[0] || {};\n\n utils.reportJSDoc(\n 'No empty blocks',\n {\n line: lastDescriptionLine,\n },\n enableFixer ? () => {\n jsdoc.source.splice(0, jsdoc.source.length);\n } : null,\n );\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Removes empty blocks with nothing but possibly line breaks',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-blocks.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n enableFixer: {\n type: 'boolean',\n },\n },\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC,KAAK;EACLC;AACF,CAAC,KAAK;EACJ,IAAID,KAAK,CAACE,IAAI,CAACC,MAAM,EAAE;IACrB;EACF;EAEA,MAAM;IACJC,WAAW;IACXC;EACF,CAAC,GAAGJ,KAAK,CAACK,cAAc,CAAC,CAAC;EAC1B,IAAIF,WAAW,CAACG,IAAI,CAAC,CAAC,EAAE;IACtB;EACF;EAEA,MAAM;IACJC;EACF,CAAC,GAAGT,OAAO,CAACU,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;EAE5BR,KAAK,CAACS,WAAW,CACf,iBAAiB,EACjB;IACEC,IAAI,EAAEN;EACR,CAAC,EACDG,WAAW,GAAG,MAAM;IAClBR,KAAK,CAACY,MAAM,CAACC,MAAM,CAAC,CAAC,EAAEb,KAAK,CAACY,MAAM,CAACT,MAAM,CAAC;EAC7C,CAAC,GAAG,IACN,CAAC;AACH,CAAC,EAAE;EACDW,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJZ,WAAW,EAAE,4DAA4D;MACzEa,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVb,WAAW,EAAE;UACXc,IAAI,EAAE;QACR;MACF;IACF,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAA1B,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
utils
}) => {
const {
noOptionalParamNames
} = context.options[0] || {};
const paramTags = utils.getPresentTags(['param', 'arg', 'argument']);
for (const tag of paramTags) {
if (noOptionalParamNames && tag.optional) {
utils.reportJSDoc(`Optional param names are not permitted on @${tag.tag}.`, tag, () => {
utils.changeTag(tag, {
name: tag.name.replace(/([^=]*)(=.+)?/u, '$1')
});
});
} else if (tag.default) {
utils.reportJSDoc(`Defaults are not permitted on @${tag.tag}.`, tag, () => {
utils.changeTag(tag, {
name: tag.name.replace(/([^=]*)(=.+)?/u, '[$1]')
});
});
}
}
const defaultTags = utils.getPresentTags(['default', 'defaultvalue']);
for (const tag of defaultTags) {
if (tag.description.trim()) {
utils.reportJSDoc(`Default values are not permitted on @${tag.tag}.`, tag, () => {
utils.changeTag(tag, {
description: '',
postTag: ''
});
});
}
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'This rule reports defaults being used on the relevant portion of `@param` or `@default`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-defaults.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
noOptionalParamNames: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noDefaults.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noDefaults.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","utils","noOptionalParamNames","options","paramTags","getPresentTags","tag","optional","reportJSDoc","changeTag","name","replace","defaultTags","description","trim","postTag","contextDefaults","meta","docs","url","fixable","schema","additionalProperties","properties","contexts","items","anyOf","type","comment","module"],"sources":["../../src/rules/noDefaults.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n utils,\n}) => {\n const {\n noOptionalParamNames,\n } = context.options[0] || {};\n const paramTags = utils.getPresentTags([\n 'param', 'arg', 'argument',\n ]);\n for (const tag of paramTags) {\n if (noOptionalParamNames && tag.optional) {\n utils.reportJSDoc(`Optional param names are not permitted on @${tag.tag}.`, tag, () => {\n utils.changeTag(tag, {\n name: tag.name.replace(/([^=]*)(=.+)?/u, '$1'),\n });\n });\n } else if (tag.default) {\n utils.reportJSDoc(`Defaults are not permitted on @${tag.tag}.`, tag, () => {\n utils.changeTag(tag, {\n name: tag.name.replace(/([^=]*)(=.+)?/u, '[$1]'),\n });\n });\n }\n }\n\n const defaultTags = utils.getPresentTags([\n 'default', 'defaultvalue',\n ]);\n for (const tag of defaultTags) {\n if (tag.description.trim()) {\n utils.reportJSDoc(`Default values are not permitted on @${tag.tag}.`, tag, () => {\n utils.changeTag(tag, {\n description: '',\n postTag: '',\n });\n });\n }\n }\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'This rule reports defaults being used on the relevant portion of `@param` or `@default`.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-defaults.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n noOptionalParamNames: {\n type: 'boolean',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC;AACF,CAAC,KAAK;EACJ,MAAM;IACJC;EACF,CAAC,GAAGF,OAAO,CAACG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;EAC5B,MAAMC,SAAS,GAAGH,KAAK,CAACI,cAAc,CAAC,CACrC,OAAO,EAAE,KAAK,EAAE,UAAU,CAC3B,CAAC;EACF,KAAK,MAAMC,GAAG,IAAIF,SAAS,EAAE;IAC3B,IAAIF,oBAAoB,IAAII,GAAG,CAACC,QAAQ,EAAE;MACxCN,KAAK,CAACO,WAAW,CAAC,8CAA8CF,GAAG,CAACA,GAAG,GAAG,EAAEA,GAAG,EAAE,MAAM;QACrFL,KAAK,CAACQ,SAAS,CAACH,GAAG,EAAE;UACnBI,IAAI,EAAEJ,GAAG,CAACI,IAAI,CAACC,OAAO,CAAC,gBAAgB,EAAE,IAAI;QAC/C,CAAC,CAAC;MACJ,CAAC,CAAC;IACJ,CAAC,MAAM,IAAIL,GAAG,CAACV,OAAO,EAAE;MACtBK,KAAK,CAACO,WAAW,CAAC,kCAAkCF,GAAG,CAACA,GAAG,GAAG,EAAEA,GAAG,EAAE,MAAM;QACzEL,KAAK,CAACQ,SAAS,CAACH,GAAG,EAAE;UACnBI,IAAI,EAAEJ,GAAG,CAACI,IAAI,CAACC,OAAO,CAAC,gBAAgB,EAAE,MAAM;QACjD,CAAC,CAAC;MACJ,CAAC,CAAC;IACJ;EACF;EAEA,MAAMC,WAAW,GAAGX,KAAK,CAACI,cAAc,CAAC,CACvC,SAAS,EAAE,cAAc,CAC1B,CAAC;EACF,KAAK,MAAMC,GAAG,IAAIM,WAAW,EAAE;IAC7B,IAAIN,GAAG,CAACO,WAAW,CAACC,IAAI,CAAC,CAAC,EAAE;MAC1Bb,KAAK,CAACO,WAAW,CAAC,wCAAwCF,GAAG,CAACA,GAAG,GAAG,EAAEA,GAAG,EAAE,MAAM;QAC/EL,KAAK,CAACQ,SAAS,CAACH,GAAG,EAAE;UACnBO,WAAW,EAAE,EAAE;UACfE,OAAO,EAAE;QACX,CAAC,CAAC;MACJ,CAAC,CAAC;IACJ;EACF;AACF,CAAC,EAAE;EACDC,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJL,WAAW,EAAE,0FAA0F;MACvGM,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEC,IAAI,EAAE;YACR,CAAC,EACD;cACEL,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVK,OAAO,EAAE;kBACPD,IAAI,EAAE;gBACR,CAAC;gBACD3B,OAAO,EAAE;kBACP2B,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR,CAAC;QACDzB,oBAAoB,EAAE;UACpByB,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAE,MAAA,CAAA/B,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,176 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @typedef {{
* comment: string,
* context: string,
* message: string,
* minimum: import('../iterateJsdoc.js').Integer
* }} ContextObject
*/
/**
* @typedef {string|ContextObject} Context
*/
/**
* @param {import('../iterateJsdoc.js').StateObject} state
* @returns {void}
*/
const setDefaults = state => {
if (!state.selectorMap) {
state.selectorMap = {};
}
};
/**
* @param {import('../iterateJsdoc.js').StateObject} state
* @param {string} selector
* @param {string} comment
* @returns {void}
*/
const incrementSelector = (state, selector, comment) => {
if (!state.selectorMap[selector]) {
state.selectorMap[selector] = {};
}
if (!state.selectorMap[selector][comment]) {
state.selectorMap[selector][comment] = 0;
}
state.selectorMap[selector][comment]++;
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
info: {
comment
},
state,
utils
}) => {
if (!context.options[0]) {
// Handle error later
return;
}
/**
* @type {Context[]}
*/
const contexts = context.options[0].contexts;
const {
contextStr
} = utils.findContext(contexts, comment);
setDefaults(state);
incrementSelector(state, contextStr, String(comment));
}, {
contextSelected: true,
exit({
context,
settings,
state
}) {
if (!context.options.length && !settings.contexts) {
context.report({
loc: {
end: {
column: 1,
line: 1
},
start: {
column: 1,
line: 1
}
},
message: 'Rule `no-missing-syntax` is missing a `contexts` option.'
});
return;
}
setDefaults(state);
/**
* @type {Context[]}
*/
const contexts = (context.options[0] ?? {}).contexts ?? (settings === null || settings === void 0 ? void 0 : settings.contexts);
// Report when MISSING
contexts.some(cntxt => {
const contextStr = typeof cntxt === 'object' ? cntxt.context ?? 'any' : cntxt;
const comment = typeof cntxt === 'string' ? '' : cntxt === null || cntxt === void 0 ? void 0 : cntxt.comment;
const contextKey = contextStr === 'any' ? 'undefined' : contextStr;
if ((!state.selectorMap[contextKey] || !state.selectorMap[contextKey][comment] || state.selectorMap[contextKey][comment] < (
// @ts-expect-error comment would need an object, not string
(cntxt === null || cntxt === void 0 ? void 0 : cntxt.minimum) ?? 1)) && (contextStr !== 'any' || Object.values(state.selectorMap).every(cmmnt => {
return !cmmnt[comment] || cmmnt[comment] < (
// @ts-expect-error comment would need an object, not string
(cntxt === null || cntxt === void 0 ? void 0 : cntxt.minimum) ?? 1);
}))) {
const message = typeof cntxt === 'string' ? 'Syntax is required: {{context}}' : (cntxt === null || cntxt === void 0 ? void 0 : cntxt.message) ?? 'Syntax is required: {{context}}' + (comment ? ' with {{comment}}' : '');
context.report({
data: {
comment,
context: contextStr
},
loc: {
end: {
column: 1,
line: 1
},
start: {
column: 1,
line: 1
}
},
message
});
return true;
}
return false;
});
},
matchContext: true,
meta: {
docs: {
description: 'Reports when certain comment structures are always expected.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-missing-syntax.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
},
message: {
type: 'string'
},
minimum: {
type: 'integer'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noMissingSyntax.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const middleAsterisksBlockWS = /^([\t ]|\*(?!\*))+/u;
const middleAsterisksNoBlockWS = /^\*+/u;
const endAsterisksSingleLineBlockWS = /\*((?:\*|(?: |\t))*)\*$/u;
const endAsterisksMultipleLineBlockWS = /((?:\*|(?: |\t))*)\*$/u;
const endAsterisksSingleLineNoBlockWS = /\*(\**)\*$/u;
const endAsterisksMultipleLineNoBlockWS = /(\**)\*$/u;
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils
}) => {
const {
allowWhitespace = false,
preventAtEnd = true,
preventAtMiddleLines = true
} = context.options[0] || {};
const middleAsterisks = allowWhitespace ? middleAsterisksNoBlockWS : middleAsterisksBlockWS;
// eslint-disable-next-line complexity -- Todo
jsdoc.source.some(({
tokens,
number
}) => {
const {
delimiter,
tag,
name,
type,
description,
end,
postDelimiter
} = tokens;
if (preventAtMiddleLines && !end && !tag && !type && !name && (!allowWhitespace && middleAsterisks.test(description) || allowWhitespace && middleAsterisks.test(postDelimiter + description))) {
// console.log('description', JSON.stringify(description));
const fix = () => {
tokens.description = description.replace(middleAsterisks, '');
};
utils.reportJSDoc('Should be no multiple asterisks on middle lines.', {
line: number
}, fix, true);
return true;
}
if (!preventAtEnd || !end) {
return false;
}
const isSingleLineBlock = delimiter === '/**';
const delim = isSingleLineBlock ? '*' : delimiter;
const endAsterisks = allowWhitespace ? isSingleLineBlock ? endAsterisksSingleLineNoBlockWS : endAsterisksMultipleLineNoBlockWS : isSingleLineBlock ? endAsterisksSingleLineBlockWS : endAsterisksMultipleLineBlockWS;
const endingAsterisksAndSpaces = (allowWhitespace ? postDelimiter + description + delim : description + delim).match(endAsterisks);
if (!endingAsterisksAndSpaces || !isSingleLineBlock && endingAsterisksAndSpaces[1] && !endingAsterisksAndSpaces[1].trim()) {
return false;
}
const endFix = () => {
if (!isSingleLineBlock) {
tokens.delimiter = '';
}
tokens.description = (description + delim).replace(endAsterisks, '');
};
utils.reportJSDoc('Should be no multiple asterisks on end lines.', {
line: number
}, endFix, true);
return true;
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: '',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-multi-asterisks.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
allowWhitespace: {
type: 'boolean'
},
preventAtEnd: {
type: 'boolean'
},
preventAtMiddleLines: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noMultiAsterisks.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
info: {
comment
},
report,
utils
}) => {
if (!context.options.length) {
report('Rule `no-restricted-syntax` is missing a `contexts` option.');
return;
}
const {
contexts
} = context.options[0];
const {
foundContext,
contextStr
} = utils.findContext(contexts, comment);
// We are not on the *particular* matching context/comment, so don't assume
// we need reporting
if (!foundContext) {
return;
}
const message = /** @type {import('../iterateJsdoc.js').ContextObject} */(foundContext === null || foundContext === void 0 ? void 0 : foundContext.message) ?? 'Syntax is restricted: {{context}}' + (comment ? ' with {{comment}}' : '');
report(message, null, null, comment ? {
comment,
context: contextStr
} : {
context: contextStr
});
}, {
contextSelected: true,
meta: {
docs: {
description: 'Reports when certain comment structures are present.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
},
message: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
required: ['contexts'],
type: 'object'
}],
type: 'suggestion'
},
nonGlobalSettings: true
});
module.exports = exports.default;
//# sourceMappingURL=noRestrictedSyntax.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noRestrictedSyntax.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","info","comment","report","utils","options","length","contexts","foundContext","contextStr","findContext","message","contextSelected","meta","docs","description","url","fixable","schema","additionalProperties","properties","items","anyOf","type","required","nonGlobalSettings","module"],"sources":["../../src/rules/noRestrictedSyntax.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n info: {\n comment,\n },\n report,\n utils,\n}) => {\n if (!context.options.length) {\n report('Rule `no-restricted-syntax` is missing a `contexts` option.');\n\n return;\n }\n\n const {\n contexts,\n } = context.options[0];\n\n const {\n foundContext,\n contextStr,\n } = utils.findContext(contexts, comment);\n\n // We are not on the *particular* matching context/comment, so don't assume\n // we need reporting\n if (!foundContext) {\n return;\n }\n\n const message = /** @type {import('../iterateJsdoc.js').ContextObject} */ (\n foundContext\n )?.message ??\n 'Syntax is restricted: {{context}}' +\n (comment ? ' with {{comment}}' : '');\n\n report(message, null, null, comment ? {\n comment,\n context: contextStr,\n } : {\n context: contextStr,\n });\n}, {\n contextSelected: true,\n meta: {\n docs: {\n description: 'Reports when certain comment structures are present.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-restricted-syntax.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n message: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n required: [\n 'contexts',\n ],\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n nonGlobalSettings: true,\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC,IAAI,EAAE;IACJC;EACF,CAAC;EACDC,MAAM;EACNC;AACF,CAAC,KAAK;EACJ,IAAI,CAACJ,OAAO,CAACK,OAAO,CAACC,MAAM,EAAE;IAC3BH,MAAM,CAAC,6DAA6D,CAAC;IAErE;EACF;EAEA,MAAM;IACJI;EACF,CAAC,GAAGP,OAAO,CAACK,OAAO,CAAC,CAAC,CAAC;EAEtB,MAAM;IACJG,YAAY;IACZC;EACF,CAAC,GAAGL,KAAK,CAACM,WAAW,CAACH,QAAQ,EAAEL,OAAO,CAAC;;EAExC;EACA;EACA,IAAI,CAACM,YAAY,EAAE;IACjB;EACF;EAEA,MAAMG,OAAO,GAAG,yDAA0D,CACxEH,YAAY,aAAZA,YAAY,uBAAZA,YAAY,CACXG,OAAO,KACR,mCAAmC,IAChCT,OAAO,GAAG,mBAAmB,GAAG,EAAE,CAAC;EAExCC,MAAM,CAACQ,OAAO,EAAE,IAAI,EAAE,IAAI,EAAET,OAAO,GAAG;IACpCA,OAAO;IACPF,OAAO,EAAES;EACX,CAAC,GAAG;IACFT,OAAO,EAAES;EACX,CAAC,CAAC;AACJ,CAAC,EAAE;EACDG,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,sDAAsD;MACnEC,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVb,QAAQ,EAAE;UACRc,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEC,IAAI,EAAE;YACR,CAAC,EACD;cACEJ,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVlB,OAAO,EAAE;kBACPqB,IAAI,EAAE;gBACR,CAAC;gBACDvB,OAAO,EAAE;kBACPuB,IAAI,EAAE;gBACR,CAAC;gBACDZ,OAAO,EAAE;kBACPY,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDC,QAAQ,EAAE,CACR,UAAU,CACX;MACDD,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR,CAAC;EACDE,iBAAiB,EAAE;AACrB,CAAC,CAAC;AAAAC,MAAA,CAAA5B,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,73 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {import('comment-parser').Line} line
*/
const removeType = ({
tokens
}) => {
tokens.postTag = '';
tokens.type = '';
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
utils
}) => {
if (!utils.isIteratingFunction() && !utils.isVirtualFunction()) {
return;
}
const tags = utils.getPresentTags(['param', 'arg', 'argument', 'returns', 'return']);
for (const tag of tags) {
if (tag.type) {
utils.reportJSDoc(`Types are not permitted on @${tag.tag}.`, tag, () => {
for (const source of tag.source) {
removeType(source);
}
});
}
}
}, {
contextDefaults: ['ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'TSDeclareFunction',
// Add this to above defaults
'TSMethodSignature'],
meta: {
docs: {
description: 'This rule reports types being used on `@param` or `@returns`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-types.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noTypes.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"noTypes.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","removeType","tokens","postTag","type","_default","exports","iterateJsdoc","utils","isIteratingFunction","isVirtualFunction","tags","getPresentTags","tag","reportJSDoc","source","contextDefaults","meta","docs","description","url","fixable","schema","additionalProperties","properties","contexts","items","anyOf","comment","context","module"],"sources":["../../src/rules/noTypes.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\n/**\n * @param {import('comment-parser').Line} line\n */\nconst removeType = ({\n tokens,\n}) => {\n tokens.postTag = '';\n tokens.type = '';\n};\n\nexport default iterateJsdoc(({\n utils,\n}) => {\n if (!utils.isIteratingFunction() && !utils.isVirtualFunction()) {\n return;\n }\n\n const tags = utils.getPresentTags([\n 'param', 'arg', 'argument', 'returns', 'return',\n ]);\n\n for (const tag of tags) {\n if (tag.type) {\n utils.reportJSDoc(`Types are not permitted on @${tag.tag}.`, tag, () => {\n for (const source of tag.source) {\n removeType(source);\n }\n });\n }\n }\n}, {\n contextDefaults: [\n 'ArrowFunctionExpression', 'FunctionDeclaration', 'FunctionExpression', 'TSDeclareFunction',\n // Add this to above defaults\n 'TSMethodSignature'\n ],\n meta: {\n docs: {\n description: 'This rule reports types being used on `@param` or `@returns`.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-types.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE9C;AACA;AACA;AACA,MAAMG,UAAU,GAAGA,CAAC;EAClBC;AACF,CAAC,KAAK;EACJA,MAAM,CAACC,OAAO,GAAG,EAAE;EACnBD,MAAM,CAACE,IAAI,GAAG,EAAE;AAClB,CAAC;AAAC,IAAAC,QAAA,GAAAC,OAAA,CAAAN,OAAA,GAEa,IAAAO,qBAAY,EAAC,CAAC;EAC3BC;AACF,CAAC,KAAK;EACJ,IAAI,CAACA,KAAK,CAACC,mBAAmB,CAAC,CAAC,IAAI,CAACD,KAAK,CAACE,iBAAiB,CAAC,CAAC,EAAE;IAC9D;EACF;EAEA,MAAMC,IAAI,GAAGH,KAAK,CAACI,cAAc,CAAC,CAChC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,CAChD,CAAC;EAEF,KAAK,MAAMC,GAAG,IAAIF,IAAI,EAAE;IACtB,IAAIE,GAAG,CAACT,IAAI,EAAE;MACZI,KAAK,CAACM,WAAW,CAAC,+BAA+BD,GAAG,CAACA,GAAG,GAAG,EAAEA,GAAG,EAAE,MAAM;QACtE,KAAK,MAAME,MAAM,IAAIF,GAAG,CAACE,MAAM,EAAE;UAC/Bd,UAAU,CAACc,MAAM,CAAC;QACpB;MACF,CAAC,CAAC;IACJ;EACF;AACF,CAAC,EAAE;EACDC,eAAe,EAAE,CACf,yBAAyB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,mBAAmB;EAC3F;EACA,mBAAmB,CACpB;EACDC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,+DAA+D;MAC5EC,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEvB,IAAI,EAAE;YACR,CAAC,EACD;cACEmB,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVI,OAAO,EAAE;kBACPxB,IAAI,EAAE;gBACR,CAAC;gBACDyB,OAAO,EAAE;kBACPzB,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAA0B,MAAA,CAAAxB,OAAA,GAAAA,OAAA,CAAAN,OAAA","ignoreList":[]}

View File

@ -0,0 +1,300 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _path = require("path");
var _url = require("url");
var _synckit = require("synckit");
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _iterateJsdoc = _interopRequireWildcard(require("../iterateJsdoc.cjs"));
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const _dirname = (0, _path.dirname)((0, _url.fileURLToPath)(require('url').pathToFileURL(__filename).toString()));
const pathName = (0, _path.join)(_dirname, '../import-worker.mjs');
const extraTypes = ['null', 'undefined', 'void', 'string', 'boolean', 'object', 'function', 'symbol', 'number', 'bigint', 'NaN', 'Infinity', 'any', '*', 'never', 'unknown', 'const', 'this', 'true', 'false', 'Array', 'Object', 'RegExp', 'Date', 'Function'];
const typescriptGlobals = [
// https://www.typescriptlang.org/docs/handbook/utility-types.html
'Awaited', 'Partial', 'Required', 'Readonly', 'Record', 'Pick', 'Omit', 'Exclude', 'Extract', 'NonNullable', 'Parameters', 'ConstructorParameters', 'ReturnType', 'InstanceType', 'ThisParameterType', 'OmitThisParameter', 'ThisType', 'Uppercase', 'Lowercase', 'Capitalize', 'Uncapitalize'];
/**
* @param {string|false|undefined} [str]
* @returns {undefined|string|false}
*/
const stripPseudoTypes = str => {
return str && str.replace(/(?:\.|<>|\.<>|\[\])$/u, '');
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
node,
report,
settings,
sourceCode,
utils
}) => {
var _globalScope$childSco;
const {
scopeManager
} = sourceCode;
// When is this ever `null`?
const globalScope = /** @type {import('eslint').Scope.Scope} */
scopeManager.globalScope;
const
/**
* @type {{
* definedTypes: string[],
* disableReporting: boolean,
* markVariablesAsUsed: boolean
* }}
*/
{
definedTypes = [],
disableReporting = false,
markVariablesAsUsed = true
} = context.options[0] || {};
/** @type {(string|undefined)[]} */
let definedPreferredTypes = [];
const {
preferredTypes,
structuredTags,
mode
} = settings;
if (Object.keys(preferredTypes).length) {
definedPreferredTypes = /** @type {string[]} */Object.values(preferredTypes).map(preferredType => {
if (typeof preferredType === 'string') {
// May become an empty string but will be filtered out below
return stripPseudoTypes(preferredType);
}
if (!preferredType) {
return undefined;
}
if (typeof preferredType !== 'object') {
utils.reportSettings('Invalid `settings.jsdoc.preferredTypes`. Values must be falsy, a string, or an object.');
}
return stripPseudoTypes(preferredType.replacement);
}).filter(Boolean);
}
const comments = sourceCode.getAllComments().filter(comment => {
return /^\*\s/u.test(comment.value);
}).map(commentNode => {
return (0, _iterateJsdoc.parseComment)(commentNode, '');
});
const typedefDeclarations = comments.flatMap(doc => {
return doc.tags.filter(({
tag
}) => {
return utils.isNamepathDefiningTag(tag);
});
}).map(tag => {
return tag.name;
});
const importTags = settings.mode === 'typescript' ? ( /** @type {string[]} */comments.flatMap(doc => {
return doc.tags.filter(({
tag
}) => {
return tag === 'import';
});
}).flatMap(tag => {
const {
type,
name,
description
} = tag;
const typePart = type ? `{${type}} ` : '';
const imprt = 'import ' + (description ? `${typePart}${name} ${description}` : `${typePart}${name}`);
const getImports = (0, _synckit.createSyncFn)(pathName);
const imports = /** @type {import('parse-imports').Import[]} */getImports(imprt);
if (!imports) {
return null;
}
return imports.flatMap(({
importClause
}) => {
/* c8 ignore next */
const {
default: dflt,
named,
namespace
} = importClause || {};
const types = [];
if (dflt) {
types.push(dflt);
}
if (namespace) {
types.push(namespace);
}
if (named) {
for (const {
binding
} of named) {
types.push(binding);
}
}
return types;
});
}).filter(Boolean)) : [];
const ancestorNodes = [];
let currentNode = node;
// No need for Program node?
while ((_currentNode = currentNode) !== null && _currentNode !== void 0 && _currentNode.parent) {
var _currentNode;
ancestorNodes.push(currentNode);
currentNode = currentNode.parent;
}
/**
* @param {import('eslint').Rule.Node} ancestorNode
* @returns {import('comment-parser').Spec[]}
*/
const getTemplateTags = function (ancestorNode) {
const commentNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, ancestorNode, settings);
if (!commentNode) {
return [];
}
const jsdoc = (0, _iterateJsdoc.parseComment)(commentNode, '');
return jsdoc.tags.filter(tag => {
return tag.tag === 'template';
});
};
// `currentScope` may be `null` or `Program`, so in such a case,
// we look to present tags instead
const templateTags = ancestorNodes.length ? ancestorNodes.flatMap(ancestorNode => {
return getTemplateTags(ancestorNode);
}) : utils.getPresentTags(['template']);
const closureGenericTypes = templateTags.flatMap(tag => {
return utils.parseClosureTemplateTag(tag);
});
// In modules, including Node, there is a global scope at top with the
// Program scope inside
const cjsOrESMScope = ((_globalScope$childSco = globalScope.childScopes[0]) === null || _globalScope$childSco === void 0 || (_globalScope$childSco = _globalScope$childSco.block) === null || _globalScope$childSco === void 0 ? void 0 : _globalScope$childSco.type) === 'Program';
const allDefinedTypes = new Set(globalScope.variables.map(({
name
}) => {
return name;
})
// If the file is a module, concat the variables from the module scope.
.concat(cjsOrESMScope ? globalScope.childScopes.flatMap(({
variables
}) => {
return variables;
}).map(({
name
}) => {
return name;
/* c8 ignore next */
}) : []).concat(extraTypes).concat(typedefDeclarations).concat(importTags).concat(definedTypes).concat( /** @type {string[]} */definedPreferredTypes).concat(settings.mode === 'jsdoc' ? [] : [...(settings.mode === 'typescript' ? typescriptGlobals : []), ...closureGenericTypes]));
/**
* @typedef {{
* parsedType: import('jsdoc-type-pratt-parser').RootResult;
* tag: import('comment-parser').Spec|import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
* line?: import('../iterateJsdoc.js').Integer
* }
* }} TypeAndTagInfo
*/
/**
* @param {string} propertyName
* @returns {(tag: (import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
* name?: string,
* type?: string,
* line?: import('../iterateJsdoc.js').Integer
* })|import('comment-parser').Spec & {
* namepathOrURL?: string
* }
* ) => undefined|TypeAndTagInfo}
*/
const tagToParsedType = propertyName => {
return tag => {
try {
const potentialType = tag[( /** @type {"type"|"name"|"namepathOrURL"} */propertyName)];
return {
parsedType: mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialType) : (0, _jsdoccomment.parse)( /** @type {string} */potentialType, mode),
tag
};
} catch {
return undefined;
}
};
};
const typeTags = utils.filterTags(({
tag
}) => {
return tag !== 'import' && utils.tagMightHaveTypePosition(tag) && (tag !== 'suppress' || settings.mode !== 'closure');
}).map(tagToParsedType('type'));
const namepathReferencingTags = utils.filterTags(({
tag
}) => {
return utils.isNamepathReferencingTag(tag);
}).map(tagToParsedType('name'));
const namepathOrUrlReferencingTags = utils.filterAllTags(({
tag
}) => {
return utils.isNamepathOrUrlReferencingTag(tag);
}).map(tagToParsedType('namepathOrURL'));
const tagsWithTypes = /** @type {TypeAndTagInfo[]} */[...typeTags, ...namepathReferencingTags, ...namepathOrUrlReferencingTags
// Remove types which failed to parse
].filter(Boolean);
for (const {
tag,
parsedType
} of tagsWithTypes) {
(0, _jsdoccomment.traverse)(parsedType, nde => {
const {
type,
value
} = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
if (type === 'JsdocTypeName') {
var _structuredTags$tag$t;
const structuredTypes = (_structuredTags$tag$t = structuredTags[tag.tag]) === null || _structuredTags$tag$t === void 0 ? void 0 : _structuredTags$tag$t.type;
if (!allDefinedTypes.has(value) && (!Array.isArray(structuredTypes) || !structuredTypes.includes(value))) {
if (!disableReporting) {
report(`The type '${value}' is undefined.`, null, tag);
}
} else if (markVariablesAsUsed && !extraTypes.includes(value)) {
if (sourceCode.markVariableAsUsed) {
sourceCode.markVariableAsUsed(value);
/* c8 ignore next 3 */
} else {
context.markVariableAsUsed(value);
}
}
}
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that types in jsdoc comments are defined.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-undefined-types.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
definedTypes: {
items: {
type: 'string'
},
type: 'array'
},
disableReporting: {
type: 'boolean'
},
markVariablesAsUsed: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=noUndefinedTypes.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,166 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils,
indent
}) => {
const [defaultRequireValue = 'always', {
tags: tagMap = {}
} = {}] = context.options;
const {
source
} = jsdoc;
const always = defaultRequireValue === 'always';
const never = defaultRequireValue === 'never';
/** @type {string} */
let currentTag;
source.some(({
number,
tokens
}) => {
var _tagMap$any2;
const {
delimiter,
tag,
end,
description
} = tokens;
/**
* @returns {void}
*/
const neverFix = () => {
tokens.delimiter = '';
tokens.postDelimiter = '';
};
/**
* @param {string} checkValue
* @returns {boolean}
*/
const checkNever = checkValue => {
var _tagMap$always, _tagMap$never;
if (delimiter && delimiter !== '/**' && (never && !((_tagMap$always = tagMap.always) !== null && _tagMap$always !== void 0 && _tagMap$always.includes(checkValue)) || (_tagMap$never = tagMap.never) !== null && _tagMap$never !== void 0 && _tagMap$never.includes(checkValue))) {
utils.reportJSDoc('Expected JSDoc line to have no prefix.', {
column: 0,
line: number
}, neverFix);
return true;
}
return false;
};
/**
* @returns {void}
*/
const alwaysFix = () => {
if (!tokens.start) {
tokens.start = indent + ' ';
}
tokens.delimiter = '*';
tokens.postDelimiter = tag || description ? ' ' : '';
};
/**
* @param {string} checkValue
* @returns {boolean}
*/
const checkAlways = checkValue => {
var _tagMap$never2, _tagMap$always2;
if (!delimiter && (always && !((_tagMap$never2 = tagMap.never) !== null && _tagMap$never2 !== void 0 && _tagMap$never2.includes(checkValue)) || (_tagMap$always2 = tagMap.always) !== null && _tagMap$always2 !== void 0 && _tagMap$always2.includes(checkValue))) {
utils.reportJSDoc('Expected JSDoc line to have the prefix.', {
column: 0,
line: number
}, alwaysFix);
return true;
}
return false;
};
if (tag) {
// Remove at sign
currentTag = tag.slice(1);
}
if (
// If this is the end but has a tag, the delimiter will also be
// populated and will be safely ignored later
end && !tag) {
return false;
}
if (!currentTag) {
var _tagMap$any;
if ((_tagMap$any = tagMap.any) !== null && _tagMap$any !== void 0 && _tagMap$any.includes('*description')) {
return false;
}
if (checkNever('*description')) {
return true;
}
if (checkAlways('*description')) {
return true;
}
return false;
}
if ((_tagMap$any2 = tagMap.any) !== null && _tagMap$any2 !== void 0 && _tagMap$any2.includes(currentTag)) {
return false;
}
if (checkNever(currentTag)) {
return true;
}
if (checkAlways(currentTag)) {
return true;
}
return false;
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires that each JSDoc line starts with an `*`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-asterisk-prefix.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
enum: ['always', 'never', 'any'],
type: 'string'
}, {
additionalProperties: false,
properties: {
tags: {
properties: {
always: {
items: {
type: 'string'
},
type: 'array'
},
any: {
items: {
type: 'string'
},
type: 'array'
},
never: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireAsteriskPrefix.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,135 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {string} description
* @returns {import('../iterateJsdoc.js').Integer}
*/
const checkDescription = description => {
return description.trim().split('\n').filter(Boolean).length;
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
report,
utils,
context
}) => {
if (utils.avoidDocs()) {
return;
}
const {
descriptionStyle = 'body'
} = context.options[0] || {};
let targetTagName = utils.getPreferredTagName({
// We skip reporting except when `@description` is essential to the rule,
// so user can block the tag and still meaningfully use this rule
// even if the tag is present (and `check-tag-names` is the one to
// normally report the fact that it is blocked but present)
skipReportingBlockedTag: descriptionStyle !== 'tag',
tagName: 'description'
});
if (!targetTagName) {
return;
}
const isBlocked = typeof targetTagName === 'object' && 'blocked' in targetTagName && targetTagName.blocked;
if (isBlocked) {
targetTagName = /** @type {{blocked: true; tagName: string;}} */targetTagName.tagName;
}
if (descriptionStyle !== 'tag') {
const {
description
} = utils.getDescription();
if (checkDescription(description || '')) {
return;
}
if (descriptionStyle === 'body') {
const descTags = utils.getPresentTags(['desc', 'description']);
if (descTags.length) {
const [{
tag: tagName
}] = descTags;
report(`Remove the @${tagName} tag to leave a plain block description or add additional description text above the @${tagName} line.`);
} else {
report('Missing JSDoc block description.');
}
return;
}
}
const functionExamples = isBlocked ? [] : jsdoc.tags.filter(({
tag
}) => {
return tag === targetTagName;
});
if (!functionExamples.length) {
report(descriptionStyle === 'any' ? `Missing JSDoc block description or @${targetTagName} declaration.` : `Missing JSDoc @${targetTagName} declaration.`);
return;
}
for (const example of functionExamples) {
if (!checkDescription(`${example.name} ${utils.getTagDescription(example)}`)) {
report(`Missing JSDoc @${targetTagName} description.`, null, example);
}
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that all functions have a description.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-description.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
checkConstructors: {
default: true,
type: 'boolean'
},
checkGetters: {
default: true,
type: 'boolean'
},
checkSetters: {
default: true,
type: 'boolean'
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
descriptionStyle: {
enum: ['body', 'tag', 'any'],
type: 'string'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireDescription.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,282 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
var _escapeStringRegexp = _interopRequireDefault(require("escape-string-regexp"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const otherDescriptiveTags = new Set([
// 'copyright' and 'see' might be good addition, but as the former may be
// sensitive text, and the latter may have just a link, they are not
// included by default
'summary', 'file', 'fileoverview', 'overview', 'classdesc', 'todo', 'deprecated', 'throws', 'exception', 'yields', 'yield']);
/**
* @param {string} text
* @returns {string[]}
*/
const extractParagraphs = text => {
return text.split(/(?<![;:])\n\n+/u);
};
/**
* @param {string} text
* @param {string|RegExp} abbreviationsRegex
* @returns {string[]}
*/
const extractSentences = (text, abbreviationsRegex) => {
const txt = text
// Remove all {} tags.
.replaceAll(/(?<!^)\{[\s\S]*?\}\s*/gu, '')
// Remove custom abbreviations
.replace(abbreviationsRegex, '');
const sentenceEndGrouping = /([.?!])(?:\s+|$)/ug;
const puncts = [...txt.matchAll(sentenceEndGrouping)].map(sentEnd => {
return sentEnd[0];
});
return txt.split(/[.?!](?:\s+|$)/u)
// Re-add the dot.
.map((sentence, idx) => {
return !puncts[idx] && /^\s*$/u.test(sentence) ? sentence : `${sentence}${puncts[idx] || ''}`;
});
};
/**
* @param {string} text
* @returns {boolean}
*/
const isNewLinePrecededByAPeriod = text => {
/** @type {boolean} */
let lastLineEndsSentence;
const lines = text.split('\n');
return !lines.some(line => {
if (lastLineEndsSentence === false && /^[A-Z][a-z]/u.test(line)) {
return true;
}
lastLineEndsSentence = /[.:?!|]$/u.test(line);
return false;
});
};
/**
* @param {string} str
* @returns {boolean}
*/
const isCapitalized = str => {
return str[0] === str[0].toUpperCase();
};
/**
* @param {string} str
* @returns {boolean}
*/
const isTable = str => {
return str.charAt(0) === '|';
};
/**
* @param {string} str
* @returns {string}
*/
const capitalize = str => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
/**
* @param {string} description
* @param {import('../iterateJsdoc.js').Report} reportOrig
* @param {import('eslint').Rule.Node} jsdocNode
* @param {string|RegExp} abbreviationsRegex
* @param {import('eslint').SourceCode} sourceCode
* @param {import('comment-parser').Spec|{
* line: import('../iterateJsdoc.js').Integer
* }} tag
* @param {boolean} newlineBeforeCapsAssumesBadSentenceEnd
* @returns {boolean}
*/
const validateDescription = (description, reportOrig, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd) => {
if (!description || /^\n+$/u.test(description)) {
return false;
}
const descriptionNoHeadings = description.replaceAll(/^\s*#[^\n]*(\n|$)/gm, '');
const paragraphs = extractParagraphs(descriptionNoHeadings).filter(Boolean);
return paragraphs.some((paragraph, parIdx) => {
const sentences = extractSentences(paragraph, abbreviationsRegex);
const fix = /** @type {import('eslint').Rule.ReportFixer} */fixer => {
let text = sourceCode.getText(jsdocNode);
if (!/[.:?!]$/u.test(paragraph)) {
const line = paragraph.split('\n').filter(Boolean).pop();
text = text.replace(new RegExp(`${(0, _escapeStringRegexp.default)( /** @type {string} */
line)}$`, 'mu'), `${line}.`);
}
for (const sentence of sentences.filter(sentence_ => {
return !/^\s*$/u.test(sentence_) && !isCapitalized(sentence_) && !isTable(sentence_);
})) {
const beginning = sentence.split('\n')[0];
if ('tag' in tag && tag.tag) {
const reg = new RegExp(`(@${(0, _escapeStringRegexp.default)(tag.tag)}.*)${(0, _escapeStringRegexp.default)(beginning)}`, 'u');
text = text.replace(reg, (_$0, $1) => {
return $1 + capitalize(beginning);
});
} else {
text = text.replace(new RegExp('((?:[.?!]|\\*|\\})\\s*)' + (0, _escapeStringRegexp.default)(beginning), 'u'), '$1' + capitalize(beginning));
}
}
return fixer.replaceText(jsdocNode, text);
};
/**
* @param {string} msg
* @param {import('eslint').Rule.ReportFixer | null | undefined} fixer
* @param {{
* line?: number | undefined;
* column?: number | undefined;
* } | (import('comment-parser').Spec & {
* line?: number | undefined;
* column?: number | undefined;
* })} tagObj
* @returns {void}
*/
const report = (msg, fixer, tagObj) => {
if ('line' in tagObj) {
/**
* @type {{
* line: number;
* }}
*/
tagObj.line += parIdx * 2;
} else {
/** @type {import('comment-parser').Spec} */tagObj.source[0].number += parIdx * 2;
}
// Avoid errors if old column doesn't exist here
tagObj.column = 0;
reportOrig(msg, fixer, tagObj);
};
if (sentences.some(sentence => {
return /^[.?!]$/u.test(sentence);
})) {
report('Sentences must be more than punctuation.', null, tag);
}
if (sentences.some(sentence => {
return !/^\s*$/u.test(sentence) && !isCapitalized(sentence) && !isTable(sentence);
})) {
report('Sentences should start with an uppercase character.', fix, tag);
}
const paragraphNoAbbreviations = paragraph.replace(abbreviationsRegex, '');
if (!/(?:[.?!|]|```)\s*$/u.test(paragraphNoAbbreviations)) {
report('Sentences must end with a period.', fix, tag);
return true;
}
if (newlineBeforeCapsAssumesBadSentenceEnd && !isNewLinePrecededByAPeriod(paragraphNoAbbreviations)) {
report('A line of text is started with an uppercase character, but the preceding line does not end the sentence.', null, tag);
return true;
}
return false;
});
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
context,
jsdoc,
report,
jsdocNode,
utils
}) => {
const /** @type {{abbreviations: string[], newlineBeforeCapsAssumesBadSentenceEnd: boolean}} */{
abbreviations = [],
newlineBeforeCapsAssumesBadSentenceEnd = false
} = context.options[0] || {};
const abbreviationsRegex = abbreviations.length ? new RegExp('\\b' + abbreviations.map(abbreviation => {
return (0, _escapeStringRegexp.default)(abbreviation.replaceAll(/\.$/ug, '') + '.');
}).join('|') + '(?:$|\\s)', 'gu') : '';
let {
description
} = utils.getDescription();
const indices = [...description.matchAll(/```[\s\S]*```/gu)].map(match => {
const {
index
} = match;
const [{
length
}] = match;
return {
index,
length
};
}).reverse();
for (const {
index,
length
} of indices) {
description = description.slice(0, index) + description.slice( /** @type {import('../iterateJsdoc.js').Integer} */index + length);
}
if (validateDescription(description, report, jsdocNode, abbreviationsRegex, sourceCode, {
line: jsdoc.source[0].number + 1
}, newlineBeforeCapsAssumesBadSentenceEnd)) {
return;
}
utils.forEachPreferredTag('description', matchingJsdocTag => {
const desc = `${matchingJsdocTag.name} ${utils.getTagDescription(matchingJsdocTag)}`.trim();
validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, matchingJsdocTag, newlineBeforeCapsAssumesBadSentenceEnd);
}, true);
const {
tagsWithNames
} = utils.getTagsByType(jsdoc.tags);
const tagsWithoutNames = utils.filterTags(({
tag: tagName
}) => {
return otherDescriptiveTags.has(tagName) || utils.hasOptionTag(tagName) && !tagsWithNames.some(({
tag
}) => {
// If user accidentally adds tags with names (or like `returns`
// get parsed as having names), do not add to this list
return tag === tagName;
});
});
tagsWithNames.some(tag => {
const desc = /** @type {string} */utils.getTagDescription(tag).replace(/^- /u, '').trimEnd();
return validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd);
});
tagsWithoutNames.some(tag => {
const desc = `${tag.name} ${utils.getTagDescription(tag)}`.trim();
return validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd);
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires that block description, explicit `@description`, and `@param`/`@returns` tag descriptions are written in complete sentences.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-description-complete-sentence.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
abbreviations: {
items: {
type: 'string'
},
type: 'array'
},
newlineBeforeCapsAssumesBadSentenceEnd: {
type: 'boolean'
},
tags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireDescriptionCompleteSentence.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,108 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
utils
}) => {
if (utils.avoidDocs()) {
return;
}
const {
enableFixer = true,
exemptNoArguments = false
} = context.options[0] || {};
const targetTagName = 'example';
const functionExamples = jsdoc.tags.filter(({
tag
}) => {
return tag === targetTagName;
});
if (!functionExamples.length) {
if (exemptNoArguments && utils.isIteratingFunction() && !utils.hasParams()) {
return;
}
utils.reportJSDoc(`Missing JSDoc @${targetTagName} declaration.`, null, () => {
if (enableFixer) {
utils.addTag(targetTagName);
}
});
return;
}
for (const example of functionExamples) {
const exampleContent = `${example.name} ${utils.getTagDescription(example)}`.trim().split('\n').filter(Boolean);
if (!exampleContent.length) {
report(`Missing JSDoc @${targetTagName} description.`, null, example);
}
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that all functions have examples.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-example.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
checkConstructors: {
default: true,
type: 'boolean'
},
checkGetters: {
default: false,
type: 'boolean'
},
checkSetters: {
default: false,
type: 'boolean'
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
default: true,
type: 'boolean'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
},
exemptNoArguments: {
default: false,
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireExample.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,135 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const defaultTags = {
file: {
initialCommentsOnly: true,
mustExist: true,
preventDuplicates: true
}
};
/**
* @param {import('../iterateJsdoc.js').StateObject} state
* @returns {void}
*/
const setDefaults = state => {
// First iteration
if (!state.globalTags) {
state.globalTags = {};
state.hasDuplicates = {};
state.hasTag = {};
state.hasNonCommentBeforeTag = {};
}
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdocNode,
state,
utils,
context
}) => {
const {
tags = defaultTags
} = context.options[0] || {};
setDefaults(state);
for (const tagName of Object.keys(tags)) {
const targetTagName = /** @type {string} */utils.getPreferredTagName({
tagName
});
const hasTag = Boolean(targetTagName && utils.hasTag(targetTagName));
state.hasTag[tagName] = hasTag || state.hasTag[tagName];
const hasDuplicate = state.hasDuplicates[tagName];
if (hasDuplicate === false) {
// Was marked before, so if a tag now, is a dupe
state.hasDuplicates[tagName] = hasTag;
} else if (!hasDuplicate && hasTag) {
// No dupes set before, but has first tag, so change state
// from `undefined` to `false` so can detect next time
state.hasDuplicates[tagName] = false;
state.hasNonCommentBeforeTag[tagName] = state.hasNonComment && state.hasNonComment < jsdocNode.range[0];
}
}
}, {
exit({
context,
state,
utils
}) {
setDefaults(state);
const {
tags = defaultTags
} = context.options[0] || {};
for (const [tagName, {
mustExist = false,
preventDuplicates = false,
initialCommentsOnly = false
}] of Object.entries(tags)) {
const obj = utils.getPreferredTagNameObject({
tagName
});
if (obj && typeof obj === 'object' && 'blocked' in obj) {
utils.reportSettings(`\`settings.jsdoc.tagNamePreference\` cannot block @${obj.tagName} ` + 'for the `require-file-overview` rule');
} else {
const targetTagName = obj && typeof obj === 'object' && obj.replacement || obj;
if (mustExist && !state.hasTag[tagName]) {
utils.reportSettings(`Missing @${targetTagName}`);
}
if (preventDuplicates && state.hasDuplicates[tagName]) {
utils.reportSettings(`Duplicate @${targetTagName}`);
}
if (initialCommentsOnly && state.hasNonCommentBeforeTag[tagName]) {
utils.reportSettings(`@${targetTagName} should be at the beginning of the file`);
}
}
}
},
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that all files have one `@file`, `@fileoverview`, or `@overview` tag at the beginning of the file.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-file-overview.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
tags: {
patternProperties: {
'.*': {
additionalProperties: false,
properties: {
initialCommentsOnly: {
type: 'boolean'
},
mustExist: {
type: 'boolean'
},
preventDuplicates: {
type: 'boolean'
}
},
type: 'object'
}
},
type: 'object'
}
},
type: 'object'
}],
type: 'suggestion'
},
nonComment({
state,
node
}) {
if (!state.hasNonComment) {
state.hasNonComment = node.range[0];
}
}
});
module.exports = exports.default;
//# sourceMappingURL=requireFileOverview.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,141 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
sourceCode,
utils,
report,
context,
jsdoc,
jsdocNode
}) => {
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*-/u.test(desc);
if (always) {
if (!startsWithHyphen) {
report(`There must be a hyphen before @${targetTagName} description.`, fixer => {
const lineIndex = /** @type {import('../iterateJsdoc.js').Integer} */
jsdocTag.line;
const sourceLines = sourceCode.getText(jsdocNode).split('\n');
// Get start index of description, accounting for multi-line descriptions
const description = desc.split('\n')[0];
const descriptionIndex = sourceLines[lineIndex].lastIndexOf(description);
const replacementLine = sourceLines[lineIndex].slice(0, descriptionIndex) + '- ' + description;
sourceLines.splice(lineIndex, 1, replacementLine);
const replacement = sourceLines.join('\n');
return fixer.replaceText(jsdocNode, replacement);
}, jsdocTag);
}
} else if (startsWithHyphen) {
let lines = 0;
for (const {
tokens
} of jsdocTag.source) {
if (tokens.description) {
break;
}
lines++;
}
utils.reportJSDoc(`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*/u, '');
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.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-hyphen-before-param-description.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
enum: ['always', 'never'],
type: 'string'
}, {
additionalProperties: false,
properties: {
tags: {
anyOf: [{
patternProperties: {
'.*': {
enum: ['always', 'never'],
type: 'string'
}
},
type: 'object'
}, {
enum: ['any'],
type: 'string'
}]
}
},
type: 'object'
}],
type: 'layout'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireHyphenBeforeParamDescription.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,507 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _exportParser = _interopRequireDefault(require("../exportParser.cjs"));
var _iterateJsdoc = require("../iterateJsdoc.cjs");
var _jsdocUtils = require("../jsdocUtils.cjs");
var _jsdoccomment = require("@es-joy/jsdoccomment");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @typedef {{
* ancestorsOnly: boolean,
* esm: boolean,
* initModuleExports: boolean,
* initWindow: boolean
* }} RequireJsdocOpts
*/
/**
* @typedef {import('eslint').Rule.Node|
* import('@typescript-eslint/types').TSESTree.Node} ESLintOrTSNode
*/
/** @type {import('json-schema').JSONSchema4} */
const OPTIONS_SCHEMA = {
additionalProperties: false,
properties: {
checkConstructors: {
default: true,
type: 'boolean'
},
checkGetters: {
anyOf: [{
type: 'boolean'
}, {
enum: ['no-setter'],
type: 'string'
}],
default: true
},
checkSetters: {
anyOf: [{
type: 'boolean'
}, {
enum: ['no-getter'],
type: 'string'
}],
default: true
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
context: {
type: 'string'
},
inlineCommentBlock: {
type: 'boolean'
},
minLineCount: {
type: 'integer'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
default: true,
type: 'boolean'
},
exemptEmptyConstructors: {
default: false,
type: 'boolean'
},
exemptEmptyFunctions: {
default: false,
type: 'boolean'
},
fixerMessage: {
default: '',
type: 'string'
},
minLineCount: {
type: 'integer'
},
publicOnly: {
oneOf: [{
default: false,
type: 'boolean'
}, {
additionalProperties: false,
default: {},
properties: {
ancestorsOnly: {
type: 'boolean'
},
cjs: {
type: 'boolean'
},
esm: {
type: 'boolean'
},
window: {
type: 'boolean'
}
},
type: 'object'
}]
},
require: {
additionalProperties: false,
default: {},
properties: {
ArrowFunctionExpression: {
default: false,
type: 'boolean'
},
ClassDeclaration: {
default: false,
type: 'boolean'
},
ClassExpression: {
default: false,
type: 'boolean'
},
FunctionDeclaration: {
default: true,
type: 'boolean'
},
FunctionExpression: {
default: false,
type: 'boolean'
},
MethodDefinition: {
default: false,
type: 'boolean'
}
},
type: 'object'
}
},
type: 'object'
};
/**
* @param {import('eslint').Rule.RuleContext} context
* @param {import('json-schema').JSONSchema4Object} baseObject
* @param {string} option
* @param {string} key
* @returns {boolean|undefined}
*/
const getOption = (context, baseObject, option, key) => {
if (context.options[0] && option in context.options[0] && (
// Todo: boolean shouldn't be returning property, but
// tests currently require
typeof context.options[0][option] === 'boolean' || key in context.options[0][option])) {
return context.options[0][option][key];
}
return /** @type {{[key: string]: {default?: boolean|undefined}}} */baseObject.properties[key].default;
};
/**
* @param {import('eslint').Rule.RuleContext} context
* @param {import('../iterateJsdoc.js').Settings} settings
* @returns {{
* contexts: (string|{
* context: string,
* inlineCommentBlock: boolean,
* minLineCount: import('../iterateJsdoc.js').Integer
* })[],
* enableFixer: boolean,
* exemptEmptyConstructors: boolean,
* exemptEmptyFunctions: boolean,
* fixerMessage: string,
* minLineCount: undefined|import('../iterateJsdoc.js').Integer,
* publicOnly: boolean|{[key: string]: boolean|undefined}
* require: {[key: string]: boolean|undefined}
* }}
*/
const getOptions = (context, settings) => {
const {
publicOnly,
contexts = settings.contexts || [],
exemptEmptyConstructors = true,
exemptEmptyFunctions = false,
enableFixer = true,
fixerMessage = '',
minLineCount = undefined
} = context.options[0] || {};
return {
contexts,
enableFixer,
exemptEmptyConstructors,
exemptEmptyFunctions,
fixerMessage,
minLineCount,
publicOnly: (baseObj => {
if (!publicOnly) {
return false;
}
/** @type {{[key: string]: boolean|undefined}} */
const properties = {};
for (const prop of Object.keys( /** @type {import('json-schema').JSONSchema4Object} */
/** @type {import('json-schema').JSONSchema4Object} */baseObj.properties)) {
const opt = getOption(context, /** @type {import('json-schema').JSONSchema4Object} */baseObj, 'publicOnly', prop);
properties[prop] = opt;
}
return properties;
})( /** @type {import('json-schema').JSONSchema4Object} */
( /** @type {import('json-schema').JSONSchema4Object} */
( /** @type {import('json-schema').JSONSchema4Object} */
OPTIONS_SCHEMA.properties.publicOnly).oneOf)[1]),
require: (baseObj => {
/** @type {{[key: string]: boolean|undefined}} */
const properties = {};
for (const prop of Object.keys( /** @type {import('json-schema').JSONSchema4Object} */
/** @type {import('json-schema').JSONSchema4Object} */baseObj.properties)) {
const opt = getOption(context, /** @type {import('json-schema').JSONSchema4Object} */
baseObj, 'require', prop);
properties[prop] = opt;
}
return properties;
})( /** @type {import('json-schema').JSONSchema4Object} */
OPTIONS_SCHEMA.properties.require)
};
};
/** @type {import('eslint').Rule.RuleModule} */
var _default = exports.default = {
create(context) {
/* c8 ignore next -- Fallback to deprecated method */
const {
sourceCode = context.getSourceCode()
} = context;
const settings = (0, _iterateJsdoc.getSettings)(context);
if (!settings) {
return {};
}
const opts = getOptions(context, settings);
const {
require: requireOption,
contexts,
exemptEmptyFunctions,
exemptEmptyConstructors,
enableFixer,
fixerMessage,
minLineCount
} = opts;
const publicOnly =
/**
* @type {{
* [key: string]: boolean | undefined;
* }}
*/
opts.publicOnly;
/**
* @type {import('../iterateJsdoc.js').CheckJsdoc}
*/
const checkJsDoc = (info, _handler, node) => {
if (
// Optimize
minLineCount !== undefined || contexts.some(ctxt => {
if (typeof ctxt === 'string') {
return false;
}
const {
minLineCount: count
} = ctxt;
return count !== undefined;
})) {
/**
* @param {undefined|import('../iterateJsdoc.js').Integer} count
*/
const underMinLine = count => {
var _sourceCode$getText$m;
return count !== undefined && count > (((_sourceCode$getText$m = sourceCode.getText(node).match(/\n/gu)) === null || _sourceCode$getText$m === void 0 ? void 0 : _sourceCode$getText$m.length) ?? 0) + 1;
};
if (underMinLine(minLineCount)) {
return;
}
const {
minLineCount: contextMinLineCount
} =
/**
* @type {{
* context: string;
* inlineCommentBlock: boolean;
* minLineCount: number;
* }}
*/
contexts.find(ctxt => {
if (typeof ctxt === 'string') {
return false;
}
const {
context: ctx
} = ctxt;
return ctx === (info.selector || node.type);
}) || {};
if (underMinLine(contextMinLineCount)) {
return;
}
}
const jsDocNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, node, settings);
if (jsDocNode) {
return;
}
// For those who have options configured against ANY constructors (or
// setters or getters) being reported
if ((0, _jsdocUtils.exemptSpeciaMethods)({
description: '',
inlineTags: [],
problems: [],
source: [],
tags: []
}, node, context, [OPTIONS_SCHEMA])) {
return;
}
if (
// Avoid reporting param-less, return-less functions (when
// `exemptEmptyFunctions` option is set)
exemptEmptyFunctions && info.isFunctionContext ||
// Avoid reporting param-less, return-less constructor methods (when
// `exemptEmptyConstructors` option is set)
exemptEmptyConstructors && (0, _jsdocUtils.isConstructor)(node)) {
const functionParameterNames = (0, _jsdocUtils.getFunctionParameterNames)(node);
if (!functionParameterNames.length && !(0, _jsdocUtils.hasReturnValue)(node)) {
return;
}
}
const fix = /** @type {import('eslint').Rule.ReportFixer} */fixer => {
// Default to one line break if the `minLines`/`maxLines` settings allow
const lines = settings.minLines === 0 && settings.maxLines >= 1 ? 1 : settings.minLines;
/** @type {ESLintOrTSNode|import('@typescript-eslint/types').TSESTree.Decorator} */
let baseNode = (0, _jsdoccomment.getReducedASTNode)(node, sourceCode);
const decorator = (0, _jsdoccomment.getDecorator)( /** @type {import('eslint').Rule.Node} */
baseNode);
if (decorator) {
baseNode = decorator;
}
const indent = (0, _jsdocUtils.getIndent)({
text: sourceCode.getText( /** @type {import('eslint').Rule.Node} */baseNode, /** @type {import('eslint').AST.SourceLocation} */
( /** @type {import('eslint').Rule.Node} */baseNode.loc).start.column)
});
const {
inlineCommentBlock
} =
/**
* @type {{
* context: string,
* inlineCommentBlock: boolean,
* minLineCount: import('../iterateJsdoc.js').Integer
* }}
*/
contexts.find(contxt => {
if (typeof contxt === 'string') {
return false;
}
const {
context: ctxt
} = contxt;
return ctxt === node.type;
}) || {};
const insertion = (inlineCommentBlock ? `/** ${fixerMessage}` : `/**\n${indent}*${fixerMessage}\n${indent}`) + `*/${'\n'.repeat(lines)}${indent.slice(0, -1)}`;
return fixer.insertTextBefore( /** @type {import('eslint').Rule.Node} */
baseNode, insertion);
};
const report = () => {
const {
start
} = /** @type {import('eslint').AST.SourceLocation} */node.loc;
const loc = {
end: {
column: 0,
line: start.line + 1
},
start
};
context.report({
fix: enableFixer ? fix : null,
loc,
messageId: 'missingJsDoc',
node
});
};
if (publicOnly) {
/** @type {RequireJsdocOpts} */
const opt = {
ancestorsOnly: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.ancestorsOnly) ?? false),
esm: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.esm) ?? true),
initModuleExports: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.cjs) ?? true),
initWindow: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.window) ?? false)
};
const exported = _exportParser.default.isUncommentedExport(node, sourceCode, opt, settings);
if (exported) {
report();
}
} else {
report();
}
};
/**
* @param {string} prop
* @returns {boolean}
*/
const hasOption = prop => {
return requireOption[prop] || contexts.some(ctxt => {
return typeof ctxt === 'object' ? ctxt.context === prop : ctxt === prop;
});
};
return {
...(0, _jsdocUtils.getContextObject)((0, _jsdocUtils.enforcedContexts)(context, [], settings), checkJsDoc),
ArrowFunctionExpression(node) {
if (!hasOption('ArrowFunctionExpression')) {
return;
}
if (['VariableDeclarator', 'AssignmentExpression', 'ExportDefaultDeclaration'].includes(node.parent.type) || ['Property', 'ObjectProperty', 'ClassProperty', 'PropertyDefinition'].includes(node.parent.type) && node ===
/**
* @type {import('@typescript-eslint/types').TSESTree.Property|
* import('@typescript-eslint/types').TSESTree.PropertyDefinition
* }
*/
node.parent.value) {
checkJsDoc({
isFunctionContext: true
}, null, node);
}
},
ClassDeclaration(node) {
if (!hasOption('ClassDeclaration')) {
return;
}
checkJsDoc({
isFunctionContext: false
}, null, node);
},
ClassExpression(node) {
if (!hasOption('ClassExpression')) {
return;
}
checkJsDoc({
isFunctionContext: false
}, null, node);
},
FunctionDeclaration(node) {
if (!hasOption('FunctionDeclaration')) {
return;
}
checkJsDoc({
isFunctionContext: true
}, null, node);
},
FunctionExpression(node) {
if (!hasOption('FunctionExpression')) {
return;
}
if (['VariableDeclarator', 'AssignmentExpression', 'ExportDefaultDeclaration'].includes(node.parent.type) || ['Property', 'ObjectProperty', 'ClassProperty', 'PropertyDefinition'].includes(node.parent.type) && node ===
/**
* @type {import('@typescript-eslint/types').TSESTree.Property|
* import('@typescript-eslint/types').TSESTree.PropertyDefinition
* }
*/
node.parent.value) {
checkJsDoc({
isFunctionContext: true
}, null, node);
}
},
MethodDefinition(node) {
if (!hasOption('MethodDefinition')) {
return;
}
checkJsDoc({
isFunctionContext: true,
selector: 'MethodDefinition'
}, null, /** @type {import('eslint').Rule.Node} */node.value);
}
};
},
meta: {
docs: {
category: 'Stylistic Issues',
description: 'Require JSDoc comments',
recommended: true,
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-jsdoc.md#repos-sticky-header'
},
fixable: 'code',
messages: {
missingJsDoc: 'Missing JSDoc comment.'
},
schema: [OPTIONS_SCHEMA],
type: 'suggestion'
}
};
module.exports = exports.default;
//# sourceMappingURL=requireJsdoc.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,527 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @typedef {[string, boolean, () => RootNamerReturn]} RootNamerReturn
*/
/**
* @param {string[]} desiredRoots
* @param {number} currentIndex
* @returns {RootNamerReturn}
*/
const rootNamer = (desiredRoots, currentIndex) => {
/** @type {string} */
let name;
let idx = currentIndex;
const incremented = desiredRoots.length <= 1;
if (incremented) {
const base = desiredRoots[0];
const suffix = idx++;
name = `${base}${suffix}`;
} else {
name = /** @type {string} */desiredRoots.shift();
}
return [name, incremented, () => {
return rootNamer(desiredRoots, idx);
}];
};
/* eslint-disable complexity -- Temporary */
var _default = exports.default = (0, _iterateJsdoc.default)(({
jsdoc,
utils,
context
}) => {
/* eslint-enable complexity -- Temporary */
if (utils.avoidDocs()) {
return;
}
// Param type is specified by type in @type
if (utils.hasTag('type')) {
return;
}
const {
autoIncrementBase = 0,
checkRestProperty = false,
checkDestructured = true,
checkDestructuredRoots = true,
checkTypesPattern = '/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/',
enableFixer = true,
enableRootFixer = true,
enableRestElementFixer = true,
unnamedRootBase = ['root'],
useDefaultObjectProperties = false
} = context.options[0] || {};
const preferredTagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'param'
});
if (!preferredTagName) {
return;
}
const functionParameterNames = utils.getFunctionParameterNames(useDefaultObjectProperties);
if (!functionParameterNames.length) {
return;
}
const jsdocParameterNames =
/**
* @type {{
* idx: import('../iterateJsdoc.js').Integer;
* name: string;
* type: string;
* }[]}
*/
utils.getJsdocTagsDeep(preferredTagName);
const shallowJsdocParameterNames = jsdocParameterNames.filter(tag => {
return !tag.name.includes('.');
}).map((tag, idx) => {
return {
...tag,
idx
};
});
const checkTypesRegex = utils.getRegexFromString(checkTypesPattern);
/**
* @type {{
* functionParameterIdx: import('../iterateJsdoc.js').Integer,
* functionParameterName: string,
* inc: boolean|undefined,
* remove?: true,
* type?: string|undefined
* }[]}
*/
const missingTags = [];
const flattenedRoots = utils.flattenRoots(functionParameterNames).names;
/**
* @type {{
* [key: string]: import('../iterateJsdoc.js').Integer
* }}
*/
const paramIndex = {};
/**
* @param {string} cur
* @returns {boolean}
*/
const hasParamIndex = cur => {
return utils.dropPathSegmentQuotes(String(cur)) in paramIndex;
};
/**
*
* @param {string|number|undefined} cur
* @returns {import('../iterateJsdoc.js').Integer}
*/
const getParamIndex = cur => {
return paramIndex[utils.dropPathSegmentQuotes(String(cur))];
};
/**
*
* @param {string} cur
* @param {import('../iterateJsdoc.js').Integer} idx
* @returns {void}
*/
const setParamIndex = (cur, idx) => {
paramIndex[utils.dropPathSegmentQuotes(String(cur))] = idx;
};
for (const [idx, cur] of flattenedRoots.entries()) {
setParamIndex(cur, idx);
}
/**
*
* @param {(import('@es-joy/jsdoccomment').JsdocTagWithInline & {
* newAdd?: boolean
* })[]} jsdocTags
* @param {import('../iterateJsdoc.js').Integer} indexAtFunctionParams
* @returns {import('../iterateJsdoc.js').Integer}
*/
const findExpectedIndex = (jsdocTags, indexAtFunctionParams) => {
const remainingRoots = functionParameterNames.slice(indexAtFunctionParams || 0);
const foundIndex = jsdocTags.findIndex(({
name,
newAdd
}) => {
return !newAdd && remainingRoots.some(remainingRoot => {
if (Array.isArray(remainingRoot)) {
return (
/**
* @type {import('../jsdocUtils.js').FlattendRootInfo & {
* annotationParamName?: string|undefined;
* }}
*/
remainingRoot[1].names.includes(name)
);
}
if (typeof remainingRoot === 'object') {
return name === remainingRoot.name;
}
return name === remainingRoot;
});
});
const tags = foundIndex > -1 ? jsdocTags.slice(0, foundIndex) : jsdocTags.filter(({
tag
}) => {
return tag === preferredTagName;
});
let tagLineCount = 0;
for (const {
source
} of tags) {
for (const {
tokens: {
end
}
} of source) {
if (!end) {
tagLineCount++;
}
}
}
return tagLineCount;
};
let [nextRootName, incremented, namer] = rootNamer([...unnamedRootBase], autoIncrementBase);
const thisOffset = functionParameterNames[0] === 'this' ? 1 : 0;
for (const [functionParameterIdx, functionParameterName] of functionParameterNames.entries()) {
let inc;
if (Array.isArray(functionParameterName)) {
const matchedJsdoc = shallowJsdocParameterNames[functionParameterIdx - thisOffset];
/** @type {string} */
let rootName;
if (functionParameterName[0]) {
rootName = functionParameterName[0];
} else if (matchedJsdoc && matchedJsdoc.name) {
rootName = matchedJsdoc.name;
if (matchedJsdoc.type && matchedJsdoc.type.search(checkTypesRegex) === -1) {
continue;
}
} else {
rootName = nextRootName;
inc = incremented;
}
[nextRootName, incremented, namer] = namer();
const {
hasRestElement,
hasPropertyRest,
rests,
names
} =
/**
* @type {import('../jsdocUtils.js').FlattendRootInfo & {
* annotationParamName?: string | undefined;
* }}
*/
functionParameterName[1];
const notCheckingNames = [];
if (!enableRestElementFixer && hasRestElement) {
continue;
}
if (!checkDestructuredRoots) {
continue;
}
for (const [idx, paramName] of names.entries()) {
// Add root if the root name is not in the docs (and is not already
// in the tags to be fixed)
if (!jsdocParameterNames.find(({
name
}) => {
return name === rootName;
}) && !missingTags.find(({
functionParameterName: fpn
}) => {
return fpn === rootName;
})) {
const emptyParamIdx = jsdocParameterNames.findIndex(({
name
}) => {
return !name;
});
if (emptyParamIdx > -1) {
missingTags.push({
functionParameterIdx: emptyParamIdx,
functionParameterName: rootName,
inc,
remove: true
});
} else {
missingTags.push({
functionParameterIdx: hasParamIndex(rootName) ? getParamIndex(rootName) : getParamIndex(paramName),
functionParameterName: rootName,
inc
});
}
}
if (!checkDestructured) {
continue;
}
if (!checkRestProperty && rests[idx]) {
continue;
}
const fullParamName = `${rootName}.${paramName}`;
const notCheckingName = jsdocParameterNames.find(({
name,
type: paramType
}) => {
return utils.comparePaths(name)(fullParamName) && paramType.search(checkTypesRegex) === -1 && paramType !== '';
});
if (notCheckingName !== undefined) {
notCheckingNames.push(notCheckingName.name);
}
if (notCheckingNames.find(name => {
return fullParamName.startsWith(name);
})) {
continue;
}
if (jsdocParameterNames && !jsdocParameterNames.find(({
name
}) => {
return utils.comparePaths(name)(fullParamName);
})) {
missingTags.push({
functionParameterIdx: getParamIndex(functionParameterName[0] ? fullParamName : paramName),
functionParameterName: fullParamName,
inc,
type: hasRestElement && !hasPropertyRest ? '{...any}' : undefined
});
}
}
continue;
}
/** @type {string} */
let funcParamName;
let type;
if (typeof functionParameterName === 'object') {
if (!enableRestElementFixer && functionParameterName.restElement) {
continue;
}
funcParamName = /** @type {string} */functionParameterName.name;
type = '{...any}';
} else {
funcParamName = /** @type {string} */functionParameterName;
}
if (jsdocParameterNames && !jsdocParameterNames.find(({
name
}) => {
return name === funcParamName;
}) && funcParamName !== 'this') {
missingTags.push({
functionParameterIdx: getParamIndex(funcParamName),
functionParameterName: funcParamName,
inc,
type
});
}
}
/**
*
* @param {{
* functionParameterIdx: import('../iterateJsdoc.js').Integer,
* functionParameterName: string,
* remove?: true,
* inc?: boolean,
* type?: string
* }} cfg
*/
const fix = ({
functionParameterIdx,
functionParameterName,
remove,
inc,
type
}) => {
if (inc && !enableRootFixer) {
return;
}
/**
*
* @param {import('../iterateJsdoc.js').Integer} tagIndex
* @param {import('../iterateJsdoc.js').Integer} sourceIndex
* @param {import('../iterateJsdoc.js').Integer} spliceCount
* @returns {void}
*/
const createTokens = (tagIndex, sourceIndex, spliceCount) => {
// console.log(sourceIndex, tagIndex, jsdoc.tags, jsdoc.source);
const tokens = {
number: sourceIndex + 1,
source: '',
tokens: {
delimiter: '*',
description: '',
end: '',
lineEnd: '',
name: functionParameterName,
newAdd: true,
postDelimiter: ' ',
postName: '',
postTag: ' ',
postType: type ? ' ' : '',
start: jsdoc.source[sourceIndex].tokens.start,
tag: `@${preferredTagName}`,
type: type ?? ''
}
};
/**
* @type {(import('@es-joy/jsdoccomment').JsdocTagWithInline & {
* newAdd?: true
* })[]}
*/
jsdoc.tags.splice(tagIndex, spliceCount, {
description: '',
inlineTags: [],
name: functionParameterName,
newAdd: true,
optional: false,
problems: [],
source: [tokens],
tag: preferredTagName,
type: type ?? ''
});
const firstNumber = jsdoc.source[0].number;
jsdoc.source.splice(sourceIndex, spliceCount, tokens);
for (const [idx, src] of jsdoc.source.slice(sourceIndex).entries()) {
src.number = firstNumber + sourceIndex + idx;
}
};
const offset = jsdoc.source.findIndex(({
tokens: {
tag,
end
}
}) => {
return tag || end;
});
if (remove) {
createTokens(functionParameterIdx, offset + functionParameterIdx, 1);
} else {
const expectedIdx = findExpectedIndex(jsdoc.tags, functionParameterIdx);
createTokens(expectedIdx, offset + expectedIdx, 0);
}
};
/**
* @returns {void}
*/
const fixer = () => {
for (const missingTag of missingTags) {
fix(missingTag);
}
};
if (missingTags.length && jsdoc.source.length === 1) {
utils.makeMultiline();
}
for (const {
functionParameterName
} of missingTags) {
utils.reportJSDoc(`Missing JSDoc @${preferredTagName} "${functionParameterName}" declaration.`, null, enableFixer ? fixer : null);
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that all function parameters are documented.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
autoIncrementBase: {
default: 0,
type: 'integer'
},
checkConstructors: {
default: true,
type: 'boolean'
},
checkDestructured: {
default: true,
type: 'boolean'
},
checkDestructuredRoots: {
default: true,
type: 'boolean'
},
checkGetters: {
default: false,
type: 'boolean'
},
checkRestProperty: {
default: false,
type: 'boolean'
},
checkSetters: {
default: false,
type: 'boolean'
},
checkTypesPattern: {
type: 'string'
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
type: 'boolean'
},
enableRestElementFixer: {
type: 'boolean'
},
enableRootFixer: {
type: 'boolean'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
},
unnamedRootBase: {
items: {
type: 'string'
},
type: 'array'
},
useDefaultObjectProperties: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
},
// We cannot cache comment nodes as the contexts may recur with the
// same comment node but a different JS node, and we may need the different
// JS node to ensure we iterate its context
noTracking: true
});
module.exports = exports.default;
//# sourceMappingURL=requireParam.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,84 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
report,
settings,
utils
}) => {
const {
defaultDestructuredRootDescription = 'The root object',
setDefaultDestructuredRootDescription = false
} = context.options[0] || {};
const functionParameterNames = utils.getFunctionParameterNames();
let rootCount = -1;
utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {
rootCount += jsdocParameter.name.includes('.') ? 0 : 1;
if (!jsdocParameter.description.trim()) {
if (Array.isArray(functionParameterNames[rootCount])) {
if (settings.exemptDestructuredRootsFromChecks) {
return;
}
if (setDefaultDestructuredRootDescription) {
utils.reportJSDoc(`Missing root description for @${targetTagName}.`, jsdocParameter, () => {
utils.changeTag(jsdocParameter, {
description: defaultDestructuredRootDescription,
postName: ' '
});
});
return;
}
}
report(`Missing JSDoc @${targetTagName} "${jsdocParameter.name}" description.`, null, jsdocParameter);
}
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that each `@param` tag has a `description` value.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-description.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
defaultDestructuredRootDescription: {
type: 'string'
},
setDefaultDestructuredRootDescription: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireParamDescription.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {
if (jsdocParameter.tag && jsdocParameter.name === '') {
report(`There must be an identifier after @${targetTagName} ${jsdocParameter.type === '' ? 'type' : 'tag'}.`, null, jsdocParameter);
}
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that all function parameters have names.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-name.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireParamName.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"requireParamName.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","report","utils","forEachPreferredTag","jsdocParameter","targetTagName","tag","name","type","contextDefaults","meta","docs","description","url","schema","additionalProperties","properties","contexts","items","anyOf","comment","context","module"],"sources":["../../src/rules/requireParamName.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {\n if (jsdocParameter.tag && jsdocParameter.name === '') {\n report(\n `There must be an identifier after @${targetTagName} ${jsdocParameter.type === '' ? 'type' : 'tag'}.`,\n null,\n jsdocParameter,\n );\n }\n });\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'Requires that all function parameters have names.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-name.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJA,KAAK,CAACC,mBAAmB,CAAC,OAAO,EAAE,CAACC,cAAc,EAAEC,aAAa,KAAK;IACpE,IAAID,cAAc,CAACE,GAAG,IAAIF,cAAc,CAACG,IAAI,KAAK,EAAE,EAAE;MACpDN,MAAM,CACJ,sCAAsCI,aAAa,IAAID,cAAc,CAACI,IAAI,KAAK,EAAE,GAAG,MAAM,GAAG,KAAK,GAAG,EACrG,IAAI,EACJJ,cACF,CAAC;IACH;EACF,CAAC,CAAC;AACJ,CAAC,EAAE;EACDK,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,mDAAmD;MAChEC,GAAG,EAAE;IACP,CAAC;IACDC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEX,IAAI,EAAE;YACR,CAAC,EACD;cACEO,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVI,OAAO,EAAE;kBACPZ,IAAI,EAAE;gBACR,CAAC;gBACDa,OAAO,EAAE;kBACPb,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAc,MAAA,CAAAvB,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,84 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
report,
settings,
utils
}) => {
const {
defaultDestructuredRootType = 'object',
setDefaultDestructuredRootType = false
} = context.options[0] || {};
const functionParameterNames = utils.getFunctionParameterNames();
let rootCount = -1;
utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {
rootCount += jsdocParameter.name.includes('.') ? 0 : 1;
if (!jsdocParameter.type) {
if (Array.isArray(functionParameterNames[rootCount])) {
if (settings.exemptDestructuredRootsFromChecks) {
return;
}
if (setDefaultDestructuredRootType) {
utils.reportJSDoc(`Missing root type for @${targetTagName}.`, jsdocParameter, () => {
utils.changeTag(jsdocParameter, {
postType: ' ',
type: `{${defaultDestructuredRootType}}`
});
});
return;
}
}
report(`Missing JSDoc @${targetTagName} "${jsdocParameter.name}" type.`, null, jsdocParameter);
}
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that each `@param` tag has a `type` value.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-type.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
defaultDestructuredRootType: {
type: 'string'
},
setDefaultDestructuredRootType: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireParamType.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"requireParamType.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","context","report","settings","utils","defaultDestructuredRootType","setDefaultDestructuredRootType","options","functionParameterNames","getFunctionParameterNames","rootCount","forEachPreferredTag","jsdocParameter","targetTagName","name","includes","type","Array","isArray","exemptDestructuredRootsFromChecks","reportJSDoc","changeTag","postType","contextDefaults","meta","docs","description","url","fixable","schema","additionalProperties","properties","contexts","items","anyOf","comment","module"],"sources":["../../src/rules/requireParamType.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n context,\n report,\n settings,\n utils,\n}) => {\n const {\n defaultDestructuredRootType = 'object',\n setDefaultDestructuredRootType = false,\n } = context.options[0] || {};\n\n const functionParameterNames = utils.getFunctionParameterNames();\n\n let rootCount = -1;\n utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {\n rootCount += jsdocParameter.name.includes('.') ? 0 : 1;\n if (!jsdocParameter.type) {\n if (Array.isArray(functionParameterNames[rootCount])) {\n if (settings.exemptDestructuredRootsFromChecks) {\n return;\n }\n\n if (setDefaultDestructuredRootType) {\n utils.reportJSDoc(`Missing root type for @${targetTagName}.`, jsdocParameter, () => {\n utils.changeTag(jsdocParameter, {\n postType: ' ',\n type: `{${defaultDestructuredRootType}}`,\n });\n });\n return;\n }\n }\n\n report(\n `Missing JSDoc @${targetTagName} \"${jsdocParameter.name}\" type.`,\n null,\n jsdocParameter,\n );\n }\n });\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'Requires that each `@param` tag has a `type` value.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-param-type.md#repos-sticky-header',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n defaultDestructuredRootType: {\n type: 'string',\n },\n setDefaultDestructuredRootType: {\n type: 'boolean',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,OAAO;EACPC,MAAM;EACNC,QAAQ;EACRC;AACF,CAAC,KAAK;EACJ,MAAM;IACJC,2BAA2B,GAAG,QAAQ;IACtCC,8BAA8B,GAAG;EACnC,CAAC,GAAGL,OAAO,CAACM,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;EAE5B,MAAMC,sBAAsB,GAAGJ,KAAK,CAACK,yBAAyB,CAAC,CAAC;EAEhE,IAAIC,SAAS,GAAG,CAAC,CAAC;EAClBN,KAAK,CAACO,mBAAmB,CAAC,OAAO,EAAE,CAACC,cAAc,EAAEC,aAAa,KAAK;IACpEH,SAAS,IAAIE,cAAc,CAACE,IAAI,CAACC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;IACtD,IAAI,CAACH,cAAc,CAACI,IAAI,EAAE;MACxB,IAAIC,KAAK,CAACC,OAAO,CAACV,sBAAsB,CAACE,SAAS,CAAC,CAAC,EAAE;QACpD,IAAIP,QAAQ,CAACgB,iCAAiC,EAAE;UAC9C;QACF;QAEA,IAAIb,8BAA8B,EAAE;UAClCF,KAAK,CAACgB,WAAW,CAAC,0BAA0BP,aAAa,GAAG,EAAED,cAAc,EAAE,MAAM;YAClFR,KAAK,CAACiB,SAAS,CAACT,cAAc,EAAE;cAC9BU,QAAQ,EAAE,GAAG;cACbN,IAAI,EAAE,IAAIX,2BAA2B;YACvC,CAAC,CAAC;UACJ,CAAC,CAAC;UACF;QACF;MACF;MAEAH,MAAM,CACJ,kBAAkBW,aAAa,KAAKD,cAAc,CAACE,IAAI,SAAS,EAChE,IAAI,EACJF,cACF,CAAC;IACH;EACF,CAAC,CAAC;AACJ,CAAC,EAAE;EACDW,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,qDAAqD;MAClEC,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACElB,IAAI,EAAE;YACR,CAAC,EACD;cACEc,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVI,OAAO,EAAE;kBACPnB,IAAI,EAAE;gBACR,CAAC;gBACDf,OAAO,EAAE;kBACPe,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR,CAAC;QACDX,2BAA2B,EAAE;UAC3BW,IAAI,EAAE;QACR,CAAC;QACDV,8BAA8B,EAAE;UAC9BU,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAoB,MAAA,CAAArC,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
utils
}) => {
const propertyAssociatedTags = utils.filterTags(({
tag
}) => {
return ['typedef', 'namespace'].includes(tag);
});
if (!propertyAssociatedTags.length) {
return;
}
const targetTagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'property'
});
if (utils.hasATag([targetTagName])) {
return;
}
for (const propertyAssociatedTag of propertyAssociatedTags) {
if (!['object', 'Object', 'PlainObject'].includes(propertyAssociatedTag.type)) {
continue;
}
utils.reportJSDoc(`Missing JSDoc @${targetTagName}.`, null, () => {
utils.addTag(targetTagName);
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires that all `@typedef` and `@namespace` tags have `@property` when their type is a plain `object`, `Object`, or `PlainObject`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-property.md#repos-sticky-header'
},
fixable: 'code',
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireProperty.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"requireProperty.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","utils","propertyAssociatedTags","filterTags","tag","includes","length","targetTagName","getPreferredTagName","tagName","hasATag","propertyAssociatedTag","type","reportJSDoc","addTag","iterateAllJsdocs","meta","docs","description","url","fixable","module"],"sources":["../../src/rules/requireProperty.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n utils,\n}) => {\n const propertyAssociatedTags = utils.filterTags(({\n tag,\n }) => {\n return [\n 'typedef', 'namespace',\n ].includes(tag);\n });\n if (!propertyAssociatedTags.length) {\n return;\n }\n\n const targetTagName = /** @type {string} */ (utils.getPreferredTagName({\n tagName: 'property',\n }));\n\n if (utils.hasATag([\n targetTagName,\n ])) {\n return;\n }\n\n for (const propertyAssociatedTag of propertyAssociatedTags) {\n if (![\n 'object', 'Object', 'PlainObject',\n ].includes(propertyAssociatedTag.type)) {\n continue;\n }\n\n utils.reportJSDoc(`Missing JSDoc @${targetTagName}.`, null, () => {\n utils.addTag(targetTagName);\n });\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Requires that all `@typedef` and `@namespace` tags have `@property` when their type is a plain `object`, `Object`, or `PlainObject`.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-property.md#repos-sticky-header',\n },\n fixable: 'code',\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC;AACF,CAAC,KAAK;EACJ,MAAMC,sBAAsB,GAAGD,KAAK,CAACE,UAAU,CAAC,CAAC;IAC/CC;EACF,CAAC,KAAK;IACJ,OAAO,CACL,SAAS,EAAE,WAAW,CACvB,CAACC,QAAQ,CAACD,GAAG,CAAC;EACjB,CAAC,CAAC;EACF,IAAI,CAACF,sBAAsB,CAACI,MAAM,EAAE;IAClC;EACF;EAEA,MAAMC,aAAa,GAAG,qBAAuBN,KAAK,CAACO,mBAAmB,CAAC;IACrEC,OAAO,EAAE;EACX,CAAC,CAAE;EAEH,IAAIR,KAAK,CAACS,OAAO,CAAC,CAChBH,aAAa,CACd,CAAC,EAAE;IACF;EACF;EAEA,KAAK,MAAMI,qBAAqB,IAAIT,sBAAsB,EAAE;IAC1D,IAAI,CAAC,CACH,QAAQ,EAAE,QAAQ,EAAE,aAAa,CAClC,CAACG,QAAQ,CAACM,qBAAqB,CAACC,IAAI,CAAC,EAAE;MACtC;IACF;IAEAX,KAAK,CAACY,WAAW,CAAC,kBAAkBN,aAAa,GAAG,EAAE,IAAI,EAAE,MAAM;MAChEN,KAAK,CAACa,MAAM,CAACP,aAAa,CAAC;IAC7B,CAAC,CAAC;EACJ;AACF,CAAC,EAAE;EACDQ,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,sIAAsI;MACnJC,GAAG,EAAE;IACP,CAAC;IACDC,OAAO,EAAE,MAAM;IACfR,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAS,MAAA,CAAAtB,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('property', (jsdoc, targetTagName) => {
if (!jsdoc.description.trim()) {
report(`Missing JSDoc @${targetTagName} "${jsdoc.name}" description.`, null, jsdoc);
}
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires that each `@property` tag has a `description` value.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-property-description.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requirePropertyDescription.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"requirePropertyDescription.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","report","utils","forEachPreferredTag","jsdoc","targetTagName","description","trim","name","iterateAllJsdocs","meta","docs","url","type","module"],"sources":["../../src/rules/requirePropertyDescription.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('property', (jsdoc, targetTagName) => {\n if (!jsdoc.description.trim()) {\n report(\n `Missing JSDoc @${targetTagName} \"${jsdoc.name}\" description.`,\n null,\n jsdoc,\n );\n }\n });\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Requires that each `@property` tag has a `description` value.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-property-description.md#repos-sticky-header',\n },\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJA,KAAK,CAACC,mBAAmB,CAAC,UAAU,EAAE,CAACC,KAAK,EAAEC,aAAa,KAAK;IAC9D,IAAI,CAACD,KAAK,CAACE,WAAW,CAACC,IAAI,CAAC,CAAC,EAAE;MAC7BN,MAAM,CACJ,kBAAkBI,aAAa,KAAKD,KAAK,CAACI,IAAI,gBAAgB,EAC9D,IAAI,EACJJ,KACF,CAAC;IACH;EACF,CAAC,CAAC;AACJ,CAAC,EAAE;EACDK,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJL,WAAW,EAAE,+DAA+D;MAC5EM,GAAG,EAAE;IACP,CAAC;IACDC,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAC,MAAA,CAAAf,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('property', (jsdoc, targetTagName) => {
if (jsdoc.tag && jsdoc.name === '') {
report(`There must be an identifier after @${targetTagName} ${jsdoc.type === '' ? 'type' : 'tag'}.`, null, jsdoc);
}
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires that all function `@property` tags have names.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-property-name.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requirePropertyName.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"requirePropertyName.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","report","utils","forEachPreferredTag","jsdoc","targetTagName","tag","name","type","iterateAllJsdocs","meta","docs","description","url","module"],"sources":["../../src/rules/requirePropertyName.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('property', (jsdoc, targetTagName) => {\n if (jsdoc.tag && jsdoc.name === '') {\n report(\n `There must be an identifier after @${targetTagName} ${jsdoc.type === '' ? 'type' : 'tag'}.`,\n null,\n jsdoc,\n );\n }\n });\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Requires that all function `@property` tags have names.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-property-name.md#repos-sticky-header',\n },\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJA,KAAK,CAACC,mBAAmB,CAAC,UAAU,EAAE,CAACC,KAAK,EAAEC,aAAa,KAAK;IAC9D,IAAID,KAAK,CAACE,GAAG,IAAIF,KAAK,CAACG,IAAI,KAAK,EAAE,EAAE;MAClCN,MAAM,CACJ,sCAAsCI,aAAa,IAAID,KAAK,CAACI,IAAI,KAAK,EAAE,GAAG,MAAM,GAAG,KAAK,GAAG,EAC5F,IAAI,EACJJ,KACF,CAAC;IACH;EACF,CAAC,CAAC;AACJ,CAAC,EAAE;EACDK,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,yDAAyD;MACtEC,GAAG,EAAE;IACP,CAAC;IACDL,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAM,MAAA,CAAAf,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('property', (jsdoc, targetTagName) => {
if (!jsdoc.type) {
report(`Missing JSDoc @${targetTagName} "${jsdoc.name}" type.`, null, jsdoc);
}
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires that each `@property` tag has a `type` value.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-property-type.md#repos-sticky-header'
},
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requirePropertyType.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"requirePropertyType.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","report","utils","forEachPreferredTag","jsdoc","targetTagName","type","name","iterateAllJsdocs","meta","docs","description","url","module"],"sources":["../../src/rules/requirePropertyType.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('property', (jsdoc, targetTagName) => {\n if (!jsdoc.type) {\n report(\n `Missing JSDoc @${targetTagName} \"${jsdoc.name}\" type.`,\n null,\n jsdoc,\n );\n }\n });\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Requires that each `@property` tag has a `type` value.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-property-type.md#repos-sticky-header',\n },\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJA,KAAK,CAACC,mBAAmB,CAAC,UAAU,EAAE,CAACC,KAAK,EAAEC,aAAa,KAAK;IAC9D,IAAI,CAACD,KAAK,CAACE,IAAI,EAAE;MACfL,MAAM,CACJ,kBAAkBI,aAAa,KAAKD,KAAK,CAACG,IAAI,SAAS,EACvD,IAAI,EACJH,KACF,CAAC;IACH;EACF,CAAC,CAAC;AACJ,CAAC,EAAE;EACDI,gBAAgB,EAAE,IAAI;EACtBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,wDAAwD;MACrEC,GAAG,EAAE;IACP,CAAC;IACDN,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAO,MAAA,CAAAd,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,209 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _exportParser = _interopRequireDefault(require("../exportParser.cjs"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* We can skip checking for a return value, in case the documentation is inherited
* or the method is either a constructor or an abstract method.
*
* In either of these cases the return value is optional or not defined.
* @param {import('../iterateJsdoc.js').Utils} utils
* a reference to the utils which are used to probe if a tag is present or not.
* @returns {boolean}
* true in case deep checking can be skipped; otherwise false.
*/
const canSkip = utils => {
return utils.hasATag([
// inheritdoc implies that all documentation is inherited
// see https://jsdoc.app/tags-inheritdoc.html
//
// Abstract methods are by definition incomplete,
// so it is not an error if it declares a return value but does not implement it.
'abstract', 'virtual',
// Constructors do not have a return value by definition (https://jsdoc.app/tags-class.html)
// So we can bail out here, too.
'class', 'constructor',
// Return type is specified by type in @type
'type',
// This seems to imply a class as well
'interface']) || utils.avoidDocs();
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
info: {
comment
},
node,
report,
settings,
utils,
context
}) => {
const {
contexts,
enableFixer = false,
forceRequireReturn = false,
forceReturnsWithAsync = false,
publicOnly = false
} = context.options[0] || {};
// A preflight check. We do not need to run a deep check
// in case the @returns comment is optional or undefined.
if (canSkip(utils)) {
return;
}
/** @type {boolean|undefined} */
let forceRequireReturnContext;
if (contexts) {
const {
foundContext
} = utils.findContext(contexts, comment);
if (typeof foundContext === 'object') {
forceRequireReturnContext = foundContext.forceRequireReturn;
}
}
const tagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'returns'
});
if (!tagName) {
return;
}
const tags = utils.getTags(tagName);
if (tags.length > 1) {
report(`Found more than one @${tagName} declaration.`);
}
const iteratingFunction = utils.isIteratingFunction();
// In case the code returns something, we expect a return value in JSDoc.
const [tag] = tags;
const missingReturnTag = typeof tag === 'undefined' || tag === null;
const shouldReport = () => {
if (!missingReturnTag) {
return false;
}
if (publicOnly) {
/** @type {import('./requireJsdoc.js').RequireJsdocOpts} */
const opt = {
ancestorsOnly: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.ancestorsOnly) ?? false),
esm: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.esm) ?? true),
initModuleExports: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.cjs) ?? true),
initWindow: Boolean((publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.window) ?? false)
};
/* c8 ignore next -- Fallback to deprecated method */
const {
sourceCode = context.getSourceCode()
} = context;
const exported = _exportParser.default.isUncommentedExport( /** @type {import('eslint').Rule.Node} */node, sourceCode, opt, settings);
if (!exported) {
return false;
}
}
if ((forceRequireReturn || forceRequireReturnContext) && (iteratingFunction || utils.isVirtualFunction())) {
return true;
}
const isAsync = !iteratingFunction && utils.hasTag('async') || iteratingFunction && utils.isAsync();
if (forceReturnsWithAsync && isAsync) {
return true;
}
return iteratingFunction && utils.hasValueOrExecutorHasNonEmptyResolveValue(forceReturnsWithAsync);
};
if (shouldReport()) {
utils.reportJSDoc(`Missing JSDoc @${tagName} declaration.`, null, enableFixer ? () => {
utils.addTag(tagName);
} : null);
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that returns are documented.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-returns.md#repos-sticky-header'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
checkConstructors: {
default: false,
type: 'boolean'
},
checkGetters: {
default: true,
type: 'boolean'
},
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
},
forceRequireReturn: {
type: 'boolean'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
type: 'boolean'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
},
forceRequireReturn: {
default: false,
type: 'boolean'
},
forceReturnsWithAsync: {
default: false,
type: 'boolean'
},
publicOnly: {
oneOf: [{
default: false,
type: 'boolean'
}, {
additionalProperties: false,
default: {},
properties: {
ancestorsOnly: {
type: 'boolean'
},
cjs: {
type: 'boolean'
},
esm: {
type: 'boolean'
},
window: {
type: 'boolean'
}
},
type: 'object'
}]
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireReturns.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,109 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* @param {import('../iterateJsdoc.js').Utils} utils
* @param {import('../iterateJsdoc.js').Settings} settings
* @returns {boolean}
*/
const canSkip = (utils, settings) => {
const voidingTags = [
// An abstract function is by definition incomplete
// so it is perfectly fine if a return is documented but
// not present within the function.
// A subclass may inherit the doc and implement the
// missing return.
'abstract', 'virtual',
// A constructor function returns `this` by default, so may be `@returns`
// tag indicating this but no explicit return
'class', 'constructor', 'interface'];
if (settings.mode === 'closure') {
// Structural Interface in GCC terms, equivalent to @interface tag as far as this rule is concerned
voidingTags.push('record');
}
return utils.hasATag(voidingTags) || utils.isConstructor() || utils.classHasTag('interface') || settings.mode === 'closure' && utils.classHasTag('record');
};
// eslint-disable-next-line complexity -- Temporary
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
node,
report,
settings,
utils
}) => {
const {
exemptAsync = true,
exemptGenerators = settings.mode === 'typescript',
reportMissingReturnForUndefinedTypes = false
} = context.options[0] || {};
if (canSkip(utils, settings)) {
return;
}
if (exemptAsync && utils.isAsync()) {
return;
}
const tagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'returns'
});
if (!tagName) {
return;
}
const tags = utils.getTags(tagName);
if (tags.length === 0) {
return;
}
if (tags.length > 1) {
report(`Found more than one @${tagName} declaration.`);
return;
}
const [tag] = tags;
const type = tag.type.trim();
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions
if (/asserts\s/u.test(type)) {
return;
}
const returnNever = type === 'never';
if (returnNever && utils.hasValueOrExecutorHasNonEmptyResolveValue(false)) {
report(`JSDoc @${tagName} declaration set with "never" but return expression is present in function.`);
return;
}
// In case a return value is declared in JSDoc, we also expect one in the code.
if (!returnNever && (reportMissingReturnForUndefinedTypes || !utils.mayBeUndefinedTypeTag(tag)) && (tag.type === '' && !utils.hasValueOrExecutorHasNonEmptyResolveValue(exemptAsync) || tag.type !== '' && !utils.hasValueOrExecutorHasNonEmptyResolveValue(exemptAsync, true)) && Boolean(!exemptGenerators || !node || !('generator' in ( /** @type {import('../iterateJsdoc.js').Node} */node)) || !( /** @type {import('@typescript-eslint/types').TSESTree.FunctionDeclaration} */node).generator)) {
report(`JSDoc @${tagName} declaration present but return expression not available in function.`);
}
}, {
meta: {
docs: {
description: 'Requires a return statement in function body if a `@returns` tag is specified in jsdoc comment.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-returns-check.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
exemptAsync: {
default: true,
type: 'boolean'
},
exemptGenerators: {
type: 'boolean'
},
reportMissingReturnForUndefinedTypes: {
default: false,
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireReturnsCheck.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('returns', (jsdocTag, targetTagName) => {
const type = jsdocTag.type && jsdocTag.type.trim();
if (['void', 'undefined', 'Promise<void>', 'Promise<undefined>'].includes(type)) {
return;
}
if (!jsdocTag.description.trim()) {
report(`Missing JSDoc @${targetTagName} description.`, null, jsdocTag);
}
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that the `@returns` tag has a `description` value.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-returns-description.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireReturnsDescription.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"requireReturnsDescription.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","report","utils","forEachPreferredTag","jsdocTag","targetTagName","type","trim","includes","description","contextDefaults","meta","docs","url","schema","additionalProperties","properties","contexts","items","anyOf","comment","context","module"],"sources":["../../src/rules/requireReturnsDescription.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('returns', (jsdocTag, targetTagName) => {\n const type = jsdocTag.type && jsdocTag.type.trim();\n\n if ([\n 'void', 'undefined', 'Promise<void>', 'Promise<undefined>',\n ].includes(type)) {\n return;\n }\n\n if (!jsdocTag.description.trim()) {\n report(`Missing JSDoc @${targetTagName} description.`, null, jsdocTag);\n }\n });\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'Requires that the `@returns` tag has a `description` value.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-returns-description.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJA,KAAK,CAACC,mBAAmB,CAAC,SAAS,EAAE,CAACC,QAAQ,EAAEC,aAAa,KAAK;IAChE,MAAMC,IAAI,GAAGF,QAAQ,CAACE,IAAI,IAAIF,QAAQ,CAACE,IAAI,CAACC,IAAI,CAAC,CAAC;IAElD,IAAI,CACF,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,oBAAoB,CAC3D,CAACC,QAAQ,CAACF,IAAI,CAAC,EAAE;MAChB;IACF;IAEA,IAAI,CAACF,QAAQ,CAACK,WAAW,CAACF,IAAI,CAAC,CAAC,EAAE;MAChCN,MAAM,CAAC,kBAAkBI,aAAa,eAAe,EAAE,IAAI,EAAED,QAAQ,CAAC;IACxE;EACF,CAAC,CAAC;AACJ,CAAC,EAAE;EACDM,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJH,WAAW,EAAE,6DAA6D;MAC1EI,GAAG,EAAE;IACP,CAAC;IACDC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEb,IAAI,EAAE;YACR,CAAC,EACD;cACES,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVI,OAAO,EAAE;kBACPd,IAAI,EAAE;gBACR,CAAC;gBACDe,OAAO,EAAE;kBACPf,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAgB,MAAA,CAAAvB,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,54 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('returns', (jsdocTag, targetTagName) => {
if (!jsdocTag.type) {
report(`Missing JSDoc @${targetTagName} type.`, null, jsdocTag);
}
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that `@returns` tag has `type` value.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-returns-type.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireReturnsType.cjs.map

View File

@ -0,0 +1 @@
{"version":3,"file":"requireReturnsType.cjs","names":["_iterateJsdoc","_interopRequireDefault","require","e","__esModule","default","_default","exports","iterateJsdoc","report","utils","forEachPreferredTag","jsdocTag","targetTagName","type","contextDefaults","meta","docs","description","url","schema","additionalProperties","properties","contexts","items","anyOf","comment","context","module"],"sources":["../../src/rules/requireReturnsType.js"],"sourcesContent":["import iterateJsdoc from '../iterateJsdoc.js';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('returns', (jsdocTag, targetTagName) => {\n if (!jsdocTag.type) {\n report(`Missing JSDoc @${targetTagName} type.`, null, jsdocTag);\n }\n });\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'Requires that `@returns` tag has `type` value.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-returns-type.md#repos-sticky-header',\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n contexts: {\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n additionalProperties: false,\n properties: {\n comment: {\n type: 'string',\n },\n context: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"mappings":";;;;;;AAAA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAA8C,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAE/B,IAAAG,qBAAY,EAAC,CAAC;EAC3BC,MAAM;EACNC;AACF,CAAC,KAAK;EACJA,KAAK,CAACC,mBAAmB,CAAC,SAAS,EAAE,CAACC,QAAQ,EAAEC,aAAa,KAAK;IAChE,IAAI,CAACD,QAAQ,CAACE,IAAI,EAAE;MAClBL,MAAM,CAAC,kBAAkBI,aAAa,QAAQ,EAAE,IAAI,EAAED,QAAQ,CAAC;IACjE;EACF,CAAC,CAAC;AACJ,CAAC,EAAE;EACDG,eAAe,EAAE,IAAI;EACrBC,IAAI,EAAE;IACJC,IAAI,EAAE;MACJC,WAAW,EAAE,gDAAgD;MAC7DC,GAAG,EAAE;IACP,CAAC;IACDC,MAAM,EAAE,CACN;MACEC,oBAAoB,EAAE,KAAK;MAC3BC,UAAU,EAAE;QACVC,QAAQ,EAAE;UACRC,KAAK,EAAE;YACLC,KAAK,EAAE,CACL;cACEX,IAAI,EAAE;YACR,CAAC,EACD;cACEO,oBAAoB,EAAE,KAAK;cAC3BC,UAAU,EAAE;gBACVI,OAAO,EAAE;kBACPZ,IAAI,EAAE;gBACR,CAAC;gBACDa,OAAO,EAAE;kBACPb,IAAI,EAAE;gBACR;cACF,CAAC;cACDA,IAAI,EAAE;YACR,CAAC;UAEL,CAAC;UACDA,IAAI,EAAE;QACR;MACF,CAAC;MACDA,IAAI,EAAE;IACR,CAAC,CACF;IACDA,IAAI,EAAE;EACR;AACF,CAAC,CAAC;AAAAc,MAAA,CAAArB,OAAA,GAAAA,OAAA,CAAAF,OAAA","ignoreList":[]}

View File

@ -0,0 +1,182 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
context,
utils,
node,
settings,
report
}) => {
const {
requireSeparateTemplates = false
} = context.options[0] || {};
const {
mode
} = settings;
const usedNames = new Set();
const templateTags = utils.getTags('template');
const templateNames = templateTags.flatMap(({
name
}) => {
return name.split(/,\s*/);
});
for (const tag of templateTags) {
const {
name
} = tag;
const names = name.split(/,\s*/);
if (requireSeparateTemplates && names.length > 1) {
report(`Missing separate @template for ${names[1]}`, null, tag);
}
}
/**
* @param {import('@typescript-eslint/types').TSESTree.FunctionDeclaration|
* import('@typescript-eslint/types').TSESTree.ClassDeclaration|
* import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration|
* import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} aliasDeclaration
*/
const checkTypeParams = aliasDeclaration => {
/* c8 ignore next -- Guard */
const {
params
} = aliasDeclaration.typeParameters ?? {
params: []
};
for (const {
name: {
name
}
} of params) {
usedNames.add(name);
}
for (const usedName of usedNames) {
if (!templateNames.includes(usedName)) {
report(`Missing @template ${usedName}`);
}
}
};
const handleTypes = () => {
var _nde$declaration, _nde$declaration2;
const nde = /** @type {import('@typescript-eslint/types').TSESTree.Node} */
node;
if (!nde) {
return;
}
switch (nde.type) {
case 'ExportDefaultDeclaration':
switch ((_nde$declaration = nde.declaration) === null || _nde$declaration === void 0 ? void 0 : _nde$declaration.type) {
case 'ClassDeclaration':
case 'FunctionDeclaration':
case 'TSInterfaceDeclaration':
checkTypeParams(nde.declaration);
break;
}
break;
case 'ExportNamedDeclaration':
switch ((_nde$declaration2 = nde.declaration) === null || _nde$declaration2 === void 0 ? void 0 : _nde$declaration2.type) {
case 'ClassDeclaration':
case 'FunctionDeclaration':
case 'TSTypeAliasDeclaration':
case 'TSInterfaceDeclaration':
checkTypeParams(nde.declaration);
break;
}
break;
case 'ClassDeclaration':
case 'FunctionDeclaration':
case 'TSTypeAliasDeclaration':
case 'TSInterfaceDeclaration':
checkTypeParams(nde);
break;
}
};
const usedNameToTag = new Map();
/**
* @param {import('comment-parser').Spec} potentialTag
*/
const checkForUsedTypes = potentialTag => {
let parsedType;
try {
parsedType = mode === 'permissive' ? (0, _jsdoccomment.tryParse)( /** @type {string} */potentialTag.type) : (0, _jsdoccomment.parse)( /** @type {string} */potentialTag.type, mode);
} catch {
return;
}
(0, _jsdoccomment.traverse)(parsedType, nde => {
const {
type,
value
} = /** @type {import('jsdoc-type-pratt-parser').NameResult} */nde;
if (type === 'JsdocTypeName' && /^[A-Z]$/.test(value)) {
usedNames.add(value);
if (!usedNameToTag.has(value)) {
usedNameToTag.set(value, potentialTag);
}
}
});
};
/**
* @param {string[]} tagNames
*/
const checkTagsAndTemplates = tagNames => {
for (const tagName of tagNames) {
const preferredTagName = /** @type {string} */utils.getPreferredTagName({
tagName
});
const matchingTags = utils.getTags(preferredTagName);
for (const matchingTag of matchingTags) {
checkForUsedTypes(matchingTag);
}
}
// Could check against whitelist/blacklist
for (const usedName of usedNames) {
if (!templateNames.includes(usedName)) {
report(`Missing @template ${usedName}`, null, usedNameToTag.get(usedName));
}
}
};
const callbackTags = utils.getTags('callback');
const functionTags = utils.getTags('function');
if (callbackTags.length || functionTags.length) {
checkTagsAndTemplates(['param', 'returns']);
return;
}
const typedefTags = utils.getTags('typedef');
if (!typedefTags.length || typedefTags.length >= 2) {
handleTypes();
return;
}
const potentialTypedef = typedefTags[0];
checkForUsedTypes(potentialTypedef);
checkTagsAndTemplates(['property']);
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires template tags for each generic type parameter',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-template.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
requireSeparateTemplates: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireTemplate.cjs.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,101 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
/**
* We can skip checking for a throws value, in case the documentation is inherited
* or the method is either a constructor or an abstract method.
* @param {import('../iterateJsdoc.js').Utils} utils a reference to the utils which are used to probe if a tag is present or not.
* @returns {boolean} true in case deep checking can be skipped; otherwise false.
*/
const canSkip = utils => {
return utils.hasATag([
// inheritdoc implies that all documentation is inherited
// see https://jsdoc.app/tags-inheritdoc.html
//
// Abstract methods are by definition incomplete,
// so it is not necessary to document that they throw an error.
'abstract', 'virtual',
// The designated type can itself document `@throws`
'type']) || utils.avoidDocs();
};
var _default = exports.default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
// A preflight check. We do not need to run a deep check for abstract
// functions.
if (canSkip(utils)) {
return;
}
const tagName = /** @type {string} */utils.getPreferredTagName({
tagName: 'throws'
});
if (!tagName) {
return;
}
const tags = utils.getTags(tagName);
const iteratingFunction = utils.isIteratingFunction();
// In case the code returns something, we expect a return value in JSDoc.
const [tag] = tags;
const missingThrowsTag = typeof tag === 'undefined' || tag === null;
const shouldReport = () => {
if (!missingThrowsTag) {
if (tag.type.trim() === 'never' && iteratingFunction && utils.hasThrowValue()) {
report(`JSDoc @${tagName} declaration set to "never" but throw value found.`);
}
return false;
}
return iteratingFunction && utils.hasThrowValue();
};
if (shouldReport()) {
report(`Missing JSDoc @${tagName} declaration.`);
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires that throw statements are documented.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-throws.md#repos-sticky-header'
},
schema: [{
additionalProperties: false,
properties: {
contexts: {
items: {
anyOf: [{
type: 'string'
}, {
additionalProperties: false,
properties: {
comment: {
type: 'string'
},
context: {
type: 'string'
}
},
type: 'object'
}]
},
type: 'array'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
module.exports = exports.default;
//# sourceMappingURL=requireThrows.cjs.map

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More