722 lines
No EOL
24 KiB
JavaScript
722 lines
No EOL
24 KiB
JavaScript
"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,
|
|
description: 'Has the following optional keys.\n',
|
|
properties: {
|
|
checkAllFunctionExpressions: {
|
|
default: false,
|
|
description: `Normally, when \`FunctionExpression\` is checked, additional checks are
|
|
added to check the parent contexts where reporting is likely to be desired. If you really
|
|
want to check *all* function expressions, then set this to \`true\`.`,
|
|
type: 'boolean'
|
|
},
|
|
checkConstructors: {
|
|
default: true,
|
|
description: `A value indicating whether \`constructor\`s should be checked. Defaults to
|
|
\`true\`. When \`true\`, \`exemptEmptyConstructors\` may still avoid reporting when
|
|
no parameters or return values are found.`,
|
|
type: 'boolean'
|
|
},
|
|
checkGetters: {
|
|
anyOf: [{
|
|
type: 'boolean'
|
|
}, {
|
|
enum: ['no-setter'],
|
|
type: 'string'
|
|
}],
|
|
default: true,
|
|
description: `A value indicating whether getters should be checked. Besides setting as a
|
|
boolean, this option can be set to the string \`"no-setter"\` to indicate that
|
|
getters should be checked but only when there is no setter. This may be useful
|
|
if one only wishes documentation on one of the two accessors. Defaults to
|
|
\`false\`.`
|
|
},
|
|
checkSetters: {
|
|
anyOf: [{
|
|
type: 'boolean'
|
|
}, {
|
|
enum: ['no-getter'],
|
|
type: 'string'
|
|
}],
|
|
default: true,
|
|
description: `A value indicating whether setters should be checked. Besides setting as a
|
|
boolean, this option can be set to the string \`"no-getter"\` to indicate that
|
|
setters should be checked but only when there is no getter. This may be useful
|
|
if one only wishes documentation on one of the two accessors. Defaults to
|
|
\`false\`.`
|
|
},
|
|
contexts: {
|
|
description: `Set this to an array of strings or objects representing the additional AST
|
|
contexts where you wish the rule to be applied (e.g., \`Property\` for
|
|
properties). If specified as an object, it should have a \`context\` property
|
|
and can have an \`inlineCommentBlock\` property which, if set to \`true\`, will
|
|
add an inline \`/** */\` instead of the regular, multi-line, indented jsdoc
|
|
block which will otherwise be added. Defaults to an empty array. Contexts
|
|
may also have their own \`minLineCount\` property which is an integer
|
|
indicating a minimum number of lines expected for a node in order
|
|
for it to require documentation.
|
|
|
|
Note that you may need to disable \`require\` items (e.g., \`MethodDefinition\`)
|
|
if you are specifying a more precise form in \`contexts\` (e.g., \`MethodDefinition:not([accessibility="private"] > FunctionExpression\`).
|
|
|
|
See the ["AST and Selectors"](../#advanced-ast-and-selectors)
|
|
section of our Advanced docs for more on the expected format.`,
|
|
items: {
|
|
anyOf: [{
|
|
type: 'string'
|
|
}, {
|
|
additionalProperties: false,
|
|
properties: {
|
|
context: {
|
|
type: 'string'
|
|
},
|
|
inlineCommentBlock: {
|
|
type: 'boolean'
|
|
},
|
|
minLineCount: {
|
|
type: 'integer'
|
|
}
|
|
},
|
|
type: 'object'
|
|
}]
|
|
},
|
|
type: 'array'
|
|
},
|
|
enableFixer: {
|
|
default: true,
|
|
description: `A boolean on whether to enable the fixer (which adds an empty JSDoc block).
|
|
Defaults to \`true\`.`,
|
|
type: 'boolean'
|
|
},
|
|
exemptEmptyConstructors: {
|
|
default: false,
|
|
description: `When \`true\`, the rule will not report missing JSDoc blocks above constructors
|
|
with no parameters or return values (this is enabled by default as the class
|
|
name or description should be seen as sufficient to convey intent).
|
|
|
|
Defaults to \`true\`.`,
|
|
type: 'boolean'
|
|
},
|
|
exemptEmptyFunctions: {
|
|
default: false,
|
|
description: `When \`true\`, the rule will not report missing JSDoc blocks above
|
|
functions/methods with no parameters or return values (intended where
|
|
function/method names are sufficient for themselves as documentation).
|
|
|
|
Defaults to \`false\`.`,
|
|
type: 'boolean'
|
|
},
|
|
exemptOverloadedImplementations: {
|
|
default: false,
|
|
description: `If set to \`true\` will avoid checking an overloaded function's implementation.
|
|
|
|
Defaults to \`false\`.`,
|
|
type: 'boolean'
|
|
},
|
|
fixerMessage: {
|
|
default: '',
|
|
description: `An optional message to add to the inserted JSDoc block. Defaults to the
|
|
empty string.`,
|
|
type: 'string'
|
|
},
|
|
minLineCount: {
|
|
description: `An integer to indicate a minimum number of lines expected for a node in order
|
|
for it to require documentation. Defaults to \`undefined\`. This option will
|
|
apply to any context; see \`contexts\` for line counts specific to a context.`,
|
|
type: 'integer'
|
|
},
|
|
publicOnly: {
|
|
description: `This option will insist that missing JSDoc blocks are only reported for
|
|
function bodies / class declarations that are exported from the module.
|
|
May be a boolean or object. If set to \`true\`, the defaults below will be
|
|
used. If unset, JSDoc block reporting will not be limited to exports.
|
|
|
|
This object supports the following optional boolean keys (\`false\` unless
|
|
otherwise noted):
|
|
|
|
- \`ancestorsOnly\` - Optimization to only check node ancestors to check if node is exported
|
|
- \`esm\` - ESM exports are checked for JSDoc comments (Defaults to \`true\`)
|
|
- \`cjs\` - CommonJS exports are checked for JSDoc comments (Defaults to \`true\`)
|
|
- \`window\` - Window global exports are checked for JSDoc comments`,
|
|
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: {},
|
|
description: `An object with the following optional boolean keys which all default to
|
|
\`false\` except for \`FunctionDeclaration\` which defaults to \`true\`.`,
|
|
properties: {
|
|
ArrowFunctionExpression: {
|
|
default: false,
|
|
description: 'Whether to check arrow functions like `() => {}`',
|
|
type: 'boolean'
|
|
},
|
|
ClassDeclaration: {
|
|
default: false,
|
|
description: 'Whether to check declarations like `class A {}`',
|
|
type: 'boolean'
|
|
},
|
|
ClassExpression: {
|
|
default: false,
|
|
description: 'Whether to check class expressions like `const myClass = class {}`',
|
|
type: 'boolean'
|
|
},
|
|
FunctionDeclaration: {
|
|
default: true,
|
|
description: 'Whether to check function declarations like `function a {}`',
|
|
type: 'boolean'
|
|
},
|
|
FunctionExpression: {
|
|
default: false,
|
|
description: 'Whether to check function expressions like `const a = function {}`',
|
|
type: 'boolean'
|
|
},
|
|
MethodDefinition: {
|
|
default: false,
|
|
description: 'Whether to check method definitions like `class A { someMethodDefinition () {} }`',
|
|
type: 'boolean'
|
|
}
|
|
},
|
|
type: 'object'
|
|
},
|
|
skipInterveningOverloadedDeclarations: {
|
|
default: true,
|
|
description: `If \`true\`, will skip above uncommented overloaded functions to check
|
|
for a comment block (e.g., at the top of a set of overloaded functions).
|
|
|
|
If \`false\`, will force each overloaded function to be checked for a
|
|
comment block.
|
|
|
|
Defaults to \`true\`.`,
|
|
type: 'boolean'
|
|
}
|
|
},
|
|
type: 'object'
|
|
};
|
|
|
|
/**
|
|
* @param {string} interfaceName
|
|
* @param {string} methodName
|
|
* @param {import("eslint").Scope.Scope | null} scope
|
|
* @returns {import('@typescript-eslint/types').TSESTree.TSMethodSignature|null}
|
|
*/
|
|
const getMethodOnInterface = (interfaceName, methodName, scope) => {
|
|
let scp = scope;
|
|
while (scp) {
|
|
for (const {
|
|
identifiers,
|
|
name
|
|
} of scp.variables) {
|
|
if (interfaceName !== name) {
|
|
continue;
|
|
}
|
|
for (const identifier of identifiers) {
|
|
const interfaceDeclaration = /** @type {import('@typescript-eslint/types').TSESTree.Identifier & {parent: import('@typescript-eslint/types').TSESTree.TSInterfaceDeclaration}} */identifier.parent;
|
|
/* c8 ignore next 3 -- TS */
|
|
if (interfaceDeclaration.type !== 'TSInterfaceDeclaration') {
|
|
continue;
|
|
}
|
|
for (const bodyItem of interfaceDeclaration.body.body) {
|
|
const methodSig = /** @type {import('@typescript-eslint/types').TSESTree.TSMethodSignature} */
|
|
bodyItem;
|
|
if (methodName === /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */methodSig.key.name) {
|
|
return methodSig;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
scp = scp.upper;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* @param {import('eslint').Rule.Node} node
|
|
* @param {import('eslint').SourceCode} sourceCode
|
|
* @param {import('eslint').Rule.RuleContext} context
|
|
* @param {import('../iterateJsdoc.js').Settings} settings
|
|
*/
|
|
const isExemptedImplementer = (node, sourceCode, context, settings) => {
|
|
if (node.type === 'FunctionExpression' && node.parent.type === 'MethodDefinition' && node.parent.parent.type === 'ClassBody' && node.parent.parent.parent.type === 'ClassDeclaration' && 'implements' in node.parent.parent.parent) {
|
|
const implments = /** @type {import('@typescript-eslint/types').TSESTree.TSClassImplements[]} */
|
|
node.parent.parent.parent.implements;
|
|
const {
|
|
name: methodName
|
|
} = /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */
|
|
node.parent.key;
|
|
for (const impl of implments) {
|
|
const {
|
|
name: interfaceName
|
|
} = /** @type {import('@typescript-eslint/types').TSESTree.Identifier} */
|
|
impl.expression;
|
|
const interfaceMethodNode = getMethodOnInterface(interfaceName, methodName, node && (sourceCode.getScope && /* c8 ignore next 3 */
|
|
sourceCode.getScope(node) ||
|
|
// @ts-expect-error ESLint 8
|
|
context.getScope()));
|
|
if (interfaceMethodNode) {
|
|
// @ts-expect-error Ok
|
|
const comment = (0, _jsdoccomment.getJSDocComment)(sourceCode, interfaceMethodNode, settings);
|
|
if (comment) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* @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 {{
|
|
* checkAllFunctionExpressions: boolean,
|
|
* contexts: (string|{
|
|
* context: string,
|
|
* inlineCommentBlock: boolean,
|
|
* minLineCount: import('../iterateJsdoc.js').Integer
|
|
* })[],
|
|
* enableFixer: boolean,
|
|
* exemptEmptyConstructors: boolean,
|
|
* exemptEmptyFunctions: boolean,
|
|
* skipInterveningOverloadedDeclarations: boolean,
|
|
* exemptOverloadedImplementations: 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 {
|
|
checkAllFunctionExpressions = false,
|
|
contexts = settings.contexts || [],
|
|
enableFixer = true,
|
|
exemptEmptyConstructors = true,
|
|
exemptEmptyFunctions = false,
|
|
exemptOverloadedImplementations = false,
|
|
fixerMessage = '',
|
|
minLineCount = undefined,
|
|
publicOnly,
|
|
skipInterveningOverloadedDeclarations = true
|
|
} = context.options[0] || {};
|
|
return {
|
|
checkAllFunctionExpressions,
|
|
contexts,
|
|
enableFixer,
|
|
exemptEmptyConstructors,
|
|
exemptEmptyFunctions,
|
|
exemptOverloadedImplementations,
|
|
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),
|
|
skipInterveningOverloadedDeclarations
|
|
};
|
|
};
|
|
|
|
/**
|
|
* @param {ESLintOrTSNode} node
|
|
*/
|
|
const isFunctionWithOverload = node => {
|
|
if (node.type !== 'FunctionDeclaration') {
|
|
return false;
|
|
}
|
|
let parent;
|
|
let child;
|
|
if (node.parent?.type === 'Program') {
|
|
parent = node.parent;
|
|
child = node;
|
|
} else if (node.parent?.type === 'ExportNamedDeclaration' && node.parent?.parent.type === 'Program') {
|
|
parent = node.parent?.parent;
|
|
child = node.parent;
|
|
}
|
|
if (!child || !parent) {
|
|
return false;
|
|
}
|
|
const functionName = node.id?.name;
|
|
const idx = parent.body.indexOf(child);
|
|
const prevSibling = parent.body[idx - 1];
|
|
return (
|
|
// @ts-expect-error Should be ok
|
|
prevSibling?.type === 'TSDeclareFunction' &&
|
|
// @ts-expect-error Should be ok
|
|
functionName === prevSibling.id.name || prevSibling?.type === 'ExportNamedDeclaration' &&
|
|
// @ts-expect-error Should be ok
|
|
prevSibling.declaration?.type === 'TSDeclareFunction' &&
|
|
// @ts-expect-error Should be ok
|
|
prevSibling.declaration?.id?.name === functionName
|
|
);
|
|
};
|
|
|
|
/** @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 {
|
|
checkAllFunctionExpressions,
|
|
contexts,
|
|
enableFixer,
|
|
exemptEmptyConstructors,
|
|
exemptEmptyFunctions,
|
|
exemptOverloadedImplementations,
|
|
fixerMessage,
|
|
minLineCount,
|
|
require: requireOption,
|
|
skipInterveningOverloadedDeclarations
|
|
} = 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 => {
|
|
return count !== undefined && count > (sourceCode.getText(node).match(/\n/gv)?.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;
|
|
}
|
|
}
|
|
if (exemptOverloadedImplementations && isFunctionWithOverload(node)) {
|
|
return;
|
|
}
|
|
const jsDocNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, node, settings, {
|
|
checkOverloads: skipInterveningOverloadedDeclarations
|
|
});
|
|
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;
|
|
}
|
|
}
|
|
if (isExemptedImplementer(node, sourceCode, context, settings)) {
|
|
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?.ancestorsOnly ?? false),
|
|
esm: Boolean(publicOnly?.esm ?? true),
|
|
initModuleExports: Boolean(publicOnly?.cjs ?? true),
|
|
initWindow: Boolean(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 (['AssignmentExpression', 'ExportDefaultDeclaration', 'VariableDeclarator'].includes(node.parent.type) || ['ClassProperty', 'ObjectProperty', 'Property', '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 (checkAllFunctionExpressions || ['AssignmentExpression', 'ExportDefaultDeclaration', 'VariableDeclarator'].includes(node.parent.type) || ['ClassProperty', 'ObjectProperty', 'Property', '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: 'Checks for presence of JSDoc comments, on functions and potentially other contexts (optionally limited to exports).',
|
|
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
|