added all files to project

This commit is contained in:
2022-03-10 10:36:59 +01:00
parent 09dd957b33
commit 46a936d7de
25351 changed files with 3883356 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
const WarnSettings = function () {
/** @type {WeakMap<object, Set<string>>} */
const warnedSettings = new WeakMap();
return {
/**
* Warn only once for each context and setting
*
* @param {object} context
* @param {string} setting
*/
hasBeenWarned(context, setting) {
return warnedSettings.has(context) && warnedSettings.get(context).has(setting);
},
markSettingAsWarned(context, setting) {
// istanbul ignore else
if (!warnedSettings.has(context)) {
warnedSettings.set(context, new Set());
}
warnedSettings.get(context).add(setting);
}
};
};
var _default = WarnSettings;
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=WarnSettings.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/WarnSettings.js"],"names":["WarnSettings","warnedSettings","WeakMap","hasBeenWarned","context","setting","has","get","markSettingAsWarned","set","Set","add"],"mappings":";;;;;;;AAAA,MAAMA,YAAY,GAAG,YAAY;AAC/B;AACA,QAAMC,cAAc,GAAG,IAAIC,OAAJ,EAAvB;AAEA,SAAO;AACL;AACJ;AACA;AACA;AACA;AACA;AACIC,IAAAA,aAAa,CAAEC,OAAF,EAAWC,OAAX,EAAoB;AAC/B,aAAOJ,cAAc,CAACK,GAAf,CAAmBF,OAAnB,KAA+BH,cAAc,CAACM,GAAf,CAAmBH,OAAnB,EAA4BE,GAA5B,CAAgCD,OAAhC,CAAtC;AACD,KATI;;AAWLG,IAAAA,mBAAmB,CAAEJ,OAAF,EAAWC,OAAX,EAAoB;AACrC;AACA,UAAI,CAACJ,cAAc,CAACK,GAAf,CAAmBF,OAAnB,CAAL,EAAkC;AAChCH,QAAAA,cAAc,CAACQ,GAAf,CAAmBL,OAAnB,EAA4B,IAAIM,GAAJ,EAA5B;AACD;;AAEDT,MAAAA,cAAc,CAACM,GAAf,CAAmBH,OAAnB,EAA4BO,GAA5B,CAAgCN,OAAhC;AACD;;AAlBI,GAAP;AAoBD,CAxBD;;eA0BeL,Y","sourcesContent":["const WarnSettings = function () {\n /** @type {WeakMap<object, Set<string>>} */\n const warnedSettings = new WeakMap();\n\n return {\n /**\n * Warn only once for each context and setting\n *\n * @param {object} context\n * @param {string} setting\n */\n hasBeenWarned (context, setting) {\n return warnedSettings.has(context) && warnedSettings.get(context).has(setting);\n },\n\n markSettingAsWarned (context, setting) {\n // istanbul ignore else\n if (!warnedSettings.has(context)) {\n warnedSettings.set(context, new Set());\n }\n\n warnedSettings.get(context).add(setting);\n },\n };\n};\n\nexport default WarnSettings;\n"],"file":"WarnSettings.js"}
+214
View File
@@ -0,0 +1,214 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _commentParser = require("comment-parser");
/**
* Transform based on https://github.com/syavorsky/comment-parser/blob/master/src/transforms/align.ts
*
* It contains some customizations to align based on the tags, and some custom options.
*/
const {
rewireSource
} = _commentParser.util;
const zeroWidth = {
name: 0,
start: 0,
tag: 0,
type: 0
};
const shouldAlign = (tags, index, source) => {
const tag = source[index].tokens.tag.replace('@', '');
const includesTag = tags.includes(tag);
if (includesTag) {
return true;
}
if (tag !== '') {
return false;
}
for (let iterator = index; iterator >= 0; iterator--) {
const previousTag = source[iterator].tokens.tag.replace('@', '');
if (previousTag !== '') {
if (tags.includes(previousTag)) {
return true;
}
return false;
}
}
return true;
};
const getWidth = tags => {
return (width, {
tokens
}, index, source) => {
if (!shouldAlign(tags, index, source)) {
return width;
}
return {
name: Math.max(width.name, tokens.name.length),
start: tokens.delimiter === _commentParser.Markers.start ? tokens.start.length : width.start,
tag: Math.max(width.tag, tokens.tag.length),
type: Math.max(width.type, tokens.type.length)
};
};
};
const space = len => {
return ''.padStart(len, ' ');
};
const alignTransform = ({
customSpacings,
tags,
indent,
preserveMainDescriptionPostDelimiter
}) => {
let intoTags = false;
let width;
const alignTokens = tokens => {
const nothingAfter = {
delim: false,
name: false,
tag: false,
type: false
};
if (tokens.description === '') {
nothingAfter.name = true;
tokens.postName = '';
if (tokens.name === '') {
nothingAfter.type = true;
tokens.postType = '';
if (tokens.type === '') {
nothingAfter.tag = true;
tokens.postTag = '';
/* istanbul ignore next: Never happens because the !intoTags return. But it's here for consistency with the original align transform */
if (tokens.tag === '') {
nothingAfter.delim = true;
}
}
}
} // Todo: Avoid fixing alignment of blocks with multiline wrapping of type
if (tokens.tag === '' && tokens.type) {
return tokens;
}
const spacings = {
postDelimiter: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postDelimiter) || 1,
postName: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postName) || 1,
postTag: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postTag) || 1,
postType: (customSpacings === null || customSpacings === void 0 ? void 0 : customSpacings.postType) || 1
};
tokens.postDelimiter = nothingAfter.delim ? '' : space(spacings.postDelimiter);
if (!nothingAfter.tag) {
tokens.postTag = space(width.tag - tokens.tag.length + spacings.postTag);
}
if (!nothingAfter.type) {
tokens.postType = space(width.type - tokens.type.length + spacings.postType);
}
if (!nothingAfter.name) {
// If post name is empty for all lines (name width 0), don't add post name spacing.
tokens.postName = width.name === 0 ? '' : space(width.name - tokens.name.length + spacings.postName);
}
return tokens;
};
const update = (line, index, source) => {
const tokens = { ...line.tokens
};
if (tokens.tag !== '') {
intoTags = true;
}
const isEmpty = tokens.tag === '' && tokens.name === '' && tokens.type === '' && tokens.description === ''; // dangling '*/'
if (tokens.end === _commentParser.Markers.end && isEmpty) {
tokens.start = indent + ' ';
return { ...line,
tokens
};
}
/* eslint-disable indent */
switch (tokens.delimiter) {
case _commentParser.Markers.start:
tokens.start = indent;
break;
case _commentParser.Markers.delim:
tokens.start = indent + ' ';
break;
default:
tokens.delimiter = ''; // compensate delimiter
tokens.start = indent + ' ';
}
/* eslint-enable */
if (!intoTags) {
if (tokens.description === '') {
tokens.postDelimiter = '';
} else if (!preserveMainDescriptionPostDelimiter) {
tokens.postDelimiter = ' ';
}
return { ...line,
tokens
};
} // Not align.
if (!shouldAlign(tags, index, source)) {
return { ...line,
tokens
};
}
return { ...line,
tokens: alignTokens(tokens)
};
};
return ({
source,
...fields
}) => {
width = source.reduce(getWidth(tags), { ...zeroWidth
});
return rewireSource({ ...fields,
source: source.map(update)
});
};
};
var _default = alignTransform;
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=alignTransform.js.map
File diff suppressed because one or more lines are too long
+214
View File
@@ -0,0 +1,214 @@
"use strict";
var _fs = require("fs");
var _promises = _interopRequireDefault(require("fs/promises"));
var _path = require("path");
var _lodash = _interopRequireDefault(require("lodash"));
var _openEditor = _interopRequireDefault(require("open-editor"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
// Todo: Would ideally have prompts, e.g., to ask for whether type was problem/layout, etc.
const [,, ruleName, ...options] = process.argv;
const recommended = options.includes('--recommended');
(async () => {
if (!ruleName) {
console.error('Please supply a rule name');
return;
}
if (/[A-Z]/u.test(ruleName)) {
console.error('Please ensure the rule has no capital letters');
return;
}
const ruleNamesPath = './test/rules/ruleNames.json';
const ruleNames = JSON.parse(await _promises.default.readFile(ruleNamesPath, 'utf8'));
if (!ruleNames.includes(ruleName)) {
ruleNames.push(ruleName);
ruleNames.sort();
}
await _promises.default.writeFile(ruleNamesPath, JSON.stringify(ruleNames, null, 2) + '\n');
console.log('ruleNames', ruleNames);
const ruleTemplate = `import iterateJsdoc from '../iterateJsdoc';
export default iterateJsdoc(({
context,
utils,
}) => {
// Rule here
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: '',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-${ruleName}',
},
schema: [
{
additionalProperies: false,
properties: {
// Option properties here (or remove the object)
},
type: 'object',
},
],
type: 'suggestion',
},
});
`;
const camelCasedRuleName = _lodash.default.camelCase(ruleName);
const rulePath = `./src/rules/${camelCasedRuleName}.js`;
if (!(0, _fs.existsSync)(rulePath)) {
await _promises.default.writeFile(rulePath, ruleTemplate);
}
const ruleTestTemplate = `export default {
invalid: [
{
code: \`
\`,
errors: [{
line: '',
message: '',
}],
},
],
valid: [
{
code: \`
\`,
},
],
};
`;
const ruleTestPath = `./test/rules/assertions/${camelCasedRuleName}.js`;
if (!(0, _fs.existsSync)(ruleTestPath)) {
await _promises.default.writeFile(ruleTestPath, ruleTestTemplate);
}
const ruleReadmeTemplate = `### \`${ruleName}\`
|||
|---|---|
|Context|everywhere|
|Tags|\`\`|
|Recommended|${recommended ? 'true' : 'false'}|
|Settings||
|Options||
<!-- assertions ${camelCasedRuleName} -->
`;
const ruleReadmePath = `./.README/rules/${ruleName}.md`;
if (!(0, _fs.existsSync)(ruleReadmePath)) {
await _promises.default.writeFile(ruleReadmePath, ruleReadmeTemplate);
}
const replaceInOrder = async ({
path,
oldRegex,
checkName,
newLine,
oldIsCamel
}) => {
const offsets = [];
let readme = await _promises.default.readFile(path, 'utf8');
readme.replace(oldRegex, (matchedLine, n1, offset, str, {
oldRule
}) => {
offsets.push({
matchedLine,
offset,
oldRule
});
});
offsets.sort(({
oldRule
}, {
oldRule: oldRuleB
}) => {
// eslint-disable-next-line no-extra-parens
return oldRule < oldRuleB ? -1 : oldRule > oldRuleB ? 1 : 0;
});
let alreadyIncluded = false;
const itemIndex = offsets.findIndex(({
oldRule
}) => {
alreadyIncluded || (alreadyIncluded = oldIsCamel ? camelCasedRuleName === oldRule : ruleName === oldRule);
return oldIsCamel ? camelCasedRuleName < oldRule : ruleName < oldRule;
});
let item = itemIndex !== undefined && offsets[itemIndex];
if (item && itemIndex === 0 && // This property would not always be sufficient but in this case it is.
oldIsCamel) {
item.offset = 0;
}
if (!item) {
item = offsets.pop();
item.offset += item.matchedLine.length;
}
if (alreadyIncluded) {
console.log(`Rule name is already present in ${checkName}.`);
} else {
readme = readme.slice(0, item.offset) + (item.offset ? '\n' : '') + newLine + (item.offset ? '' : '\n') + readme.slice(item.offset);
await _promises.default.writeFile(path, readme);
}
};
await replaceInOrder({
checkName: 'README',
newLine: `{"gitdown": "include", "file": "./rules/${ruleName}.md"}`,
oldRegex: /\n\{"gitdown": "include", "file": ".\/rules\/(?<oldRule>[^.]*).md"\}/gu,
path: './.README/README.md'
});
await replaceInOrder({
checkName: 'index import',
newLine: `import ${camelCasedRuleName} from './rules/${camelCasedRuleName}';`,
oldIsCamel: true,
oldRegex: /\nimport (?<oldRule>[^ ]*) from '.\/rules\/\1';/gu,
path: './src/index.js'
});
await replaceInOrder({
checkName: 'index recommended',
newLine: `${' '.repeat(8)}'jsdoc/${ruleName}': '${recommended ? 'warn' : 'off'}',`,
oldRegex: /\n\s{8}'jsdoc\/(?<oldRule>[^']*)': '[^']*',/gu,
path: './src/index.js'
});
await replaceInOrder({
checkName: 'index rules',
newLine: `${' '.repeat(4)}'${ruleName}': ${camelCasedRuleName},`,
oldRegex: /\n\s{4}'(?<oldRule>[^']*)': [^,]*,/gu,
path: './src/index.js'
});
await Promise.resolve().then(() => _interopRequireWildcard(require('./generateReadme.js')));
/*
console.log('Paths to open for further editing\n');
console.log(`open ${ruleReadmePath}`);
console.log(`open ${rulePath}`);
console.log(`open ${ruleTestPath}\n`);
*/
// Set chdir as somehow still in operation from other test
process.chdir((0, _path.resolve)(__dirname, '../../'));
await (0, _openEditor.default)([// Could even add editor line column numbers like `${rulePath}:1:1`
ruleReadmePath, ruleTestPath, rulePath]);
})();
//# sourceMappingURL=generateRule.js.map
File diff suppressed because one or more lines are too long
+605
View File
@@ -0,0 +1,605 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _debug = _interopRequireDefault(require("debug"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = (0, _debug.default)('requireExportJsdoc');
const createNode = function () {
return {
props: {}
};
};
const getSymbolValue = function (symbol) {
/* istanbul ignore next */
if (!symbol) {
/* istanbul ignore next */
return null;
}
/* istanbul ignore next */
if (symbol.type === 'literal') {
return symbol.value.value;
}
/* istanbul ignore next */
return null;
};
const getIdentifier = function (node, globals, scope, opts) {
if (opts.simpleIdentifier) {
// Type is Identier for noncomputed properties
const identifierLiteral = createNode();
identifierLiteral.type = 'literal';
identifierLiteral.value = {
value: node.name
};
return identifierLiteral;
}
/* istanbul ignore next */
const block = scope || globals; // As scopes are not currently supported, they are not traversed upwards recursively
if (block.props[node.name]) {
return block.props[node.name];
} // Seems this will only be entered once scopes added and entered
/* istanbul ignore next */
if (globals.props[node.name]) {
return globals.props[node.name];
}
return null;
};
let createSymbol = null;
const getSymbol = function (node, globals, scope, opt) {
const opts = opt || {};
/* istanbul ignore next */
switch (node.type) {
case 'Identifier':
{
return getIdentifier(node, globals, scope, opts);
}
case 'MemberExpression':
{
const obj = getSymbol(node.object, globals, scope, opts);
const propertySymbol = getSymbol(node.property, globals, scope, {
simpleIdentifier: !node.computed
});
const propertyValue = getSymbolValue(propertySymbol);
/* istanbul ignore next */
if (obj && propertyValue && obj.props[propertyValue]) {
const block = obj.props[propertyValue];
return block;
}
/*
if (opts.createMissingProps && propertyValue) {
obj.props[propertyValue] = createNode();
return obj.props[propertyValue];
}
*/
/* istanbul ignore next */
debug(`MemberExpression: Missing property ${node.property.name}`);
/* istanbul ignore next */
return null;
}
case 'TSTypeAliasDeclaration':
case 'TSEnumDeclaration':
case 'TSInterfaceDeclaration':
case 'ClassDeclaration':
case 'ClassExpression':
case 'FunctionExpression':
case 'FunctionDeclaration':
case 'ArrowFunctionExpression':
{
const val = createNode();
val.props.prototype = createNode();
val.props.prototype.type = 'object';
val.type = 'object';
val.value = node;
return val;
}
case 'AssignmentExpression':
{
return createSymbol(node.left, globals, node.right, scope, opts);
}
case 'ClassBody':
{
const val = createNode();
node.body.forEach(method => {
val.props[method.key.name] = createNode();
val.props[method.key.name].type = 'object';
val.props[method.key.name].value = method.value;
});
val.type = 'object';
val.value = node;
return val;
}
case 'ObjectExpression':
{
const val = createNode();
val.type = 'object';
node.properties.forEach(prop => {
if ([// @typescript-eslint/parser, espree, acorn, etc.
'SpreadElement', // @babel/eslint-parser
'ExperimentalSpreadProperty'].includes(prop.type)) {
return;
}
const propVal = getSymbol(prop.value, globals, scope, opts);
/* istanbul ignore next */
if (propVal) {
val.props[prop.key.name] = propVal;
}
});
return val;
}
case 'Literal':
{
const val = createNode();
val.type = 'literal';
val.value = node;
return val;
}
}
/* istanbul ignore next */
return null;
};
const createBlockSymbol = function (block, name, value, globals, isGlobal) {
block.props[name] = value;
if (isGlobal && globals.props.window && globals.props.window.special) {
globals.props.window.props[name] = value;
}
};
createSymbol = function (node, globals, value, scope, isGlobal) {
const block = scope || globals;
let symbol;
switch (node.type) {
case 'FunctionDeclaration':
/* istanbul ignore next */
// Fall through
case 'TSEnumDeclaration':
case 'TSInterfaceDeclaration':
/* istanbul ignore next */
// Fall through
case 'TSTypeAliasDeclaration':
case 'ClassDeclaration':
{
/* istanbul ignore next */
if (node.id && node.id.type === 'Identifier') {
return createSymbol(node.id, globals, node, globals);
}
/* istanbul ignore next */
break;
}
case 'Identifier':
{
if (value) {
const valueSymbol = getSymbol(value, globals, block);
/* istanbul ignore next */
if (valueSymbol) {
createBlockSymbol(block, node.name, valueSymbol, globals, isGlobal);
return block.props[node.name];
}
/* istanbul ignore next */
debug('Identifier: Missing value symbol for %s', node.name);
} else {
createBlockSymbol(block, node.name, createNode(), globals, isGlobal);
return block.props[node.name];
}
/* istanbul ignore next */
break;
}
case 'MemberExpression':
{
symbol = getSymbol(node.object, globals, block);
const propertySymbol = getSymbol(node.property, globals, block, {
simpleIdentifier: !node.computed
});
const propertyValue = getSymbolValue(propertySymbol);
if (symbol && propertyValue) {
createBlockSymbol(symbol, propertyValue, getSymbol(value, globals, block), globals, isGlobal);
return symbol.props[propertyValue];
}
/* istanbul ignore next */
debug('MemberExpression: Missing symbol: %s', node.property.name);
break;
}
}
return null;
}; // Creates variables from variable definitions
const initVariables = function (node, globals, opts) {
switch (node.type) {
case 'Program':
{
node.body.forEach(childNode => {
initVariables(childNode, globals, opts);
});
break;
}
case 'ExpressionStatement':
{
initVariables(node.expression, globals, opts);
break;
}
case 'VariableDeclaration':
{
node.declarations.forEach(declaration => {
// let and const
const symbol = createSymbol(declaration.id, globals, null, globals);
if (opts.initWindow && node.kind === 'var' && globals.props.window) {
// If var, also add to window
globals.props.window.props[declaration.id.name] = symbol;
}
});
break;
}
case 'ExportNamedDeclaration':
{
if (node.declaration) {
initVariables(node.declaration, globals, opts);
}
break;
}
}
}; // Populates variable maps using AST
const mapVariables = function (node, globals, opt, isExport) {
/* istanbul ignore next */
const opts = opt || {};
/* istanbul ignore next */
switch (node.type) {
case 'Program':
{
if (opts.ancestorsOnly) {
return false;
}
node.body.forEach(childNode => {
mapVariables(childNode, globals, opts);
});
break;
}
case 'ExpressionStatement':
{
mapVariables(node.expression, globals, opts);
break;
}
case 'AssignmentExpression':
{
createSymbol(node.left, globals, node.right);
break;
}
case 'VariableDeclaration':
{
node.declarations.forEach(declaration => {
const isGlobal = opts.initWindow && node.kind === 'var' && globals.props.window;
const symbol = createSymbol(declaration.id, globals, declaration.init, globals, isGlobal);
if (symbol && isExport) {
symbol.exported = true;
}
});
break;
}
case 'FunctionDeclaration':
{
/* istanbul ignore next */
if (node.id.type === 'Identifier') {
createSymbol(node.id, globals, node, globals, true);
}
break;
}
case 'ExportDefaultDeclaration':
{
const symbol = createSymbol(node.declaration, globals, node.declaration);
if (symbol) {
symbol.exported = true;
} else if (!node.id) {
globals.ANONYMOUS_DEFAULT = node.declaration;
}
break;
}
case 'ExportNamedDeclaration':
{
if (node.declaration) {
if (node.declaration.type === 'VariableDeclaration') {
mapVariables(node.declaration, globals, opts, true);
} else {
const symbol = createSymbol(node.declaration, globals, node.declaration);
/* istanbul ignore next */
if (symbol) {
symbol.exported = true;
}
}
}
node.specifiers.forEach(specifier => {
mapVariables(specifier, globals, opts);
});
break;
}
case 'ExportSpecifier':
{
const symbol = getSymbol(node.local, globals, globals);
/* istanbul ignore next */
if (symbol) {
symbol.exported = true;
}
break;
}
case 'ClassDeclaration':
{
createSymbol(node.id, globals, node.body, globals);
break;
}
default:
{
/* istanbul ignore next */
return false;
}
}
return true;
};
const findNode = function (node, block, cache) {
let blockCache = cache || [];
/* istanbul ignore next */
if (!block || blockCache.includes(block)) {
return false;
}
blockCache = blockCache.slice();
blockCache.push(block);
if ((block.type === 'object' || block.type === 'MethodDefinition') && block.value === node) {
return true;
}
const {
props = block.body
} = block;
for (const propval of Object.values(props || {})) {
if (Array.isArray(propval)) {
/* istanbul ignore if */
if (propval.some(val => {
return findNode(node, val, blockCache);
})) {
return true;
}
} else if (findNode(node, propval, blockCache)) {
return true;
}
}
return false;
};
const exportTypes = new Set(['ExportNamedDeclaration', 'ExportDefaultDeclaration']);
const getExportAncestor = function (nde) {
let node = nde;
while (node) {
if (exportTypes.has(node.type)) {
return node;
}
node = node.parent;
}
return false;
};
const canExportedByAncestorType = new Set(['TSPropertySignature', 'TSMethodSignature', 'ClassProperty', 'Method']);
const canExportChildrenType = new Set(['TSInterfaceBody', 'TSInterfaceDeclaration', 'ClassDefinition', 'ClassExpression', 'Program']);
const isExportByAncestor = function (nde) {
if (!canExportedByAncestorType.has(nde.type)) {
return false;
}
let node = nde.parent;
while (node) {
if (exportTypes.has(node.type)) {
return node;
}
if (!canExportChildrenType.has(node.type)) {
return false;
}
node = node.parent;
}
return false;
};
const findExportedNode = function (block, node, cache) {
/* istanbul ignore next */
if (block === null) {
return false;
}
const blockCache = cache || [];
const {
props
} = block;
for (const propval of Object.values(props)) {
blockCache.push(propval);
if (propval.exported && (node === propval.value || findNode(node, propval.value))) {
return true;
} // No need to check `propval` for exported nodes as ESM
// exports are only global
}
return false;
};
const isNodeExported = function (node, globals, opt) {
if (opt.initModuleExports && globals.props.module && globals.props.module.props.exports && findNode(node, globals.props.module.props.exports)) {
return true;
}
if (opt.initWindow && globals.props.window && findNode(node, globals.props.window)) {
return true;
}
if (opt.esm && findExportedNode(globals, node)) {
return true;
}
return false;
};
const parseRecursive = function (node, globalVars, opts) {
// Iterate from top using recursion - stop at first processed node from top
if (node.parent && parseRecursive(node.parent, globalVars, opts)) {
return true;
}
return mapVariables(node, globalVars, opts);
};
const parse = function (ast, node, opt) {
/* istanbul ignore next */
const opts = opt || {
ancestorsOnly: false,
esm: true,
initModuleExports: true,
initWindow: true
};
const globalVars = createNode();
if (opts.initModuleExports) {
globalVars.props.module = createNode();
globalVars.props.module.props.exports = createNode();
globalVars.props.exports = globalVars.props.module.props.exports;
}
if (opts.initWindow) {
globalVars.props.window = createNode();
globalVars.props.window.special = true;
}
if (opts.ancestorsOnly) {
parseRecursive(node, globalVars, opts);
} else {
initVariables(ast, globalVars, opts);
mapVariables(ast, globalVars, opts);
}
return {
globalVars
};
};
const isUncommentedExport = function (node, sourceCode, opt, settings) {
// console.log({node});
// Optimize with ancestor check for esm
if (opt.esm) {
const exportNode = getExportAncestor(node); // Is export node comment
if (exportNode && !(0, _jsdoccomment.findJSDocComment)(exportNode, sourceCode, settings)) {
return true;
}
/** Some typescript types are not in variable map, but inherit exported (interface property and method)*/
if (isExportByAncestor(node) && !(0, _jsdoccomment.findJSDocComment)(node, sourceCode, settings)) {
return true;
}
}
const parseResult = parse(sourceCode.ast, node, opt);
return isNodeExported(node, parseResult.globalVars, opt);
};
var _default = {
isUncommentedExport,
parse
};
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=exportParser.js.map
File diff suppressed because one or more lines are too long
+214
View File
@@ -0,0 +1,214 @@
"use strict";
var _fs = require("fs");
var _promises = _interopRequireDefault(require("fs/promises"));
var _path = require("path");
var _lodash = _interopRequireDefault(require("lodash"));
var _openEditor = _interopRequireDefault(require("open-editor"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
// Todo: Would ideally have prompts, e.g., to ask for whether type was problem/layout, etc.
const [,, ruleName, ...options] = process.argv;
const recommended = options.includes('--recommended');
(async () => {
if (!ruleName) {
console.error('Please supply a rule name');
return;
}
if (/[A-Z]/u.test(ruleName)) {
console.error('Please ensure the rule has no capital letters');
return;
}
const ruleNamesPath = './test/rules/ruleNames.json';
const ruleNames = JSON.parse(await _promises.default.readFile(ruleNamesPath, 'utf8'));
if (!ruleNames.includes(ruleName)) {
ruleNames.push(ruleName);
ruleNames.sort();
}
await _promises.default.writeFile(ruleNamesPath, JSON.stringify(ruleNames, null, 2) + '\n');
console.log('ruleNames', ruleNames);
const ruleTemplate = `import iterateJsdoc from '../iterateJsdoc';
export default iterateJsdoc(({
context,
utils,
}) => {
// Rule here
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: '',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-${ruleName}',
},
schema: [
{
additionalProperies: false,
properties: {
// Option properties here (or remove the object)
},
type: 'object',
},
],
type: 'suggestion',
},
});
`;
const camelCasedRuleName = _lodash.default.camelCase(ruleName);
const rulePath = `./src/rules/${camelCasedRuleName}.js`;
if (!(0, _fs.existsSync)(rulePath)) {
await _promises.default.writeFile(rulePath, ruleTemplate);
}
const ruleTestTemplate = `export default {
invalid: [
{
code: \`
\`,
errors: [{
line: '',
message: '',
}],
},
],
valid: [
{
code: \`
\`,
},
],
};
`;
const ruleTestPath = `./test/rules/assertions/${camelCasedRuleName}.js`;
if (!(0, _fs.existsSync)(ruleTestPath)) {
await _promises.default.writeFile(ruleTestPath, ruleTestTemplate);
}
const ruleReadmeTemplate = `### \`${ruleName}\`
|||
|---|---|
|Context|everywhere|
|Tags|\`\`|
|Recommended|${recommended ? 'true' : 'false'}|
|Settings||
|Options||
<!-- assertions ${camelCasedRuleName} -->
`;
const ruleReadmePath = `./.README/rules/${ruleName}.md`;
if (!(0, _fs.existsSync)(ruleReadmePath)) {
await _promises.default.writeFile(ruleReadmePath, ruleReadmeTemplate);
}
const replaceInOrder = async ({
path,
oldRegex,
checkName,
newLine,
oldIsCamel
}) => {
const offsets = [];
let readme = await _promises.default.readFile(path, 'utf8');
readme.replace(oldRegex, (matchedLine, n1, offset, str, {
oldRule
}) => {
offsets.push({
matchedLine,
offset,
oldRule
});
});
offsets.sort(({
oldRule
}, {
oldRule: oldRuleB
}) => {
// eslint-disable-next-line no-extra-parens
return oldRule < oldRuleB ? -1 : oldRule > oldRuleB ? 1 : 0;
});
let alreadyIncluded = false;
const itemIndex = offsets.findIndex(({
oldRule
}) => {
alreadyIncluded || (alreadyIncluded = oldIsCamel ? camelCasedRuleName === oldRule : ruleName === oldRule);
return oldIsCamel ? camelCasedRuleName < oldRule : ruleName < oldRule;
});
let item = itemIndex !== undefined && offsets[itemIndex];
if (item && itemIndex === 0 && // This property would not always be sufficient but in this case it is.
oldIsCamel) {
item.offset = 0;
}
if (!item) {
item = offsets.pop();
item.offset += item.matchedLine.length;
}
if (alreadyIncluded) {
console.log(`Rule name is already present in ${checkName}.`);
} else {
readme = readme.slice(0, item.offset) + (item.offset ? '\n' : '') + newLine + (item.offset ? '' : '\n') + readme.slice(item.offset);
await _promises.default.writeFile(path, readme);
}
};
await replaceInOrder({
checkName: 'README',
newLine: `{"gitdown": "include", "file": "./rules/${ruleName}.md"}`,
oldRegex: /\n\{"gitdown": "include", "file": ".\/rules\/(?<oldRule>[^.]*).md"\}/gu,
path: './.README/README.md'
});
await replaceInOrder({
checkName: 'index import',
newLine: `import ${camelCasedRuleName} from './rules/${camelCasedRuleName}';`,
oldIsCamel: true,
oldRegex: /\nimport (?<oldRule>[^ ]*) from '.\/rules\/\1';/gu,
path: './src/index.js'
});
await replaceInOrder({
checkName: 'index recommended',
newLine: `${' '.repeat(8)}'jsdoc/${ruleName}': '${recommended ? 'warn' : 'off'}',`,
oldRegex: /\n\s{8}'jsdoc\/(?<oldRule>[^']*)': '[^']*',/gu,
path: './src/index.js'
});
await replaceInOrder({
checkName: 'index rules',
newLine: `${' '.repeat(4)}'${ruleName}': ${camelCasedRuleName},`,
oldRegex: /\n\s{4}'(?<oldRule>[^']*)': [^,]*,/gu,
path: './src/index.js'
});
await Promise.resolve().then(() => _interopRequireWildcard(require('./generateReadme.js')));
/*
console.log('Paths to open for further editing\n');
console.log(`open ${ruleReadmePath}`);
console.log(`open ${rulePath}`);
console.log(`open ${ruleTestPath}\n`);
*/
// Set chdir as somehow still in operation from other test
process.chdir((0, _path.resolve)(__dirname, '../../'));
await (0, _openEditor.default)([// Could even add editor line column numbers like `${rulePath}:1:1`
ruleReadmePath, ruleTestPath, rulePath]);
})();
//# sourceMappingURL=generateRule.js.map
File diff suppressed because one or more lines are too long
+167
View File
@@ -0,0 +1,167 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
const getDefaultTagStructureForMode = mode => {
const isJsdoc = mode === 'jsdoc';
const isClosure = mode === 'closure';
const isTypescript = mode === 'typescript';
const isPermissive = mode === 'permissive';
const isJsdocOrTypescript = isJsdoc || isTypescript;
const isTypescriptOrClosure = isTypescript || isClosure;
const isClosureOrPermissive = isClosure || isPermissive;
const isJsdocTypescriptOrPermissive = isJsdocOrTypescript || isPermissive; // Properties:
// `nameContents` - 'namepath-referencing'|'namepath-defining'|'text'|false
// `typeAllowed` - boolean
// `nameRequired` - boolean
// `typeRequired` - boolean
// `typeOrNameRequired` - boolean
// All of `typeAllowed` have a signature with "type" except for
// `augments`/`extends` ("namepath")
// `param`/`arg`/`argument` (no signature)
// `property`/`prop` (no signature)
// `modifies` (undocumented)
// None of the `nameContents: 'namepath-defining'` show as having curly
// brackets for their name/namepath
// Among `namepath-defining` and `namepath-referencing`, these do not seem
// to allow curly brackets in their doc signature or examples (`modifies`
// references namepaths within its type brackets and `param` is
// name-defining but not namepath-defining, so not part of these groups)
// Todo: Should support special processing for "name" as distinct from
// "namepath" (e.g., param can't define a namepath)
// Once checking inline tags:
// Todo: Re: `typeOrNameRequired`, `@link` (or @linkcode/@linkplain) seems
// to require a namepath OR URL and might be checked as such.
// Todo: Should support a `tutorialID` type (for `@tutorial` block and
// inline)
return new Map([['alias', new Map([// Signature seems to require a "namepath" (and no counter-examples)
['nameContents', 'namepath-referencing'], // "namepath"
['typeOrNameRequired', true]])], ['arg', new Map([['nameContents', 'namepath-defining'], // See `param`
['nameRequired', true], // Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['argument', new Map([['nameContents', 'namepath-defining'], // See `param`
['nameRequired', true], // Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['augments', new Map([// Signature seems to require a "namepath" (and no counter-examples)
['nameContents', 'namepath-referencing'], // Does not show curly brackets in either the signature or examples
['typeAllowed', true], // "namepath"
['typeOrNameRequired', true]])], ['borrows', new Map([// `borrows` has a different format, however, so needs special parsing;
// seems to require both, and as "namepath"'s
['nameContents', 'namepath-referencing'], // "namepath"
['typeOrNameRequired', true]])], ['callback', new Map([// Seems to require a "namepath" in the signature (with no
// counter-examples)
['nameContents', 'namepath-defining'], // "namepath"
['nameRequired', true]])], ['class', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining'], ['typeAllowed', true]])], ['const', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining'], ['typeAllowed', true]])], ['constant', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining'], ['typeAllowed', true]])], ['constructor', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining'], ['typeAllowed', true]])], ['define', new Map([['typeRequired', isClosure]])], ['emits', new Map([// Signature seems to require a "name" (of an event) and no counter-examples
['nameContents', 'namepath-referencing']])], ['enum', new Map([// Has example showing curly brackets but not in doc signature
['typeAllowed', true]])], ['event', new Map([// The doc signature of `event` seems to require a "name"
['nameRequired', true], // Appears to require a "name" in its signature, albeit somewhat
// different from other "name"'s (including as described
// at https://jsdoc.app/about-namepaths.html )
['nameContents', 'namepath-defining']])], ['exception', new Map([// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['export', new Map([['typeAllowed', isClosureOrPermissive]])], ['extends', new Map([// Signature seems to require a "namepath" (and no counter-examples)
['nameContents', 'namepath-referencing'], // Does not show curly brackets in either the signature or examples
['typeAllowed', isTypescriptOrClosure || isPermissive], ['nameRequired', isJsdoc], // "namepath"
['typeOrNameRequired', isTypescriptOrClosure || isPermissive]])], ['external', new Map([// Appears to require a "name" in its signature, albeit somewhat
// different from other "name"'s (including as described
// at https://jsdoc.app/about-namepaths.html )
['nameContents', 'namepath-defining'], // "name" (and a special syntax for the `external` name)
['nameRequired', true]])], ['fires', new Map([// Signature seems to require a "name" (of an event) and no
// counter-examples
['nameContents', 'namepath-referencing']])], ['function', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining']])], ['func', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining']])], ['host', new Map([// Appears to require a "name" in its signature, albeit somewhat
// different from other "name"'s (including as described
// at https://jsdoc.app/about-namepaths.html )
['nameContents', 'namepath-defining'], // See `external`
['nameRequired', true], // "namepath"
['typeOrNameRequired', true]])], ['interface', new Map([// Allows for "name" in signature, but indicates as optional
['nameContents', isJsdocTypescriptOrPermissive ? 'namepath-defining' : false]])], ['implements', new Map([// Shows curly brackets in the doc signature and examples
// "typeExpression"
['typeRequired', true]])], ['lends', new Map([// Signature seems to require a "namepath" (and no counter-examples)
['nameContents', 'namepath-referencing'], // "namepath"
['typeOrNameRequired', true]])], ['listens', new Map([// Signature seems to require a "name" (of an event) and no
// counter-examples
['nameContents', 'namepath-referencing']])], ['member', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining'], // Has example showing curly brackets but not in doc signature
['typeAllowed', true]])], ['memberof', new Map([// Signature seems to require a "namepath" (and no counter-examples),
// though it allows an incomplete namepath ending with connecting symbol
['nameContents', 'namepath-referencing'], // "namepath"
['typeOrNameRequired', true]])], ['memberof!', new Map([// Signature seems to require a "namepath" (and no counter-examples),
// though it allows an incomplete namepath ending with connecting symbol
['nameContents', 'namepath-referencing'], // "namepath"
['typeOrNameRequired', true]])], ['method', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining']])], ['mixes', new Map([// Signature seems to require a "OtherObjectPath" with no
// counter-examples
['nameContents', 'namepath-referencing'], // "OtherObjectPath"
['typeOrNameRequired', true]])], ['mixin', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining']])], ['modifies', new Map([// Has no documentation, but test example has curly brackets, and
// "name" would be suggested rather than "namepath" based on example;
// not sure if name is required
['typeAllowed', true]])], ['module', new Map([// Optional "name" and no curly brackets
// this block impacts `no-undefined-types` and `valid-types` (search for
// "isNamepathDefiningTag|tagMightHaveNamepath|tagMightHaveEitherTypeOrNamePosition")
['nameContents', isJsdoc ? 'namepath-defining' : 'text'], // Shows the signature with curly brackets but not in the example
['typeAllowed', true]])], ['name', new Map([// Seems to require a "namepath" in the signature (with no
// counter-examples)
['nameContents', 'namepath-defining'], // "namepath"
['nameRequired', true], // "namepath"
['typeOrNameRequired', true]])], ['namespace', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining'], // Shows the signature with curly brackets but not in the example
['typeAllowed', true]])], ['package', new Map([// Shows the signature with curly brackets but not in the example
// "typeExpression"
['typeAllowed', isClosureOrPermissive]])], ['param', new Map([['nameContents', 'namepath-defining'], // Though no signature provided requiring, per
// https://jsdoc.app/tags-param.html:
// "The @param tag requires you to specify the name of the parameter you
// are documenting."
['nameRequired', true], // Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['private', new Map([// Shows the signature with curly brackets but not in the example
// "typeExpression"
['typeAllowed', isClosureOrPermissive]])], ['prop', new Map([['nameContents', 'namepath-defining'], // See `property`
['nameRequired', true], // Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['property', new Map([['nameContents', 'namepath-defining'], // No docs indicate required, but since parallel to `param`, we treat as
// such:
['nameRequired', true], // Has no formal signature in the docs but shows curly brackets
// in the examples
['typeAllowed', true]])], ['protected', new Map([// Shows the signature with curly brackets but not in the example
// "typeExpression"
['typeAllowed', isClosureOrPermissive]])], ['public', new Map([// Does not show a signature nor show curly brackets in the example
['typeAllowed', isClosureOrPermissive]])], ['returns', new Map([// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['return', new Map([// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['see', new Map([// Signature allows for "namepath" or text, so user must configure to
// 'namepath-referencing' to enforce checks
['nameContents', 'text']])], ['static', new Map([// Does not show a signature nor show curly brackets in the example
['typeAllowed', isClosureOrPermissive]])], ['template', new Map([['nameContents', isJsdoc ? 'text' : 'namepath-referencing'], // Though defines `nameContents: 'namepath-defining'` in a sense, it is
// not parseable in the same way for template (e.g., allowing commas),
// so not adding
['typeAllowed', isTypescriptOrClosure || isPermissive]])], ['this', new Map([// Signature seems to require a "namepath" (and no counter-examples)
// Not used with namepath in Closure/TypeScript, however
['nameContents', isJsdoc ? 'namepath-referencing' : false], ['typeRequired', isTypescriptOrClosure], // namepath
['typeOrNameRequired', isJsdoc]])], ['throws', new Map([// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['type', new Map([// Shows curly brackets in the doc signature and examples
// "typeName"
['typeRequired', true]])], ['typedef', new Map([// Seems to require a "namepath" in the signature (with no
// counter-examples)
['nameContents', 'namepath-defining'], // "namepath"
['nameRequired', isJsdocTypescriptOrPermissive], // Has example showing curly brackets but not in doc signature
['typeAllowed', true], // "namepath"
['typeOrNameRequired', true]])], ['var', new Map([// Allows for "name"'s in signature, but indicated as optional
['nameContents', 'namepath-defining'], // Has example showing curly brackets but not in doc signature
['typeAllowed', true]])], ['yields', new Map([// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])], ['yield', new Map([// Shows curly brackets in the signature and in the examples
['typeAllowed', true]])]]);
};
var _default = getDefaultTagStructureForMode;
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=getDefaultTagStructureForMode.js.map
File diff suppressed because one or more lines are too long
+215
View File
@@ -0,0 +1,215 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _checkAccess = _interopRequireDefault(require("./rules/checkAccess"));
var _checkAlignment = _interopRequireDefault(require("./rules/checkAlignment"));
var _checkExamples = _interopRequireDefault(require("./rules/checkExamples"));
var _checkIndentation = _interopRequireDefault(require("./rules/checkIndentation"));
var _checkLineAlignment = _interopRequireDefault(require("./rules/checkLineAlignment"));
var _checkParamNames = _interopRequireDefault(require("./rules/checkParamNames"));
var _checkPropertyNames = _interopRequireDefault(require("./rules/checkPropertyNames"));
var _checkSyntax = _interopRequireDefault(require("./rules/checkSyntax"));
var _checkTagNames = _interopRequireDefault(require("./rules/checkTagNames"));
var _checkTypes = _interopRequireDefault(require("./rules/checkTypes"));
var _checkValues = _interopRequireDefault(require("./rules/checkValues"));
var _emptyTags = _interopRequireDefault(require("./rules/emptyTags"));
var _implementsOnClasses = _interopRequireDefault(require("./rules/implementsOnClasses"));
var _matchDescription = _interopRequireDefault(require("./rules/matchDescription"));
var _matchName = _interopRequireDefault(require("./rules/matchName"));
var _multilineBlocks = _interopRequireDefault(require("./rules/multilineBlocks"));
var _newlineAfterDescription = _interopRequireDefault(require("./rules/newlineAfterDescription"));
var _noBadBlocks = _interopRequireDefault(require("./rules/noBadBlocks"));
var _noDefaults = _interopRequireDefault(require("./rules/noDefaults"));
var _noMissingSyntax = _interopRequireDefault(require("./rules/noMissingSyntax"));
var _noMultiAsterisks = _interopRequireDefault(require("./rules/noMultiAsterisks"));
var _noRestrictedSyntax = _interopRequireDefault(require("./rules/noRestrictedSyntax"));
var _noTypes = _interopRequireDefault(require("./rules/noTypes"));
var _noUndefinedTypes = _interopRequireDefault(require("./rules/noUndefinedTypes"));
var _requireAsteriskPrefix = _interopRequireDefault(require("./rules/requireAsteriskPrefix"));
var _requireDescription = _interopRequireDefault(require("./rules/requireDescription"));
var _requireDescriptionCompleteSentence = _interopRequireDefault(require("./rules/requireDescriptionCompleteSentence"));
var _requireExample = _interopRequireDefault(require("./rules/requireExample"));
var _requireFileOverview = _interopRequireDefault(require("./rules/requireFileOverview"));
var _requireHyphenBeforeParamDescription = _interopRequireDefault(require("./rules/requireHyphenBeforeParamDescription"));
var _requireJsdoc = _interopRequireDefault(require("./rules/requireJsdoc"));
var _requireParam = _interopRequireDefault(require("./rules/requireParam"));
var _requireParamDescription = _interopRequireDefault(require("./rules/requireParamDescription"));
var _requireParamName = _interopRequireDefault(require("./rules/requireParamName"));
var _requireParamType = _interopRequireDefault(require("./rules/requireParamType"));
var _requireProperty = _interopRequireDefault(require("./rules/requireProperty"));
var _requirePropertyDescription = _interopRequireDefault(require("./rules/requirePropertyDescription"));
var _requirePropertyName = _interopRequireDefault(require("./rules/requirePropertyName"));
var _requirePropertyType = _interopRequireDefault(require("./rules/requirePropertyType"));
var _requireReturns = _interopRequireDefault(require("./rules/requireReturns"));
var _requireReturnsCheck = _interopRequireDefault(require("./rules/requireReturnsCheck"));
var _requireReturnsDescription = _interopRequireDefault(require("./rules/requireReturnsDescription"));
var _requireReturnsType = _interopRequireDefault(require("./rules/requireReturnsType"));
var _requireThrows = _interopRequireDefault(require("./rules/requireThrows"));
var _requireYields = _interopRequireDefault(require("./rules/requireYields"));
var _requireYieldsCheck = _interopRequireDefault(require("./rules/requireYieldsCheck"));
var _tagLines = _interopRequireDefault(require("./rules/tagLines"));
var _validTypes = _interopRequireDefault(require("./rules/validTypes"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = {
configs: {
recommended: {
plugins: ['jsdoc'],
rules: {
'jsdoc/check-access': 'warn',
'jsdoc/check-alignment': 'warn',
'jsdoc/check-examples': 'off',
'jsdoc/check-indentation': 'off',
'jsdoc/check-line-alignment': 'off',
'jsdoc/check-param-names': 'warn',
'jsdoc/check-property-names': 'warn',
'jsdoc/check-syntax': 'off',
'jsdoc/check-tag-names': 'warn',
'jsdoc/check-types': 'warn',
'jsdoc/check-values': 'warn',
'jsdoc/empty-tags': 'warn',
'jsdoc/implements-on-classes': 'warn',
'jsdoc/match-description': 'off',
'jsdoc/match-name': 'off',
'jsdoc/multiline-blocks': 'warn',
'jsdoc/newline-after-description': 'warn',
'jsdoc/no-bad-blocks': 'off',
'jsdoc/no-defaults': 'off',
'jsdoc/no-missing-syntax': 'off',
'jsdoc/no-multi-asterisks': 'warn',
'jsdoc/no-restricted-syntax': 'off',
'jsdoc/no-types': 'off',
'jsdoc/no-undefined-types': 'warn',
'jsdoc/require-asterisk-prefix': 'off',
'jsdoc/require-description': 'off',
'jsdoc/require-description-complete-sentence': 'off',
'jsdoc/require-example': 'off',
'jsdoc/require-file-overview': 'off',
'jsdoc/require-hyphen-before-param-description': 'off',
'jsdoc/require-jsdoc': 'warn',
'jsdoc/require-param': 'warn',
'jsdoc/require-param-description': 'warn',
'jsdoc/require-param-name': 'warn',
'jsdoc/require-param-type': 'warn',
'jsdoc/require-property': 'warn',
'jsdoc/require-property-description': 'warn',
'jsdoc/require-property-name': 'warn',
'jsdoc/require-property-type': 'warn',
'jsdoc/require-returns': 'warn',
'jsdoc/require-returns-check': 'warn',
'jsdoc/require-returns-description': 'warn',
'jsdoc/require-returns-type': 'warn',
'jsdoc/require-throws': 'off',
'jsdoc/require-yields': 'warn',
'jsdoc/require-yields-check': 'warn',
'jsdoc/tag-lines': 'warn',
'jsdoc/valid-types': 'warn'
}
}
},
rules: {
'check-access': _checkAccess.default,
'check-alignment': _checkAlignment.default,
'check-examples': _checkExamples.default,
'check-indentation': _checkIndentation.default,
'check-line-alignment': _checkLineAlignment.default,
'check-param-names': _checkParamNames.default,
'check-property-names': _checkPropertyNames.default,
'check-syntax': _checkSyntax.default,
'check-tag-names': _checkTagNames.default,
'check-types': _checkTypes.default,
'check-values': _checkValues.default,
'empty-tags': _emptyTags.default,
'implements-on-classes': _implementsOnClasses.default,
'match-description': _matchDescription.default,
'match-name': _matchName.default,
'multiline-blocks': _multilineBlocks.default,
'newline-after-description': _newlineAfterDescription.default,
'no-bad-blocks': _noBadBlocks.default,
'no-defaults': _noDefaults.default,
'no-missing-syntax': _noMissingSyntax.default,
'no-multi-asterisks': _noMultiAsterisks.default,
'no-restricted-syntax': _noRestrictedSyntax.default,
'no-types': _noTypes.default,
'no-undefined-types': _noUndefinedTypes.default,
'require-asterisk-prefix': _requireAsteriskPrefix.default,
'require-description': _requireDescription.default,
'require-description-complete-sentence': _requireDescriptionCompleteSentence.default,
'require-example': _requireExample.default,
'require-file-overview': _requireFileOverview.default,
'require-hyphen-before-param-description': _requireHyphenBeforeParamDescription.default,
'require-jsdoc': _requireJsdoc.default,
'require-param': _requireParam.default,
'require-param-description': _requireParamDescription.default,
'require-param-name': _requireParamName.default,
'require-param-type': _requireParamType.default,
'require-property': _requireProperty.default,
'require-property-description': _requirePropertyDescription.default,
'require-property-name': _requirePropertyName.default,
'require-property-type': _requirePropertyType.default,
'require-returns': _requireReturns.default,
'require-returns-check': _requireReturnsCheck.default,
'require-returns-description': _requireReturnsDescription.default,
'require-returns-type': _requireReturnsType.default,
'require-throws': _requireThrows.default,
'require-yields': _requireYields.default,
'require-yields-check': _requireYieldsCheck.default,
'tag-lines': _tagLines.default,
'valid-types': _validTypes.default
}
};
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+49
View File
@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const accessLevels = ['package', 'private', 'protected', 'public'];
var _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#eslint-plugin-jsdoc-rules-check-access'
},
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkAccess.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/checkAccess.js"],"names":["accessLevels","report","utils","forEachPreferredTag","jsdocParameter","targetTagName","desc","name","description","includes","trim","accessLength","getTags","length","individualTagLength","getPresentTags","checkPrivate","iterateAllJsdocs","meta","docs","url","type"],"mappings":";;;;;;;AAAA;;;;AAEA,MAAMA,YAAY,GAAG,CAAC,SAAD,EAAY,SAAZ,EAAuB,WAAvB,EAAoC,QAApC,CAArB;;eAEe,2BAAa,CAAC;AAC3BC,EAAAA,MAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJA,EAAAA,KAAK,CAACC,mBAAN,CAA0B,QAA1B,EAAoC,CAACC,cAAD,EAAiBC,aAAjB,KAAmC;AACrE,UAAMC,IAAI,GAAGF,cAAc,CAACG,IAAf,GAAsB,GAAtB,GAA4BH,cAAc,CAACI,WAAxD;;AAEA,QAAI,CAACR,YAAY,CAACS,QAAb,CAAsBH,IAAI,CAACI,IAAL,EAAtB,CAAL,EAAyC;AACvCT,MAAAA,MAAM,CACH,wBAAuBI,aAAc,SADlC,EAEJ,IAFI,EAGJD,cAHI,CAAN;AAKD;AACF,GAVD;AAWA,QAAMO,YAAY,GAAGT,KAAK,CAACU,OAAN,CAAc,QAAd,EAAwBC,MAA7C;AACA,QAAMC,mBAAmB,GAAGZ,KAAK,CAACa,cAAN,CAAqBf,YAArB,EAAmCa,MAA/D;;AACA,MAAIF,YAAY,IAAIG,mBAApB,EAAyC;AACvCb,IAAAA,MAAM,CACJ,iHADI,CAAN;AAGD;;AACD,MAAIU,YAAY,GAAG,CAAf,IAAoBG,mBAAmB,GAAG,CAA9C,EAAiD;AAC/Cb,IAAAA,MAAM,CACJ,iEADI,CAAN;AAGD;AACF,CA3Bc,EA2BZ;AACDe,EAAAA,YAAY,EAAE,IADb;AAEDC,EAAAA,gBAAgB,EAAE,IAFjB;AAGDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJX,MAAAA,WAAW,EAAE,gDADT;AAEJY,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,IAAI,EAAE;AALF;AAHL,CA3BY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nconst accessLevels = ['package', 'private', 'protected', 'public'];\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 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#eslint-plugin-jsdoc-rules-check-access',\n },\n type: 'suggestion',\n },\n});\n"],"file":"checkAccess.js"}
+63
View File
@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const trimStart = string => {
return string.replace(/^\s+/u, '');
};
var _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;
});
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#eslint-plugin-jsdoc-rules-check-alignment'
},
fixable: 'code',
type: 'layout'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkAlignment.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/checkAlignment.js"],"names":["trimStart","string","replace","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"],"mappings":";;;;;;;AAAA;;;;AAEA,MAAMA,SAAS,GAAIC,MAAD,IAAY;AAC5B,SAAOA,MAAM,CAACC,OAAP,CAAe,OAAf,EAAwB,EAAxB,CAAP;AACD,CAFD;;eAIe,2BAAa,CAAC;AAC3BC,EAAAA,UAD2B;AAE3BC,EAAAA,SAF2B;AAG3BC,EAAAA,MAH2B;AAI3BC,EAAAA;AAJ2B,CAAD,KAKtB;AACJ;AACA,QAAMC,WAAW,GAAGD,MAAM,CAACE,MAAP,GAAgB,CAApC;AACA,QAAMC,WAAW,GAAGN,UAAU,CAACO,OAAX,CAAmBN,SAAnB,EAA8BO,KAA9B,CAAoC,IAApC,EACjBC,KADiB,CACX,CADW,EAEjBC,GAFiB,CAEZC,IAAD,IAAU;AACb,WAAOA,IAAI,CAACH,KAAL,CAAW,GAAX,EAAgB,CAAhB,CAAP;AACD,GAJiB,EAKjBI,MALiB,CAKTD,IAAD,IAAU;AAChB,WAAO,CAACd,SAAS,CAACc,IAAD,CAAT,CAAgBN,MAAxB;AACD,GAPiB,CAApB;;AASA,QAAMQ,GAAG,GAAIC,KAAD,IAAW;AACrB,UAAMC,WAAW,GAAGf,UAAU,CAACO,OAAX,CAAmBN,SAAnB,EAA8BO,KAA9B,CAAoC,IAApC,EACjBE,GADiB,CACb,CAACC,IAAD,EAAOK,KAAP,KAAiB;AACpB;AACA,YAAMC,OAAO,GAAG,CAACD,KAAD,IAAUnB,SAAS,CAACc,IAAI,CAACH,KAAL,CAAW,GAAX,EAAgB,CAAhB,CAAD,CAAT,CAA8BH,MAAxD;AAEA,aAAOY,OAAO,GAAGN,IAAH,GAAW,GAAER,MAAO,IAAGN,SAAS,CAACc,IAAD,CAAO,EAArD;AACD,KANiB,EAOjBO,IAPiB,CAOZ,IAPY,CAApB;AASA,WAAOJ,KAAK,CAACK,WAAN,CAAkBlB,SAAlB,EAA6Bc,WAA7B,CAAP;AACD,GAXD;;AAaAT,EAAAA,WAAW,CAACc,IAAZ,CAAiB,CAACT,IAAD,EAAOU,OAAP,KAAmB;AAClC,QAAIV,IAAI,CAACN,MAAL,KAAgBD,WAApB,EAAiC;AAC/BF,MAAAA,MAAM,CAAC,qCAAD,EAAwCW,GAAxC,EAA6C;AACjDF,QAAAA,IAAI,EAAEU,OAAO,GAAG;AADiC,OAA7C,CAAN;AAIA,aAAO,IAAP;AACD;;AAED,WAAO,KAAP;AACD,GAVD;AAWD,CAzCc,EAyCZ;AACDC,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,qDADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,OAAO,EAAE,MALL;AAMJC,IAAAA,IAAI,EAAE;AANF;AAFL,CAzCY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\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 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#eslint-plugin-jsdoc-rules-check-alignment',\n },\n fixable: 'code',\n type: 'layout',\n },\n});\n"],"file":"checkAlignment.js"}
+469
View File
@@ -0,0 +1,469 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _eslint = require("eslint");
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Todo: When peerDeps bump to ESLint 7, see about replacing `CLIEngine`
// with non-deprecated `ESLint` class:
// https://github.com/eslint/eslint/blob/master/docs/user-guide/migrating-to-7.0.0.md#-the-cliengine-class-has-been-deprecated
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;
const escapeStringRegexp = str => {
return str.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
};
const countChars = (str, ch) => {
return (str.match(new RegExp(escapeStringRegexp(ch), 'gu')) || []).length;
};
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
};
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'
};
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 = (0, _iterateJsdoc.default)(({
report,
utils,
context,
globalState
}) => {
if (!globalState.has('checkExamples-matchingFileName')) {
globalState.set('checkExamples-matchingFileName', new Map());
}
const matchingFileNameMap = 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?
const rulePaths = [];
const mdRules = noDefaultExampleRules ? undefined : defaultMdRules;
const expressionRules = noDefaultExampleRules ? undefined : defaultExpressionRules;
if (exampleCodeRegex) {
exampleCodeRegex = utils.getRegexFromString(exampleCodeRegex);
}
if (rejectExampleCodeRegex) {
rejectExampleCodeRegex = utils.getRegexFromString(rejectExampleCodeRegex);
}
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
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.replace(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 _eslint.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 _eslint.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 = tag.line + nonJSPrefacingLines;
const codeStartCol = likelyNestedJSDocIndentSpace;
messages.forEach(({
message,
line,
column,
severity,
ruleId
}) => {
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
});
});
};
sources.forEach(checkRules);
};
/**
*
* @param {string} filename
* @param {string} [ext="md/*.js"] 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, 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(/\..*?$/, `.${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 = utils.getPreferredTagName({
tagName: 'example'
});
if (!utils.hasTag(tagName)) {
return;
}
const matchingFilenameInfo = getFilenameInfo(matchingFileName);
utils.forEachPreferredTag('example', (tag, targetTagName) => {
let source = 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#eslint-plugin-jsdoc-rules-check-examples'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkExamples.js.map
File diff suppressed because one or more lines are too long
+72
View File
@@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const maskExcludedContent = (str, excludeTags) => {
const regContent = new RegExp(`([ \\t]+\\*)[ \\t]@(?:${excludeTags.join('|')})(?=[ \\n])([\\w|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*@|\\/))`, 'gu');
return str.replace(regContent, (_match, margin, code) => {
return new Array(code.match(/\n/gu).length + 1).join(margin + '\n');
});
};
const maskCodeBlocks = str => {
const regContent = /([ \t]+\*)[ \t]```[^\n]*?([\w|\W]*?\n)(?=[ \t]*\*(?:[ \t]*(?:```|@)|\/))/gu;
return str.replace(regContent, (_match, margin, code) => {
return new Array(code.match(/\n/gu).length + 1).join(margin + '\n');
});
};
var _default = (0, _iterateJsdoc.default)(({
sourceCode,
jsdocNode,
report,
context
}) => {
const options = context.options[0] || {};
const {
excludeTags = ['example']
} = options;
const reg = new RegExp(/^(?:\/?\**|[ \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#eslint-plugin-jsdoc-rules-check-indentation'
},
schema: [{
additionalProperties: false,
properties: {
excludeTags: {
items: {
pattern: '^\\S+$',
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'layout'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkIndentation.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/checkIndentation.js"],"names":["maskExcludedContent","str","excludeTags","regContent","RegExp","join","replace","_match","margin","code","Array","match","length","maskCodeBlocks","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"],"mappings":";;;;;;;AAAA;;;;AAEA,MAAMA,mBAAmB,GAAG,CAACC,GAAD,EAAMC,WAAN,KAAsB;AAChD,QAAMC,UAAU,GAAG,IAAIC,MAAJ,CAAY,yBAAwBF,WAAW,CAACG,IAAZ,CAAiB,GAAjB,CAAsB,2DAA1D,EAAsH,IAAtH,CAAnB;AAEA,SAAOJ,GAAG,CAACK,OAAJ,CAAYH,UAAZ,EAAwB,CAACI,MAAD,EAASC,MAAT,EAAiBC,IAAjB,KAA0B;AACvD,WAAO,IAAIC,KAAJ,CAAUD,IAAI,CAACE,KAAL,CAAW,MAAX,EAAmBC,MAAnB,GAA4B,CAAtC,EAAyCP,IAAzC,CAA8CG,MAAM,GAAG,IAAvD,CAAP;AACD,GAFM,CAAP;AAGD,CAND;;AAQA,MAAMK,cAAc,GAAIZ,GAAD,IAAS;AAC9B,QAAME,UAAU,GAAG,4EAAnB;AAEA,SAAOF,GAAG,CAACK,OAAJ,CAAYH,UAAZ,EAAwB,CAACI,MAAD,EAASC,MAAT,EAAiBC,IAAjB,KAA0B;AACvD,WAAO,IAAIC,KAAJ,CAAUD,IAAI,CAACE,KAAL,CAAW,MAAX,EAAmBC,MAAnB,GAA4B,CAAtC,EAAyCP,IAAzC,CAA8CG,MAAM,GAAG,IAAvD,CAAP;AACD,GAFM,CAAP;AAGD,CAND;;eAQe,2BAAa,CAAC;AAC3BM,EAAAA,UAD2B;AAE3BC,EAAAA,SAF2B;AAG3BC,EAAAA,MAH2B;AAI3BC,EAAAA;AAJ2B,CAAD,KAKtB;AACJ,QAAMC,OAAO,GAAGD,OAAO,CAACC,OAAR,CAAgB,CAAhB,KAAsB,EAAtC;AACA,QAAM;AACJhB,IAAAA,WAAW,GAAG,CAAC,SAAD;AADV,MAEFgB,OAFJ;AAIA,QAAMC,GAAG,GAAG,IAAIf,MAAJ,CAAW,iCAAX,CAAZ;AACA,QAAMgB,qBAAqB,GAAGP,cAAc,CAACC,UAAU,CAACO,OAAX,CAAmBN,SAAnB,CAAD,CAA5C;AACA,QAAMO,IAAI,GAAGpB,WAAW,CAACU,MAAZ,GAAqBZ,mBAAmB,CAACoB,qBAAD,EAAwBlB,WAAxB,CAAxC,GAA+EkB,qBAA5F;;AAEA,MAAID,GAAG,CAACI,IAAJ,CAASD,IAAT,CAAJ,EAAoB;AAClB,UAAME,UAAU,GAAGF,IAAI,CAACG,KAAL,CAAW,CAAX,EAAcN,GAAG,CAACO,SAAlB,EAA6Bf,KAA7B,CAAmC,MAAnC,KAA8C,EAAjE;AACAK,IAAAA,MAAM,CAAC,+BAAD,EAAkC,IAAlC,EAAwC;AAC5CW,MAAAA,IAAI,EAAEH,UAAU,CAACZ;AAD2B,KAAxC,CAAN;AAGD;AACF,CArBc,EAqBZ;AACDgB,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,8CADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,MAAM,EAAE,CAAC;AACPC,MAAAA,oBAAoB,EAAE,KADf;AAEPC,MAAAA,UAAU,EAAE;AACVjC,QAAAA,WAAW,EAAE;AACXkC,UAAAA,KAAK,EAAE;AACLC,YAAAA,OAAO,EAAE,QADJ;AAELC,YAAAA,IAAI,EAAE;AAFD,WADI;AAKXA,UAAAA,IAAI,EAAE;AALK;AADH,OAFL;AAWPA,MAAAA,IAAI,EAAE;AAXC,KAAD,CALJ;AAkBJA,IAAAA,IAAI,EAAE;AAlBF;AAFL,CArBY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nconst maskExcludedContent = (str, excludeTags) => {\n const regContent = new RegExp(`([ \\\\t]+\\\\*)[ \\\\t]@(?:${excludeTags.join('|')})(?=[ \\\\n])([\\\\w|\\\\W]*?\\\\n)(?=[ \\\\t]*\\\\*(?:[ \\\\t]*@|\\\\/))`, 'gu');\n\n return str.replace(regContent, (_match, margin, code) => {\n return new Array(code.match(/\\n/gu).length + 1).join(margin + '\\n');\n });\n};\n\nconst maskCodeBlocks = (str) => {\n const regContent = /([ \\t]+\\*)[ \\t]```[^\\n]*?([\\w|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*(?:```|@)|\\/))/gu;\n\n return str.replace(regContent, (_match, margin, code) => {\n return new Array(code.match(/\\n/gu).length + 1).join(margin + '\\n');\n });\n};\n\nexport default iterateJsdoc(({\n sourceCode,\n jsdocNode,\n report,\n context,\n}) => {\n const options = context.options[0] || {};\n const {\n excludeTags = ['example'],\n } = options;\n\n const reg = new RegExp(/^(?:\\/?\\**|[ \\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#eslint-plugin-jsdoc-rules-check-indentation',\n },\n schema: [{\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 type: 'layout',\n },\n});\n"],"file":"checkIndentation.js"}
+223
View File
@@ -0,0 +1,223 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _commentParser = require("comment-parser");
var _alignTransform = _interopRequireDefault(require("../alignTransform"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const {
flow: commentFlow
} = _commentParser.transforms;
const checkNotAlignedPerTag = (utils, tag, customSpacings) => {
/*
start +
delimiter +
postDelimiter +
tag +
postTag +
type +
postType +
name +
postName +
description +
end +
lineEnd
*/
let spacerProps;
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];
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);
});
}; // 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);
});
if (ok) {
return;
}
const fix = () => {
spacerProps.forEach((spacerProp, idx) => {
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] = '';
}
});
utils.setTag(tag, tokens);
};
utils.reportJSDoc('Expected JSDoc block lines to not be aligned.', tag, fix, true);
};
const checkAlignment = ({
customSpacings,
indent,
jsdoc,
jsdocNode,
preserveMainDescriptionPostDelimiter,
report,
tags,
utils
}) => {
const transform = commentFlow((0, _alignTransform.default)({
customSpacings,
indent,
preserveMainDescriptionPostDelimiter,
tags
}));
const transformedJsdoc = transform(jsdoc);
const comment = '/*' + jsdocNode.value + '*/';
const formatted = utils.stringify(transformedJsdoc).trimStart();
if (comment !== formatted) {
report('Expected JSDoc block lines to be aligned.', fixer => {
return fixer.replaceText(jsdocNode, formatted);
});
}
};
var _default = (0, _iterateJsdoc.default)(({
indent,
jsdoc,
jsdocNode,
report,
context,
utils
}) => {
const {
tags: applicableTags = ['param', 'arg', 'argument', 'property', 'prop', 'returns', 'return'],
preserveMainDescriptionPostDelimiter,
customSpacings
} = context.options[1] || {};
if (context.options[0] === 'always') {
// Skip if it contains only a single line.
if (!jsdocNode.value.includes('\n')) {
return;
}
checkAlignment({
customSpacings,
indent,
jsdoc,
jsdocNode,
preserveMainDescriptionPostDelimiter,
report,
tags: applicableTags,
utils
});
return;
}
const foundTags = utils.getPresentTags(applicableTags);
foundTags.forEach(tag => {
checkNotAlignedPerTag(utils, tag, customSpacings);
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid alignment of JSDoc block lines.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-line-alignment'
},
fixable: 'whitespace',
schema: [{
enum: ['always', 'never'],
type: 'string'
}, {
additionalProperties: false,
properties: {
customSpacings: {
additionalProperties: false,
properties: {
postDelimiter: {
type: 'integer'
},
postName: {
type: 'integer'
},
postTag: {
type: 'integer'
},
postType: {
type: 'integer'
}
}
},
preserveMainDescriptionPostDelimiter: {
default: false,
type: 'boolean'
},
tags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'layout'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkLineAlignment.js.map
File diff suppressed because one or more lines are too long
+291
View File
@@ -0,0 +1,291 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const validateParameterNames = (targetTagName, allowExtraTrailingParamDocs, checkDestructured, checkRestProperty, checkTypesRegex, disableExtraPropertyReporting, enableFixer, functionParameterNames, jsdoc, _jsdocNode, 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;
return paramTags.some(([, tag], index) => {
let tagsIndex;
const dupeTagInfo = paramTags.find(([tgsIndex, tg], idx) => {
tagsIndex = 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;
}
const functionParameterName = functionParameterNames[index - dotted];
if (!functionParameterName) {
if (allowExtraTrailingParamDocs) {
return false;
}
report(`@${targetTagName} "${tag.name}" does not match an existing function parameter.`, 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
}] = 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 = [];
const notCheckingNames = [];
expectedNames.forEach((name, idx) => {
if (notCheckingNames.some(notCheckingName => {
return name.startsWith(notCheckingName);
})) {
return;
}
const actualNameIdx = actualNames.findIndex(actualName => {
return utils.comparePaths(name)(actualName);
});
if (actualNameIdx === -1) {
if (!checkRestProperty && rests[idx]) {
return;
}
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) {
missingProperties.forEach(({
tagPlacement,
name: missingProperty
}) => {
report(`Missing @${targetTagName} "${missingProperty}"`, null, tagPlacement);
});
}
if (!hasPropertyRest || checkRestProperty) {
const extraProperties = [];
actualNames.forEach((name, idx) => {
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) {
extraProperties.forEach(([extraProperty, tg]) => {
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 (item !== null && item !== void 0 && (_item$ = item[1]) !== null && _item$ !== void 0 && _item$.names) {
return actualNames[idx];
}
return item;
}).join(', ');
report(`Expected @${targetTagName} names to be "${expectedNames}". Got "${actualNames.join(', ')}".`, null, tag);
return true;
}
return false;
});
};
const validateParameterNamesDeep = (targetTagName, _allowExtraTrailingParamDocs, jsdocParameterNames, jsdoc, report) => {
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 = (0, _iterateJsdoc.default)(({
context,
jsdoc,
jsdocNode,
report,
utils
}) => {
const {
allowExtraTrailingParamDocs,
checkDestructured = true,
checkRestProperty = false,
checkTypesPattern = '/^(?:[oO]bject|[aA]rray|PlainObject|Generic(?:Object|Array))$/',
enableFixer = false,
useDefaultObjectProperties = false,
disableExtraPropertyReporting = false
} = context.options[0] || {};
const checkTypesRegex = utils.getRegexFromString(checkTypesPattern);
const jsdocParameterNamesDeep = utils.getJsdocTagsDeep('param');
if (!jsdocParameterNamesDeep.length) {
return;
}
const functionParameterNames = utils.getFunctionParameterNames(useDefaultObjectProperties);
const targetTagName = utils.getPreferredTagName({
tagName: 'param'
});
const isError = validateParameterNames(targetTagName, allowExtraTrailingParamDocs, checkDestructured, checkRestProperty, checkTypesRegex, disableExtraPropertyReporting, enableFixer, functionParameterNames, jsdoc, jsdocNode, utils, report);
if (isError || !checkDestructured) {
return;
}
validateParameterNamesDeep(targetTagName, allowExtraTrailingParamDocs, jsdocParameterNamesDeep, jsdoc, report);
}, {
meta: {
docs: {
description: 'Ensures that parameter names in JSDoc match those in the function declaration.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-param-names'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
allowExtraTrailingParamDocs: {
type: 'boolean'
},
checkDestructured: {
type: 'boolean'
},
checkRestProperty: {
type: 'boolean'
},
checkTypesPattern: {
type: 'string'
},
disableExtraPropertyReporting: {
type: 'boolean'
},
enableFixer: {
type: 'boolean'
},
useDefaultObjectProperties: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkParamNames.js.map
File diff suppressed because one or more lines are too long
+115
View File
@@ -0,0 +1,115 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const validatePropertyNames = (targetTagName, enableFixer, jsdoc, jsdocNode, utils) => {
const propertyTags = Object.entries(jsdoc.tags).filter(([, tag]) => {
return tag.tag === targetTagName;
});
return propertyTags.some(([, tag], index) => {
let tagsIndex;
const dupeTagInfo = propertyTags.find(([tgsIndex, tg], idx) => {
tagsIndex = 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;
});
};
const validatePropertyNamesDeep = (targetTagName, jsdocPropertyNames, jsdoc, report) => {
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 = (0, _iterateJsdoc.default)(({
context,
jsdoc,
jsdocNode,
report,
utils
}) => {
const {
enableFixer = false
} = context.options[0] || {};
const jsdocPropertyNamesDeep = utils.getJsdocTagsDeep('property');
if (!jsdocPropertyNamesDeep.length) {
return;
}
const targetTagName = utils.getPreferredTagName({
tagName: 'property'
});
const isError = validatePropertyNames(targetTagName, enableFixer, jsdoc, jsdocNode, 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#eslint-plugin-jsdoc-rules-check-property-names'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
enableFixer: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkPropertyNames.js.map
File diff suppressed because one or more lines are too long
+42
View File
@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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#eslint-plugin-jsdoc-rules-check-syntax'
},
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkSyntax.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/checkSyntax.js"],"names":["jsdoc","report","settings","mode","tag","tags","type","slice","iterateAllJsdocs","meta","docs","description","url"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,KAD2B;AAE3BC,EAAAA,MAF2B;AAG3BC,EAAAA;AAH2B,CAAD,KAItB;AACJ,QAAM;AAACC,IAAAA;AAAD,MAASD,QAAf,CADI,CAGJ;;AACA,MAAIC,IAAI,KAAK,OAAT,IAAoBA,IAAI,KAAK,YAAjC,EAA+C;AAC7C,SAAK,MAAMC,GAAX,IAAkBJ,KAAK,CAACK,IAAxB,EAA8B;AAC5B,UAAID,GAAG,CAACE,IAAJ,CAASC,KAAT,CAAe,CAAC,CAAhB,MAAuB,GAA3B,EAAgC;AAC9BN,QAAAA,MAAM,CAAC,qDAAD,EAAwD,IAAxD,EAA8DG,GAA9D,CAAN;AACA;AACD;AACF;AACF;AACF,CAhBc,EAgBZ;AACDI,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,oGADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJN,IAAAA,IAAI,EAAE;AALF;AAFL,CAhBY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nexport default iterateJsdoc(({\n jsdoc,\n report,\n settings,\n}) => {\n const {mode} = 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#eslint-plugin-jsdoc-rules-check-syntax',\n },\n type: 'suggestion',\n },\n});\n"],"file":"checkSyntax.js"}
+129
View File
@@ -0,0 +1,129 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _lodash = _interopRequireDefault(require("lodash"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/
const jsxTagNames = new Set(['jsx', 'jsxFrag', 'jsxImportSource', 'jsxRuntime']);
var _default = (0, _iterateJsdoc.default)(({
sourceCode,
jsdoc,
report,
utils,
context,
settings,
jsdocNode
}) => {
const {
definedTags = [],
jsxTags
} = context.options[0] || {};
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(preferredType => {
return preferredType;
});
}
jsdoc.tags.forEach(jsdocTag => {
const tagName = jsdocTag.tag;
if (jsxTags && jsxTagNames.has(tagName)) {
return;
}
if (utils.isValidTag(tagName, [...definedTags, ...definedPreferredTags, ...definedNonPreferredTags, ...definedStructuredTags])) {
let preferredTagName = utils.getPreferredTagName({
allowObjectReturn: true,
defaultMessage: `Blacklisted tag found (\`@${tagName}\`)`,
tagName
});
if (!preferredTagName) {
return;
}
let message;
if (typeof preferredTagName === 'object') {
({
message,
replacement: preferredTagName
} = 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(`@${_lodash.default.escapeRegExp(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#eslint-plugin-jsdoc-rules-check-tag-names'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
definedTags: {
items: {
type: 'string'
},
type: 'array'
},
jsxTags: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkTagNames.js.map
File diff suppressed because one or more lines are too long
+267
View File
@@ -0,0 +1,267 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsdocTypePrattParser = require("jsdoc-type-pratt-parser");
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const strictNativeTypes = ['undefined', 'null', 'boolean', 'number', 'bigint', 'string', 'symbol', 'object', 'Array', 'Function', 'Date', 'RegExp'];
const adjustNames = (type, preferred, isGenericMatch, nodeName, node, parentNode) => {
let ret = preferred;
if (isGenericMatch) {
if (preferred === '[]') {
parentNode.meta.brackets = 'square';
parentNode.meta.dot = false;
ret = 'Array';
} else {
const dotBracketEnd = preferred.match(/\.(?:<>)?$/u);
if (dotBracketEnd) {
parentNode.meta.brackets = 'angle';
parentNode.meta.dot = true;
ret = preferred.slice(0, -dotBracketEnd[0].length);
} else {
const bracketEnd = preferred.endsWith('<>');
if (bracketEnd) {
parentNode.meta.brackets = 'angle';
parentNode.meta.dot = false;
ret = preferred.slice(0, -2);
} else if (parentNode.meta.brackets === 'square' && (nodeName === '[]' || nodeName === 'Array')) {
parentNode.meta.brackets = 'angle';
parentNode.meta.dot = false;
}
}
}
} else if (type === 'JsdocTypeAny') {
node.type = 'JsdocTypeName';
}
node.value = ret.replace(/(?:\.|<>|\.<>|\[\])$/u, ''); // For bare pseudo-types like `<>`
if (!ret) {
node.value = nodeName;
}
};
var _default = (0, _iterateJsdoc.default)(({
jsdocNode,
sourceCode,
report,
utils,
settings,
context
}) => {
const jsdocTagsWithPossibleType = utils.filterTags(tag => {
return utils.tagMightHaveTypePosition(tag.tag);
});
const {
preferredTypes,
structuredTags,
mode
} = settings;
const {
noDefaults,
unifyParentAndChildTypeChecks,
exemptTagContexts = []
} = context.options[0] || {};
const getPreferredTypeInfo = (_type, nodeName, parentNode, property) => {
let hasMatchingPreferredType;
let isGenericMatch;
let typeName = nodeName;
if (Object.keys(preferredTypes).length) {
const isNameOfGeneric = parentNode !== undefined && parentNode.type === 'JsdocTypeGeneric' && property === 'left';
if (unifyParentAndChildTypeChecks || isNameOfGeneric) {
var _parentNode$meta, _parentNode$meta2;
const brackets = parentNode === null || parentNode === void 0 ? void 0 : (_parentNode$meta = parentNode.meta) === null || _parentNode$meta === void 0 ? void 0 : _parentNode$meta.brackets;
const dot = parentNode === null || parentNode === void 0 ? 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[nodeName + checkPostFix]) !== undefined) {
typeName += checkPostFix;
return true;
}
return false;
});
}
if (!isGenericMatch && property) {
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[nodeName]) !== undefined && !Object.values(preferredTypes).includes(nodeName);
const unifiedSyntaxParentMatch = property && directNameMatch && unifyParentAndChildTypeChecks;
isGenericMatch = isGenericMatch || unifiedSyntaxParentMatch;
hasMatchingPreferredType = isGenericMatch || directNameMatch && !property;
}
return [hasMatchingPreferredType, typeName, isGenericMatch];
};
jsdocTagsWithPossibleType.forEach(jsdocTag => {
const invalidTypes = [];
let typeAst;
try {
typeAst = mode === 'permissive' ? (0, _jsdocTypePrattParser.tryParse)(jsdocTag.type) : (0, _jsdocTypePrattParser.parse)(jsdocTag.type, mode);
} catch {
return;
}
const tagName = jsdocTag.tag;
(0, _jsdocTypePrattParser.traverse)(typeAst, (node, parentNode, property) => {
const {
type,
value
} = node;
if (!['JsdocTypeName', 'JsdocTypeAny'].includes(type)) {
return;
}
let nodeName = type === 'JsdocTypeAny' ? '*' : value;
const [hasMatchingPreferredType, typeName, isGenericMatch] = getPreferredTypeInfo(type, nodeName, parentNode, property);
let preferred;
let types;
if (hasMatchingPreferredType) {
const preferredSetting = preferredTypes[typeName];
nodeName = typeName === '[]' ? typeName : nodeName;
if (!preferredSetting) {
invalidTypes.push([nodeName]);
} else if (typeof preferredSetting === 'string') {
preferred = preferredSetting;
invalidTypes.push([nodeName, preferred]);
} else if (typeof preferredSetting === 'object') {
preferred = preferredSetting === null || preferredSetting === void 0 ? void 0 : preferredSetting.replacement;
invalidTypes.push([nodeName, preferred, preferredSetting === null || preferredSetting === void 0 ? void 0 : 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(nodeName);
})) {
invalidTypes.push([nodeName, types]);
} else if (!noDefaults && type === 'JsdocTypeName') {
for (const strictNativeType of strictNativeTypes) {
if (strictNativeType === 'object' && mode === 'typescript') {
continue;
}
if (strictNativeType.toLowerCase() === nodeName.toLowerCase() && strictNativeType !== nodeName && (!preferredTypes || (preferredTypes === null || preferredTypes === void 0 ? void 0 : preferredTypes[strictNativeType]) === undefined)) {
preferred = strictNativeType;
invalidTypes.push([nodeName, preferred]);
break;
}
}
} // For fixer
if (preferred) {
adjustNames(type, preferred, isGenericMatch, nodeName, node, parentNode);
}
});
if (invalidTypes.length) {
const fixedType = (0, _jsdocTypePrattParser.stringify)(typeAst);
invalidTypes.forEach(([badType, preferredType = '', message]) => {
const fix = fixer => {
return fixer.replaceText(jsdocNode, sourceCode.getText(jsdocNode).replace(`{${jsdocTag.type}}`, `{${fixedType}}`));
};
const tagValue = jsdocTag.name ? ` "${jsdocTag.name}"` : '';
if (exemptTagContexts.some(({
tag,
types
}) => {
return tag === tagName && (types === true || types.includes(jsdocTag.type));
})) {
return;
}
report(message || `Invalid JSDoc @${tagName}${tagValue} type "${badType}"` + (preferredType ? '; ' : '.') + (preferredType ? `prefer: ${JSON.stringify(preferredType)}.` : ''), preferredType ? fix : null, jsdocTag, message ? {
tagName,
tagValue
} : null);
});
}
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Reports invalid types.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-check-types'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkTypes.js.map
File diff suppressed because one or more lines are too long
+128
View File
@@ -0,0 +1,128 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _semver = _interopRequireDefault(require("semver"));
var _spdxExpressionParse = _interopRequireDefault(require("spdx-expression-parse"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
utils,
report,
context
}) => {
const options = context.options[0] || {};
const {
allowedLicenses = null,
allowedAuthors = null,
numericOnlyVariation = false,
licensePattern = '/([^\n\r]*)/gu'
} = options;
utils.forEachPreferredTag('version', (jsdocParameter, targetTagName) => {
const version = 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);
}
});
if (numericOnlyVariation) {
utils.forEachPreferredTag('variation', (jsdocParameter, targetTagName) => {
const variation = 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 = 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 match = utils.getTagDescription(jsdocParameter).match(licenseRegex);
const license = match && match[1] || match[0];
if (!license.trim()) {
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);
}
}
});
utils.forEachPreferredTag('author', (jsdocParameter, targetTagName) => {
const author = 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#eslint-plugin-jsdoc-rules-check-values'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=checkValues.js.map
File diff suppressed because one or more lines are too long
+72
View File
@@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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']);
const emptyIfNotClosure = new Set(['package', 'private', 'protected', 'public', 'static', // Closure doesn't allow with this casing
'inheritdoc']);
var _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' && emptyIfNotClosure.has(tagName);
});
emptyTags.forEach(tag => {
const content = tag.name || tag.description || tag.type;
if (content.trim()) {
const fix = () => {
utils.setTag(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#eslint-plugin-jsdoc-rules-empty-tags'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
tags: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=emptyTags.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/emptyTags.js"],"names":["defaultEmptyTags","Set","emptyIfNotClosure","settings","jsdoc","utils","emptyTags","filterTags","tag","tagName","has","hasOptionTag","tags","some","mode","forEach","content","name","description","type","trim","fix","setTag","reportJSDoc","checkInternal","checkPrivate","iterateAllJsdocs","meta","docs","url","fixable","schema","additionalProperties","properties","items"],"mappings":";;;;;;;AAAA;;;;AAEA,MAAMA,gBAAgB,GAAG,IAAIC,GAAJ,CAAQ,CAC/B,UAD+B,EACnB,OADmB,EACV,WADU,EACG,QADH,EACa,iBADb,EAE/B,QAF+B,EAErB,OAFqB,EAEZ,UAFY,EAEA,UAFA,EAEY,UAFZ,EAI/B;AACA;AACA,YAN+B,EAQ/B;AACA,UAT+B,CAAR,CAAzB;AAYA,MAAMC,iBAAiB,GAAG,IAAID,GAAJ,CAAQ,CAChC,SADgC,EACrB,SADqB,EACV,WADU,EACG,QADH,EACa,QADb,EAGhC;AACA,YAJgC,CAAR,CAA1B;;eAOe,2BAAa,CAAC;AAC3BE,EAAAA,QAD2B;AAE3BC,EAAAA,KAF2B;AAG3BC,EAAAA;AAH2B,CAAD,KAItB;AACJ,QAAMC,SAAS,GAAGD,KAAK,CAACE,UAAN,CAAiB,CAAC;AAACC,IAAAA,GAAG,EAAEC;AAAN,GAAD,KAAoB;AACrD,WAAOT,gBAAgB,CAACU,GAAjB,CAAqBD,OAArB,KACLJ,KAAK,CAACM,YAAN,CAAmBF,OAAnB,KAA+BL,KAAK,CAACQ,IAAN,CAAWC,IAAX,CAAgB,CAAC;AAACL,MAAAA;AAAD,KAAD,KAAW;AACxD,aAAOA,GAAG,KAAKC,OAAf;AACD,KAF8B,CAD1B,IAILN,QAAQ,CAACW,IAAT,KAAkB,SAAlB,IAA+BZ,iBAAiB,CAACQ,GAAlB,CAAsBD,OAAtB,CAJjC;AAKD,GANiB,CAAlB;AAOAH,EAAAA,SAAS,CAACS,OAAV,CAAmBP,GAAD,IAAS;AACzB,UAAMQ,OAAO,GAAGR,GAAG,CAACS,IAAJ,IAAYT,GAAG,CAACU,WAAhB,IAA+BV,GAAG,CAACW,IAAnD;;AACA,QAAIH,OAAO,CAACI,IAAR,EAAJ,EAAoB;AAClB,YAAMC,GAAG,GAAG,MAAM;AAChBhB,QAAAA,KAAK,CAACiB,MAAN,CAAad,GAAb;AACD,OAFD;;AAGAH,MAAAA,KAAK,CAACkB,WAAN,CAAmB,IAAGf,GAAG,CAACA,GAAI,mBAA9B,EAAkDA,GAAlD,EAAuDa,GAAvD,EAA4D,IAA5D;AACD;AACF,GARD;AASD,CArBc,EAqBZ;AACDG,EAAAA,aAAa,EAAE,IADd;AAEDC,EAAAA,YAAY,EAAE,IAFb;AAGDC,EAAAA,gBAAgB,EAAE,IAHjB;AAIDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJV,MAAAA,WAAW,EAAE,mDADT;AAEJW,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,OAAO,EAAE,MALL;AAMJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,oBAAoB,EAAE,KADxB;AAEEC,MAAAA,UAAU,EAAE;AACVrB,QAAAA,IAAI,EAAE;AACJsB,UAAAA,KAAK,EAAE;AACLf,YAAAA,IAAI,EAAE;AADD,WADH;AAIJA,UAAAA,IAAI,EAAE;AAJF;AADI,OAFd;AAUEA,MAAAA,IAAI,EAAE;AAVR,KADM,CANJ;AAoBJA,IAAAA,IAAI,EAAE;AApBF;AAJL,CArBY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\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]);\n\nconst emptyIfNotClosure = new Set([\n 'package', 'private', 'protected', 'public', 'static',\n\n // Closure doesn't allow with this casing\n 'inheritdoc',\n]);\n\nexport default iterateJsdoc(({\n settings,\n jsdoc,\n utils,\n}) => {\n const emptyTags = utils.filterTags(({tag: tagName}) => {\n return defaultEmptyTags.has(tagName) ||\n utils.hasOptionTag(tagName) && jsdoc.tags.some(({tag}) => {\n return tag === tagName;\n }) ||\n settings.mode !== 'closure' && emptyIfNotClosure.has(tagName);\n });\n emptyTags.forEach((tag) => {\n const content = tag.name || tag.description || tag.type;\n if (content.trim()) {\n const fix = () => {\n utils.setTag(tag);\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#eslint-plugin-jsdoc-rules-empty-tags',\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"],"file":"emptyTags.js"}
+67
View File
@@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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#eslint-plugin-jsdoc-rules-implements-on-classes'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=implementsOnClasses.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/implementsOnClasses.js"],"names":["report","utils","iteratingFunction","isIteratingFunction","hasATag","isConstructor","isVirtualFunction","forEachPreferredTag","tag","contextDefaults","meta","docs","description","url","schema","additionalProperties","properties","contexts","items","anyOf","type","comment","context"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,MAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJ,QAAMC,iBAAiB,GAAGD,KAAK,CAACE,mBAAN,EAA1B;;AAEA,MAAID,iBAAJ,EAAuB;AACrB,QAAID,KAAK,CAACG,OAAN,CAAc,CAChB,OADgB,EAEhB,aAFgB,CAAd,KAIFH,KAAK,CAACI,aAAN,EAJF,EAKE;AACA;AACD;AACF,GATD,MASO,IAAI,CAACJ,KAAK,CAACK,iBAAN,EAAL,EAAgC;AACrC;AACD;;AAEDL,EAAAA,KAAK,CAACM,mBAAN,CAA0B,YAA1B,EAAyCC,GAAD,IAAS;AAC/CR,IAAAA,MAAM,CAAC,gDAAD,EAAmD,IAAnD,EAAyDQ,GAAzD,CAAN;AACD,GAFD;AAGD,CAtBc,EAsBZ;AACDC,EAAAA,eAAe,EAAE,IADhB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,yEADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,oBAAoB,EAAE,KADxB;AAEEC,MAAAA,UAAU,EAAE;AACVC,QAAAA,QAAQ,EAAE;AACRC,UAAAA,KAAK,EAAE;AACLC,YAAAA,KAAK,EAAE,CACL;AACEC,cAAAA,IAAI,EAAE;AADR,aADK,EAIL;AACEL,cAAAA,oBAAoB,EAAE,KADxB;AAEEC,cAAAA,UAAU,EAAE;AACVK,gBAAAA,OAAO,EAAE;AACPD,kBAAAA,IAAI,EAAE;AADC,iBADC;AAIVE,gBAAAA,OAAO,EAAE;AACPF,kBAAAA,IAAI,EAAE;AADC;AAJC,eAFd;AAUEA,cAAAA,IAAI,EAAE;AAVR,aAJK;AADF,WADC;AAoBRA,UAAAA,IAAI,EAAE;AApBE;AADA,OAFd;AA0BEA,MAAAA,IAAI,EAAE;AA1BR,KADM,CALJ;AAmCJA,IAAAA,IAAI,EAAE;AAnCF;AAFL,CAtBY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\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#eslint-plugin-jsdoc-rules-implements-on-classes',\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"],"file":"implementsOnClasses.js"}
+208
View File
@@ -0,0 +1,208 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// If supporting Node >= 10, we could loosen the default to this for the
// initial letter: \\p{Upper}
const matchDescriptionDefault = '^[A-Z`\\d_][\\s\\S]*[.?!`]$';
const stringOrDefault = (value, userDefault) => {
return typeof value === 'string' ? value : userDefault || matchDescriptionDefault;
};
var _default = (0, _iterateJsdoc.default)(({
jsdoc,
report,
context,
utils
}) => {
const {
mainDescription,
matchDescription,
message,
tags
} = context.options[0] || {};
const validateDescription = (description, tag) => {
let mainDescriptionMatch = mainDescription;
let errorMessage = message;
if (typeof mainDescription === 'object') {
mainDescriptionMatch = mainDescription.match;
errorMessage = mainDescription.message;
}
if (!tag && mainDescriptionMatch === false) {
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(description)) {
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
});
}
};
if (jsdoc.description) {
const {
description
} = utils.getDescription();
validateDescription(description.replace(/\s+$/, ''));
}
if (!tags || !Object.keys(tags).length) {
return;
}
const hasOptionTag = tagName => {
return Boolean(tags[tagName]);
};
utils.forEachPreferredTag('description', (matchingJsdocTag, targetTagName) => {
const description = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();
if (hasOptionTag(targetTagName)) {
validateDescription(description, matchingJsdocTag);
}
}, true);
const whitelistedTags = utils.filterTags(({
tag: tagName
}) => {
return hasOptionTag(tagName);
});
const {
tagsWithNames,
tagsWithoutNames
} = utils.getTagsByType(whitelistedTags);
tagsWithNames.some(tag => {
const description = utils.getTagDescription(tag).replace(/^[- ]*/u, '').trim();
return validateDescription(description, tag);
});
tagsWithoutNames.some(tag => {
const description = (tag.name + ' ' + utils.getTagDescription(tag)).trim();
return validateDescription(description, tag);
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Enforces a regular expression pattern on descriptions.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-match-description'
},
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'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=matchDescription.js.map
File diff suppressed because one or more lines are too long
+137
View File
@@ -0,0 +1,137 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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[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;
applicableTags.forEach(tag => {
const allowed = !allowNameRegex || allowNameRegex.test(tag.name);
const disallowed = disallowNameRegex && disallowNameRegex.test(tag.name);
const hasRegex = allowNameRegex || disallowNameRegex;
if (hasRegex && allowed && !disallowed) {
return;
}
if (!hasRegex && reported) {
return;
}
const fixer = () => {
tag.source[0].tokens.name = tag.source[0].tokens.name.replace(disallowNameRegex, replacement);
};
let {
message
} = match[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#eslint-plugin-jsdoc-rules-match-name'
},
fixable: 'code',
schema: [{
additionalProperies: false,
properties: {
match: {
additionalProperies: 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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=matchName.js.map
File diff suppressed because one or more lines are too long
+249
View File
@@ -0,0 +1,249 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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;
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;
['delimiter', 'postDelimiter', 'tag', 'type', 'lineEnd', 'postType', 'postTag', 'name', 'postName', 'description'].forEach(prop => {
finalLineTokens[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#eslint-plugin-jsdoc-rules-multiline-blocks'
},
fixable: 'code',
schema: [{
additionalProperies: 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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=multilineBlocks.js.map
File diff suppressed because one or more lines are too long
+81
View File
@@ -0,0 +1,81 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _lodash = _interopRequireDefault(require("lodash"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
jsdoc,
report,
context,
jsdocNode,
sourceCode,
indent,
utils
}) => {
let always;
if (!jsdoc.description.trim() || !jsdoc.tags.length) {
return;
}
if (_lodash.default.has(context.options, 0)) {
always = context.options[0] === 'always';
} else {
always = true;
}
const {
description,
lastDescriptionLine
} = utils.getDescription();
const descriptionEndsWithANewline = /\n\r?$/.test(description);
if (always) {
if (!descriptionEndsWithANewline) {
const sourceLines = sourceCode.getText(jsdocNode).split('\n');
report('There must be a newline after the description of the JSDoc block.', fixer => {
// Add the new line
const injectedLine = `${indent} *` + (sourceLines[lastDescriptionLine].endsWith('\r') ? '\r' : '');
sourceLines.splice(lastDescriptionLine + 1, 0, injectedLine);
return fixer.replaceText(jsdocNode, sourceLines.join('\n'));
}, {
line: lastDescriptionLine
});
}
} else if (descriptionEndsWithANewline) {
const sourceLines = sourceCode.getText(jsdocNode).split('\n');
report('There must be no newline after the description of the JSDoc block.', fixer => {
// Remove the extra line
sourceLines.splice(lastDescriptionLine, 1);
return fixer.replaceText(jsdocNode, sourceLines.join('\n'));
}, {
line: lastDescriptionLine
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Enforces a consistent padding of the block description.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-newline-after-description'
},
fixable: 'whitespace',
schema: [{
enum: ['always', 'never'],
type: 'string'
}],
type: 'layout'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=newlineAfterDescription.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/newlineAfterDescription.js"],"names":["jsdoc","report","context","jsdocNode","sourceCode","indent","utils","always","description","trim","tags","length","_","has","options","lastDescriptionLine","getDescription","descriptionEndsWithANewline","test","sourceLines","getText","split","fixer","injectedLine","endsWith","splice","replaceText","join","line","iterateAllJsdocs","meta","docs","url","fixable","schema","enum","type"],"mappings":";;;;;;;AAAA;;AACA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,KAD2B;AAE3BC,EAAAA,MAF2B;AAG3BC,EAAAA,OAH2B;AAI3BC,EAAAA,SAJ2B;AAK3BC,EAAAA,UAL2B;AAM3BC,EAAAA,MAN2B;AAO3BC,EAAAA;AAP2B,CAAD,KAQtB;AACJ,MAAIC,MAAJ;;AAEA,MAAI,CAACP,KAAK,CAACQ,WAAN,CAAkBC,IAAlB,EAAD,IAA6B,CAACT,KAAK,CAACU,IAAN,CAAWC,MAA7C,EAAqD;AACnD;AACD;;AAED,MAAIC,gBAAEC,GAAF,CAAMX,OAAO,CAACY,OAAd,EAAuB,CAAvB,CAAJ,EAA+B;AAC7BP,IAAAA,MAAM,GAAGL,OAAO,CAACY,OAAR,CAAgB,CAAhB,MAAuB,QAAhC;AACD,GAFD,MAEO;AACLP,IAAAA,MAAM,GAAG,IAAT;AACD;;AAED,QAAM;AAACC,IAAAA,WAAD;AAAcO,IAAAA;AAAd,MAAqCT,KAAK,CAACU,cAAN,EAA3C;AACA,QAAMC,2BAA2B,GAAI,QAAD,CAAWC,IAAX,CAAgBV,WAAhB,CAApC;;AAEA,MAAID,MAAJ,EAAY;AACV,QAAI,CAACU,2BAAL,EAAkC;AAChC,YAAME,WAAW,GAAGf,UAAU,CAACgB,OAAX,CAAmBjB,SAAnB,EAA8BkB,KAA9B,CAAoC,IAApC,CAApB;AAEApB,MAAAA,MAAM,CAAC,mEAAD,EAAuEqB,KAAD,IAAW;AACrF;AACA,cAAMC,YAAY,GAAI,GAAElB,MAAO,IAAV,IAClBc,WAAW,CAACJ,mBAAD,CAAX,CAAiCS,QAAjC,CAA0C,IAA1C,IAAkD,IAAlD,GAAyD,EADvC,CAArB;AAEAL,QAAAA,WAAW,CAACM,MAAZ,CAAmBV,mBAAmB,GAAG,CAAzC,EAA4C,CAA5C,EAA+CQ,YAA/C;AAEA,eAAOD,KAAK,CAACI,WAAN,CAAkBvB,SAAlB,EAA6BgB,WAAW,CAACQ,IAAZ,CAAiB,IAAjB,CAA7B,CAAP;AACD,OAPK,EAOH;AACDC,QAAAA,IAAI,EAAEb;AADL,OAPG,CAAN;AAUD;AACF,GAfD,MAeO,IAAIE,2BAAJ,EAAiC;AACtC,UAAME,WAAW,GAAGf,UAAU,CAACgB,OAAX,CAAmBjB,SAAnB,EAA8BkB,KAA9B,CAAoC,IAApC,CAApB;AACApB,IAAAA,MAAM,CAAC,oEAAD,EAAwEqB,KAAD,IAAW;AACtF;AACAH,MAAAA,WAAW,CAACM,MAAZ,CAAmBV,mBAAnB,EAAwC,CAAxC;AAEA,aAAOO,KAAK,CAACI,WAAN,CAAkBvB,SAAlB,EAA6BgB,WAAW,CAACQ,IAAZ,CAAiB,IAAjB,CAA7B,CAAP;AACD,KALK,EAKH;AACDC,MAAAA,IAAI,EAAEb;AADL,KALG,CAAN;AAQD;AACF,CAlDc,EAkDZ;AACDc,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJvB,MAAAA,WAAW,EAAE,yDADT;AAEJwB,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,OAAO,EAAE,YALL;AAMJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,IAAI,EAAE,CAAC,QAAD,EAAW,OAAX,CADR;AAEEC,MAAAA,IAAI,EAAE;AAFR,KADM,CANJ;AAYJA,IAAAA,IAAI,EAAE;AAZF;AAFL,CAlDY,C","sourcesContent":["import _ from 'lodash';\nimport iterateJsdoc from '../iterateJsdoc';\n\nexport default iterateJsdoc(({\n jsdoc,\n report,\n context,\n jsdocNode,\n sourceCode,\n indent,\n utils,\n}) => {\n let always;\n\n if (!jsdoc.description.trim() || !jsdoc.tags.length) {\n return;\n }\n\n if (_.has(context.options, 0)) {\n always = context.options[0] === 'always';\n } else {\n always = true;\n }\n\n const {description, lastDescriptionLine} = utils.getDescription();\n const descriptionEndsWithANewline = (/\\n\\r?$/).test(description);\n\n if (always) {\n if (!descriptionEndsWithANewline) {\n const sourceLines = sourceCode.getText(jsdocNode).split('\\n');\n\n report('There must be a newline after the description of the JSDoc block.', (fixer) => {\n // Add the new line\n const injectedLine = `${indent} *` +\n (sourceLines[lastDescriptionLine].endsWith('\\r') ? '\\r' : '');\n sourceLines.splice(lastDescriptionLine + 1, 0, injectedLine);\n\n return fixer.replaceText(jsdocNode, sourceLines.join('\\n'));\n }, {\n line: lastDescriptionLine,\n });\n }\n } else if (descriptionEndsWithANewline) {\n const sourceLines = sourceCode.getText(jsdocNode).split('\\n');\n report('There must be no newline after the description of the JSDoc block.', (fixer) => {\n // Remove the extra line\n sourceLines.splice(lastDescriptionLine, 1);\n\n return fixer.replaceText(jsdocNode, sourceLines.join('\\n'));\n }, {\n line: lastDescriptionLine,\n });\n }\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: 'Enforces a consistent padding of the block description.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-newline-after-description',\n },\n fixable: 'whitespace',\n schema: [\n {\n enum: ['always', 'never'],\n type: 'string',\n },\n ],\n type: 'layout',\n },\n});\n"],"file":"newlineAfterDescription.js"}
+104
View File
@@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _commentParser = require("comment-parser");
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// 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 = (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 = 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)}`);
return tags.length && !tags.some(({
tag
}) => {
return ignore.includes(tag);
});
});
if (!nonJsdocNodes.length) {
return;
}
nonJsdocNodes.forEach(node => {
const report = makeReport(context, node);
const fix = 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#eslint-plugin-jsdoc-rules-no-bad-blocks'
},
fixable: 'code',
schema: [{
additionalProperties: false,
properties: {
ignore: {
items: {
type: 'string'
},
type: 'array'
},
preventAllMultiAsteriskBlocks: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'layout'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=noBadBlocks.js.map
File diff suppressed because one or more lines are too long
+88
View File
@@ -0,0 +1,88 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
context,
utils
}) => {
const {
noOptionalParamNames
} = context.options[0] || {};
const paramTags = utils.getPresentTags(['param', 'arg', 'argument']);
paramTags.forEach(tag => {
if (noOptionalParamNames && tag.optional) {
utils.reportJSDoc(`Optional param names are not permitted on @${tag.tag}.`, tag, () => {
utils.changeTag(tag, {
name: tag.name.replace(/([^=]*)(=.+)?/, '$1')
});
});
} else if (tag.default) {
utils.reportJSDoc(`Defaults are not permitted on @${tag.tag}.`, tag, () => {
utils.changeTag(tag, {
name: tag.name.replace(/([^=]*)(=.+)?/, '[$1]')
});
});
}
});
const defaultTags = utils.getPresentTags(['default', 'defaultvalue']);
defaultTags.forEach(tag => {
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#eslint-plugin-jsdoc-rules-no-defaults'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=noDefaults.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/noDefaults.js"],"names":["context","utils","noOptionalParamNames","options","paramTags","getPresentTags","forEach","tag","optional","reportJSDoc","changeTag","name","replace","default","defaultTags","description","trim","postTag","contextDefaults","meta","docs","url","fixable","schema","additionalProperties","properties","contexts","items","anyOf","type","comment"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,OAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJ,QAAM;AAACC,IAAAA;AAAD,MAAyBF,OAAO,CAACG,OAAR,CAAgB,CAAhB,KAAsB,EAArD;AACA,QAAMC,SAAS,GAAGH,KAAK,CAACI,cAAN,CAAqB,CAAC,OAAD,EAAU,KAAV,EAAiB,UAAjB,CAArB,CAAlB;AACAD,EAAAA,SAAS,CAACE,OAAV,CAAmBC,GAAD,IAAS;AACzB,QAAIL,oBAAoB,IAAIK,GAAG,CAACC,QAAhC,EAA0C;AACxCP,MAAAA,KAAK,CAACQ,WAAN,CAAmB,8CAA6CF,GAAG,CAACA,GAAI,GAAxE,EAA4EA,GAA5E,EAAiF,MAAM;AACrFN,QAAAA,KAAK,CAACS,SAAN,CAAgBH,GAAhB,EAAqB;AACnBI,UAAAA,IAAI,EAAEJ,GAAG,CAACI,IAAJ,CAASC,OAAT,CAAiB,eAAjB,EAAkC,IAAlC;AADa,SAArB;AAGD,OAJD;AAKD,KAND,MAMO,IAAIL,GAAG,CAACM,OAAR,EAAiB;AACtBZ,MAAAA,KAAK,CAACQ,WAAN,CAAmB,kCAAiCF,GAAG,CAACA,GAAI,GAA5D,EAAgEA,GAAhE,EAAqE,MAAM;AACzEN,QAAAA,KAAK,CAACS,SAAN,CAAgBH,GAAhB,EAAqB;AACnBI,UAAAA,IAAI,EAAEJ,GAAG,CAACI,IAAJ,CAASC,OAAT,CAAiB,eAAjB,EAAkC,MAAlC;AADa,SAArB;AAGD,OAJD;AAKD;AACF,GAdD;AAeA,QAAME,WAAW,GAAGb,KAAK,CAACI,cAAN,CAAqB,CAAC,SAAD,EAAY,cAAZ,CAArB,CAApB;AACAS,EAAAA,WAAW,CAACR,OAAZ,CAAqBC,GAAD,IAAS;AAC3B,QAAIA,GAAG,CAACQ,WAAJ,CAAgBC,IAAhB,EAAJ,EAA4B;AAC1Bf,MAAAA,KAAK,CAACQ,WAAN,CAAmB,wCAAuCF,GAAG,CAACA,GAAI,GAAlE,EAAsEA,GAAtE,EAA2E,MAAM;AAC/EN,QAAAA,KAAK,CAACS,SAAN,CAAgBH,GAAhB,EAAqB;AACnBQ,UAAAA,WAAW,EAAE,EADM;AAEnBE,UAAAA,OAAO,EAAE;AAFU,SAArB;AAID,OALD;AAMD;AACF,GATD;AAUD,CAhCc,EAgCZ;AACDC,EAAAA,eAAe,EAAE,IADhB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJL,MAAAA,WAAW,EAAE,0FADT;AAEJM,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,OAAO,EAAE,MALL;AAMJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,oBAAoB,EAAE,KADxB;AAEEC,MAAAA,UAAU,EAAE;AACVC,QAAAA,QAAQ,EAAE;AACRC,UAAAA,KAAK,EAAE;AACLC,YAAAA,KAAK,EAAE,CACL;AACEC,cAAAA,IAAI,EAAE;AADR,aADK,EAIL;AACEL,cAAAA,oBAAoB,EAAE,KADxB;AAEEC,cAAAA,UAAU,EAAE;AACVK,gBAAAA,OAAO,EAAE;AACPD,kBAAAA,IAAI,EAAE;AADC,iBADC;AAIV7B,gBAAAA,OAAO,EAAE;AACP6B,kBAAAA,IAAI,EAAE;AADC;AAJC,eAFd;AAUEA,cAAAA,IAAI,EAAE;AAVR,aAJK;AADF,WADC;AAoBRA,UAAAA,IAAI,EAAE;AApBE,SADA;AAuBV3B,QAAAA,oBAAoB,EAAE;AACpB2B,UAAAA,IAAI,EAAE;AADc;AAvBZ,OAFd;AA6BEA,MAAAA,IAAI,EAAE;AA7BR,KADM,CANJ;AAuCJA,IAAAA,IAAI,EAAE;AAvCF;AAFL,CAhCY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nexport default iterateJsdoc(({\n context,\n utils,\n}) => {\n const {noOptionalParamNames} = context.options[0] || {};\n const paramTags = utils.getPresentTags(['param', 'arg', 'argument']);\n paramTags.forEach((tag) => {\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(/([^=]*)(=.+)?/, '$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(/([^=]*)(=.+)?/, '[$1]'),\n });\n });\n }\n });\n const defaultTags = utils.getPresentTags(['default', 'defaultvalue']);\n defaultTags.forEach((tag) => {\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#eslint-plugin-jsdoc-rules-no-defaults',\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"],"file":"noDefaults.js"}
+144
View File
@@ -0,0 +1,144 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const setDefaults = state => {
if (!state.selectorMap) {
state.selectorMap = {};
}
};
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 = (0, _iterateJsdoc.default)(({
info: {
selector,
comment
},
state
}) => {
setDefaults(state);
incrementSelector(state, selector, comment);
}, {
contextSelected: true,
exit({
context,
state
}) {
if (!context.options.length) {
context.report({
loc: {
start: {
column: 1,
line: 1
}
},
message: 'Rule `no-missing-syntax` is missing a `context` option.'
});
return;
}
setDefaults(state);
const {
contexts
} = context.options[0]; // Report when MISSING
contexts.some(cntxt => {
var _cntxt$context, _cntxt$comment, _cntxt$minimum;
const contextStr = typeof cntxt === 'object' ? (_cntxt$context = cntxt.context) !== null && _cntxt$context !== void 0 ? _cntxt$context : 'any' : cntxt;
const comment = (_cntxt$comment = cntxt === null || cntxt === void 0 ? void 0 : cntxt.comment) !== null && _cntxt$comment !== void 0 ? _cntxt$comment : '';
const contextKey = contextStr === 'any' ? undefined : contextStr;
if ((!state.selectorMap[contextKey] || !state.selectorMap[contextKey][comment] || state.selectorMap[contextKey][comment] < ((_cntxt$minimum = cntxt === null || cntxt === void 0 ? void 0 : cntxt.minimum) !== null && _cntxt$minimum !== void 0 ? _cntxt$minimum : 1)) && (contextStr !== 'any' || Object.values(state.selectorMap).every(cmmnt => {
var _cntxt$minimum2;
return !cmmnt[comment] || cmmnt[comment] < ((_cntxt$minimum2 = cntxt === null || cntxt === void 0 ? void 0 : cntxt.minimum) !== null && _cntxt$minimum2 !== void 0 ? _cntxt$minimum2 : 1);
}))) {
var _cntxt$message;
const message = (_cntxt$message = cntxt === null || cntxt === void 0 ? void 0 : cntxt.message) !== null && _cntxt$message !== void 0 ? _cntxt$message : 'Syntax is required: {{context}}' + (comment ? ' with {{comment}}' : '');
context.report({
data: {
comment,
context: contextStr
},
loc: {
end: {
line: 1
},
start: {
line: 1
}
},
message
});
return true;
}
return false;
});
},
meta: {
docs: {
description: 'Reports when certain comment structures are always expected.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-no-missing-syntax'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=noMissingSyntax.js.map
File diff suppressed because one or more lines are too long
+99
View File
@@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const middleAsterisks = /^[* \t]+/u;
var _default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
utils
}) => {
const {
preventAtEnd = true,
preventAtMiddleLines = true
} = context.options[0] || {};
jsdoc.source.some(({
tokens,
number
}) => {
const {
delimiter,
tag,
name,
type,
description,
end
} = tokens;
if (preventAtMiddleLines && !end && !tag && !type && !name && middleAsterisks.test(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 = isSingleLineBlock ? /\*((?:\*|(?: |\t))*)\*$/u : /((?:\*|(?: |\t))*)\*$/u;
const endingAsterisksAndSpaces = (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#eslint-plugin-jsdoc-rules-no-multi-asterisks'
},
fixable: 'code',
schema: [{
additionalProperies: false,
properties: {
preventAtEnd: {
type: 'boolean'
},
preventAtMiddleLines: {
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=noMultiAsterisks.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/noMultiAsterisks.js"],"names":["middleAsterisks","context","jsdoc","utils","preventAtEnd","preventAtMiddleLines","options","source","some","tokens","number","delimiter","tag","name","type","description","end","test","fix","replace","reportJSDoc","line","isSingleLineBlock","delim","endAsterisks","endingAsterisksAndSpaces","match","trim","endFix","iterateAllJsdocs","meta","docs","url","fixable","schema","additionalProperies","properties"],"mappings":";;;;;;;AAAA;;;;AAEA,MAAMA,eAAe,GAAG,WAAxB;;eAEe,2BAAa,CAAC;AAC3BC,EAAAA,OAD2B;AAE3BC,EAAAA,KAF2B;AAG3BC,EAAAA;AAH2B,CAAD,KAItB;AACJ,QAAM;AACJC,IAAAA,YAAY,GAAG,IADX;AAEJC,IAAAA,oBAAoB,GAAG;AAFnB,MAGFJ,OAAO,CAACK,OAAR,CAAgB,CAAhB,KAAsB,EAH1B;AAKAJ,EAAAA,KAAK,CAACK,MAAN,CAAaC,IAAb,CAAkB,CAAC;AAACC,IAAAA,MAAD;AAASC,IAAAA;AAAT,GAAD,KAAsB;AACtC,UAAM;AACJC,MAAAA,SADI;AACOC,MAAAA,GADP;AACYC,MAAAA,IADZ;AACkBC,MAAAA,IADlB;AACwBC,MAAAA,WADxB;AACqCC,MAAAA;AADrC,QAEFP,MAFJ;;AAGA,QACEJ,oBAAoB,IACpB,CAACW,GADD,IACQ,CAACJ,GADT,IACgB,CAACE,IADjB,IACyB,CAACD,IAD1B,IACkCb,eAAe,CAACiB,IAAhB,CAAqBF,WAArB,CAFpC,EAGE;AACA,YAAMG,GAAG,GAAG,MAAM;AAChBT,QAAAA,MAAM,CAACM,WAAP,GAAqBA,WAAW,CAACI,OAAZ,CAAoBnB,eAApB,EAAqC,EAArC,CAArB;AACD,OAFD;;AAGAG,MAAAA,KAAK,CAACiB,WAAN,CACE,kDADF,EAEE;AACEC,QAAAA,IAAI,EAAEX;AADR,OAFF,EAKEQ,GALF,EAME,IANF;AASA,aAAO,IAAP;AACD;;AAED,QAAI,CAACd,YAAD,IAAiB,CAACY,GAAtB,EAA2B;AACzB,aAAO,KAAP;AACD;;AAED,UAAMM,iBAAiB,GAAGX,SAAS,KAAK,KAAxC;AACA,UAAMY,KAAK,GAAGD,iBAAiB,GAAG,GAAH,GAASX,SAAxC;AACA,UAAMa,YAAY,GAAGF,iBAAiB,GACpC,0BADoC,GAEpC,wBAFF;AAIA,UAAMG,wBAAwB,GAAG,CAACV,WAAW,GAAGQ,KAAf,EAAsBG,KAAtB,CAC/BF,YAD+B,CAAjC;;AAIA,QACE,CAACC,wBAAD,IACA,CAACH,iBAAD,IAAsBG,wBAAwB,CAAC,CAAD,CAA9C,IAAqD,CAACA,wBAAwB,CAAC,CAAD,CAAxB,CAA4BE,IAA5B,EAFxD,EAGE;AACA,aAAO,KAAP;AACD;;AAED,UAAMC,MAAM,GAAG,MAAM;AACnB,UAAI,CAACN,iBAAL,EAAwB;AACtBb,QAAAA,MAAM,CAACE,SAAP,GAAmB,EAAnB;AACD;;AACDF,MAAAA,MAAM,CAACM,WAAP,GAAqB,CAACA,WAAW,GAAGQ,KAAf,EAAsBJ,OAAtB,CAA8BK,YAA9B,EAA4C,EAA5C,CAArB;AACD,KALD;;AAOArB,IAAAA,KAAK,CAACiB,WAAN,CACE,+CADF,EAEE;AACEC,MAAAA,IAAI,EAAEX;AADR,KAFF,EAKEkB,MALF,EAME,IANF;AASA,WAAO,IAAP;AACD,GA7DD;AA8DD,CAxEc,EAwEZ;AACDC,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJhB,MAAAA,WAAW,EAAE,EADT;AAEJiB,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,OAAO,EAAE,MALL;AAMJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,mBAAmB,EAAE,KADvB;AAEEC,MAAAA,UAAU,EAAE;AACVhC,QAAAA,YAAY,EAAE;AACZU,UAAAA,IAAI,EAAE;AADM,SADJ;AAIVT,QAAAA,oBAAoB,EAAE;AACpBS,UAAAA,IAAI,EAAE;AADc;AAJZ,OAFd;AAUEA,MAAAA,IAAI,EAAE;AAVR,KADM,CANJ;AAoBJA,IAAAA,IAAI,EAAE;AApBF;AAFL,CAxEY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nconst middleAsterisks = /^[* \\t]+/u;\n\nexport default iterateJsdoc(({\n context,\n jsdoc,\n utils,\n}) => {\n const {\n preventAtEnd = true,\n preventAtMiddleLines = true,\n } = context.options[0] || {};\n\n jsdoc.source.some(({tokens, number}) => {\n const {\n delimiter, tag, name, type, description, end,\n } = tokens;\n if (\n preventAtMiddleLines &&\n !end && !tag && !type && !name && middleAsterisks.test(description)\n ) {\n const fix = () => {\n tokens.description = description.replace(middleAsterisks, '');\n };\n utils.reportJSDoc(\n 'Should be no multiple asterisks on middle lines.',\n {\n line: number,\n },\n fix,\n true,\n );\n\n return true;\n }\n\n if (!preventAtEnd || !end) {\n return false;\n }\n\n const isSingleLineBlock = delimiter === '/**';\n const delim = isSingleLineBlock ? '*' : delimiter;\n const endAsterisks = isSingleLineBlock ?\n /\\*((?:\\*|(?: |\\t))*)\\*$/u :\n /((?:\\*|(?: |\\t))*)\\*$/u;\n\n const endingAsterisksAndSpaces = (description + delim).match(\n endAsterisks,\n );\n\n if (\n !endingAsterisksAndSpaces ||\n !isSingleLineBlock && endingAsterisksAndSpaces[1] && !endingAsterisksAndSpaces[1].trim()\n ) {\n return false;\n }\n\n const endFix = () => {\n if (!isSingleLineBlock) {\n tokens.delimiter = '';\n }\n tokens.description = (description + delim).replace(endAsterisks, '');\n };\n\n utils.reportJSDoc(\n 'Should be no multiple asterisks on end lines.',\n {\n line: number,\n },\n endFix,\n true,\n );\n\n return true;\n });\n}, {\n iterateAllJsdocs: true,\n meta: {\n docs: {\n description: '',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-no-multi-asterisks',\n },\n fixable: 'code',\n schema: [\n {\n additionalProperies: false,\n properties: {\n preventAtEnd: {\n type: 'boolean',\n },\n preventAtMiddleLines: {\n type: 'boolean',\n },\n },\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"file":"noMultiAsterisks.js"}
+81
View File
@@ -0,0 +1,81 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
context,
info: {
selector,
comment
},
report
}) => {
var _foundContext$context, _foundContext$message;
if (!context.options.length) {
report('Rule `no-restricted-syntax` is missing a `context` option.');
return;
}
const {
contexts
} = context.options[0];
const foundContext = contexts.find(cntxt => {
return cntxt === selector || typeof cntxt === 'object' && (!cntxt.context || cntxt.context === 'any' || selector === cntxt.context) && comment === cntxt.comment;
});
const contextStr = typeof foundContext === 'object' ? (_foundContext$context = foundContext.context) !== null && _foundContext$context !== void 0 ? _foundContext$context : 'any' : foundContext;
const message = (_foundContext$message = foundContext === null || foundContext === void 0 ? void 0 : foundContext.message) !== null && _foundContext$message !== void 0 ? _foundContext$message : 'Syntax is restricted: {{context}}.';
report(message, null, null, {
context: contextStr
});
}, {
contextSelected: true,
meta: {
docs: {
description: 'Reports when certain comment structures are present.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-no-restricted-syntax'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=noRestrictedSyntax.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/noRestrictedSyntax.js"],"names":["context","info","selector","comment","report","options","length","contexts","foundContext","find","cntxt","contextStr","message","contextSelected","meta","docs","description","url","fixable","schema","additionalProperties","properties","items","anyOf","type","required"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,OAD2B;AAE3BC,EAAAA,IAAI,EAAE;AAACC,IAAAA,QAAD;AAAWC,IAAAA;AAAX,GAFqB;AAG3BC,EAAAA;AAH2B,CAAD,KAItB;AAAA;;AACJ,MAAI,CAACJ,OAAO,CAACK,OAAR,CAAgBC,MAArB,EAA6B;AAC3BF,IAAAA,MAAM,CAAC,4DAAD,CAAN;AAEA;AACD;;AACD,QAAM;AAACG,IAAAA;AAAD,MAAaP,OAAO,CAACK,OAAR,CAAgB,CAAhB,CAAnB;AAEA,QAAMG,YAAY,GAAGD,QAAQ,CAACE,IAAT,CAAeC,KAAD,IAAW;AAC5C,WAAOA,KAAK,KAAKR,QAAV,IACL,OAAOQ,KAAP,KAAiB,QAAjB,KACC,CAACA,KAAK,CAACV,OAAP,IAAkBU,KAAK,CAACV,OAAN,KAAkB,KAApC,IAA6CE,QAAQ,KAAKQ,KAAK,CAACV,OADjE,KAEEG,OAAO,KAAKO,KAAK,CAACP,OAHtB;AAID,GALoB,CAArB;AAOA,QAAMQ,UAAU,GAAG,OAAOH,YAAP,KAAwB,QAAxB,4BACjBA,YAAY,CAACR,OADI,yEACO,KADP,GAEjBQ,YAFF;AAGA,QAAMI,OAAO,4BAAGJ,YAAH,aAAGA,YAAH,uBAAGA,YAAY,CAAEI,OAAjB,yEACX,oCADF;AAGAR,EAAAA,MAAM,CAACQ,OAAD,EAAU,IAAV,EAAgB,IAAhB,EAAsB;AAC1BZ,IAAAA,OAAO,EAAEW;AADiB,GAAtB,CAAN;AAGD,CA5Bc,EA4BZ;AACDE,EAAAA,eAAe,EAAE,IADhB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,sDADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,OAAO,EAAE,MALL;AAMJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,oBAAoB,EAAE,KADxB;AAEEC,MAAAA,UAAU,EAAE;AACVd,QAAAA,QAAQ,EAAE;AACRe,UAAAA,KAAK,EAAE;AACLC,YAAAA,KAAK,EAAE,CACL;AACEC,cAAAA,IAAI,EAAE;AADR,aADK,EAIL;AACEJ,cAAAA,oBAAoB,EAAE,KADxB;AAEEC,cAAAA,UAAU,EAAE;AACVlB,gBAAAA,OAAO,EAAE;AACPqB,kBAAAA,IAAI,EAAE;AADC,iBADC;AAIVxB,gBAAAA,OAAO,EAAE;AACPwB,kBAAAA,IAAI,EAAE;AADC,iBAJC;AAOVZ,gBAAAA,OAAO,EAAE;AACPY,kBAAAA,IAAI,EAAE;AADC;AAPC,eAFd;AAaEA,cAAAA,IAAI,EAAE;AAbR,aAJK;AADF,WADC;AAuBRA,UAAAA,IAAI,EAAE;AAvBE;AADA,OAFd;AA6BEC,MAAAA,QAAQ,EAAE,CAAC,UAAD,CA7BZ;AA8BED,MAAAA,IAAI,EAAE;AA9BR,KADM,CANJ;AAwCJA,IAAAA,IAAI,EAAE;AAxCF;AAFL,CA5BY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nexport default iterateJsdoc(({\n context,\n info: {selector, comment},\n report,\n}) => {\n if (!context.options.length) {\n report('Rule `no-restricted-syntax` is missing a `context` option.');\n\n return;\n }\n const {contexts} = context.options[0];\n\n const foundContext = contexts.find((cntxt) => {\n return cntxt === selector ||\n typeof cntxt === 'object' &&\n (!cntxt.context || cntxt.context === 'any' || selector === cntxt.context) &&\n comment === cntxt.comment;\n });\n\n const contextStr = typeof foundContext === 'object' ?\n foundContext.context ?? 'any' :\n foundContext;\n const message = foundContext?.message ??\n 'Syntax is restricted: {{context}}.';\n\n report(message, null, null, {\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#eslint-plugin-jsdoc-rules-no-restricted-syntax',\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: ['contexts'],\n type: 'object',\n },\n ],\n type: 'suggestion',\n },\n});\n"],"file":"noRestrictedSyntax.js"}
+73
View File
@@ -0,0 +1,73 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const removeType = ({
tokens
}) => {
tokens.postTag = '';
tokens.type = '';
};
var _default = (0, _iterateJsdoc.default)(({
utils
}) => {
if (!utils.isIteratingFunction() && !utils.isVirtualFunction()) {
return;
}
const tags = utils.getPresentTags(['param', 'arg', 'argument', 'returns', 'return']);
tags.forEach(tag => {
if (tag.type) {
utils.reportJSDoc(`Types are not permitted on @${tag.tag}.`, tag, () => {
tag.source.forEach(removeType);
});
}
});
}, {
contextDefaults: true,
meta: {
docs: {
description: 'This rule reports types being used on `@param` or `@returns`.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-no-types'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=noTypes.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/noTypes.js"],"names":["removeType","tokens","postTag","type","utils","isIteratingFunction","isVirtualFunction","tags","getPresentTags","forEach","tag","reportJSDoc","source","contextDefaults","meta","docs","description","url","fixable","schema","additionalProperties","properties","contexts","items","anyOf","comment","context"],"mappings":";;;;;;;AAAA;;;;AAEA,MAAMA,UAAU,GAAG,CAAC;AAACC,EAAAA;AAAD,CAAD,KAAc;AAC/BA,EAAAA,MAAM,CAACC,OAAP,GAAiB,EAAjB;AACAD,EAAAA,MAAM,CAACE,IAAP,GAAc,EAAd;AACD,CAHD;;eAKe,2BAAa,CAAC;AAC3BC,EAAAA;AAD2B,CAAD,KAEtB;AACJ,MAAI,CAACA,KAAK,CAACC,mBAAN,EAAD,IAAgC,CAACD,KAAK,CAACE,iBAAN,EAArC,EAAgE;AAC9D;AACD;;AAED,QAAMC,IAAI,GAAGH,KAAK,CAACI,cAAN,CAAqB,CAAC,OAAD,EAAU,KAAV,EAAiB,UAAjB,EAA6B,SAA7B,EAAwC,QAAxC,CAArB,CAAb;AAEAD,EAAAA,IAAI,CAACE,OAAL,CAAcC,GAAD,IAAS;AACpB,QAAIA,GAAG,CAACP,IAAR,EAAc;AACZC,MAAAA,KAAK,CAACO,WAAN,CAAmB,+BAA8BD,GAAG,CAACA,GAAI,GAAzD,EAA6DA,GAA7D,EAAkE,MAAM;AACtEA,QAAAA,GAAG,CAACE,MAAJ,CAAWH,OAAX,CAAmBT,UAAnB;AACD,OAFD;AAGD;AACF,GAND;AAOD,CAhBc,EAgBZ;AACDa,EAAAA,eAAe,EAAE,IADhB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,+DADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,OAAO,EAAE,MALL;AAMJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,oBAAoB,EAAE,KADxB;AAEEC,MAAAA,UAAU,EAAE;AACVC,QAAAA,QAAQ,EAAE;AACRC,UAAAA,KAAK,EAAE;AACLC,YAAAA,KAAK,EAAE,CACL;AACErB,cAAAA,IAAI,EAAE;AADR,aADK,EAIL;AACEiB,cAAAA,oBAAoB,EAAE,KADxB;AAEEC,cAAAA,UAAU,EAAE;AACVI,gBAAAA,OAAO,EAAE;AACPtB,kBAAAA,IAAI,EAAE;AADC,iBADC;AAIVuB,gBAAAA,OAAO,EAAE;AACPvB,kBAAAA,IAAI,EAAE;AADC;AAJC,eAFd;AAUEA,cAAAA,IAAI,EAAE;AAVR,aAJK;AADF,WADC;AAoBRA,UAAAA,IAAI,EAAE;AApBE;AADA,OAFd;AA0BEA,MAAAA,IAAI,EAAE;AA1BR,KADM,CANJ;AAoCJA,IAAAA,IAAI,EAAE;AApCF;AAFL,CAhBY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nconst removeType = ({tokens}) => {\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(['param', 'arg', 'argument', 'returns', 'return']);\n\n tags.forEach((tag) => {\n if (tag.type) {\n utils.reportJSDoc(`Types are not permitted on @${tag.tag}.`, tag, () => {\n tag.source.forEach(removeType);\n });\n }\n });\n}, {\n contextDefaults: true,\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#eslint-plugin-jsdoc-rules-no-types',\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"],"file":"noTypes.js"}
+200
View File
@@ -0,0 +1,200 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _jsdocTypePrattParser = require("jsdoc-type-pratt-parser");
var _lodash = _interopRequireDefault(require("lodash"));
var _iterateJsdoc = _interopRequireWildcard(require("../iterateJsdoc"));
var _jsdocUtils = _interopRequireDefault(require("../jsdocUtils"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const extraTypes = ['null', 'undefined', 'void', 'string', 'boolean', 'object', 'function', 'symbol', 'number', 'bigint', 'NaN', 'Infinity', 'any', '*', 'this', 'true', 'false', 'Array', 'Object', 'RegExp', 'Date', 'Function'];
const stripPseudoTypes = str => {
return str && str.replace(/(?:\.|<>|\.<>|\[\])$/u, '');
};
var _default = (0, _iterateJsdoc.default)(({
context,
node,
report,
settings,
sourceCode,
utils
}) => {
var _globalScope$childSco;
const {
scopeManager
} = sourceCode;
const {
globalScope
} = scopeManager;
const {
definedTypes = []
} = context.options[0] || {};
let definedPreferredTypes = [];
const {
preferredTypes,
structuredTags,
mode
} = settings;
if (Object.keys(preferredTypes).length) {
definedPreferredTypes = 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(preferredType => {
return preferredType;
});
}
const typedefDeclarations = (0, _lodash.default)(context.getAllComments()).filter(comment => {
return comment.value.startsWith('*');
}).map(commentNode => {
return (0, _iterateJsdoc.parseComment)(commentNode, '');
}).flatMap(doc => {
return doc.tags.filter(({
tag
}) => {
return utils.isNamepathDefiningTag(tag);
});
}).map(tag => {
return tag.name;
}).value();
const ancestorNodes = [];
let currentScope = scopeManager.acquire(node);
while (currentScope && currentScope.block.type !== 'Program') {
ancestorNodes.push(currentScope.block);
currentScope = currentScope.upper;
} // `currentScope` may be `null` or `Program`, so in such a case,
// we look to present tags instead
let templateTags = ancestorNodes.length ? (0, _lodash.default)(ancestorNodes).flatMap(ancestorNode => {
const commentNode = (0, _jsdoccomment.getJSDocComment)(sourceCode, ancestorNode, settings);
if (!commentNode) {
return [];
}
const jsdoc = (0, _iterateJsdoc.parseComment)(commentNode, '');
return _jsdocUtils.default.filterTags(jsdoc.tags, tag => {
return 'template' === tag.tag;
});
}).value() : utils.getPresentTags('template');
const classJsdoc = utils.getClassJsdoc();
if (classJsdoc !== null && classJsdoc !== void 0 && classJsdoc.tags) {
templateTags = templateTags.concat(classJsdoc.tags.filter(({
tag
}) => {
return tag === 'template';
}));
}
const closureGenericTypes = _lodash.default.flatMap(templateTags, 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 ? void 0 : _globalScope$childSco.block.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 ? _lodash.default.flatMap(globalScope.childScopes, ({
variables
}) => {
return variables;
}, []).map(({
name
}) => {
return name;
}) : []).concat(extraTypes).concat(typedefDeclarations).concat(definedTypes).concat(definedPreferredTypes).concat(settings.mode === 'jsdoc' ? [] : closureGenericTypes));
const jsdocTagsWithPossibleType = utils.filterTags(({
tag
}) => {
return utils.tagMightHaveTypePosition(tag);
});
jsdocTagsWithPossibleType.forEach(tag => {
let parsedType;
try {
parsedType = mode === 'permissive' ? (0, _jsdocTypePrattParser.tryParse)(tag.type) : (0, _jsdocTypePrattParser.parse)(tag.type, mode);
} catch {
// On syntax error, will be handled by valid-types.
return;
}
(0, _jsdocTypePrattParser.traverse)(parsedType, ({
type,
value
}) => {
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))) {
report(`The type '${value}' is undefined.`, null, tag);
} else if (!extraTypes.includes(value)) {
context.markVariableAsUsed(value);
}
}
});
});
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Checks that types in jsdoc comments are defined.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-no-undefined-types'
},
schema: [{
additionalProperties: false,
properties: {
definedTypes: {
items: {
type: 'string'
},
type: 'array'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=noUndefinedTypes.js.map
File diff suppressed because one or more lines are too long
+167
View File
@@ -0,0 +1,167 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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';
let currentTag;
source.some(({
number,
tokens
}) => {
var _tagMap$any2;
const {
delimiter,
tag,
end,
description
} = tokens;
const neverFix = () => {
tokens.delimiter = '';
tokens.postDelimiter = '';
};
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;
};
const alwaysFix = () => {
if (!tokens.start) {
tokens.start = indent + ' ';
}
tokens.delimiter = '*';
tokens.postDelimiter = tag || description ? ' ' : '';
};
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: {
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireAsteriskPrefix.js.map
File diff suppressed because one or more lines are too long
+151
View File
@@ -0,0 +1,151 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _lodash = _interopRequireDefault(require("lodash"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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' && targetTagName.blocked;
if (isBlocked) {
targetTagName = targetTagName.tagName;
}
const checkDescription = description => {
const exampleContent = _lodash.default.compact(description.trim().split('\n'));
return exampleContent.length;
};
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 ? [] : _lodash.default.filter(jsdoc.tags, {
tag: targetTagName
});
if (!functionExamples.length) {
report(descriptionStyle === 'any' ? `Missing JSDoc block description or @${targetTagName} declaration.` : `Missing JSDoc @${targetTagName} declaration.`);
return;
}
functionExamples.forEach(example => {
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#eslint-plugin-jsdoc-rules-require-description'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireDescription.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,221 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _lodash = _interopRequireDefault(require("lodash"));
var _mainUmd = require("regextras/dist/main-umd");
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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']);
const extractParagraphs = text => {
return text.split(/(?<![;:])\n\n/u);
};
const extractSentences = (text, abbreviationsRegex) => {
const txt = text // Remove all {} tags.
.replace(/\{[\s\S]*?\}\s*/gu, '') // Remove custom abbreviations
.replace(abbreviationsRegex, '');
const sentenceEndGrouping = /([.?!])(?:\s+|$)/u;
const puncts = (0, _mainUmd.RegExtras)(sentenceEndGrouping).map(txt, punct => {
return punct;
});
return txt.split(/[.?!](?:\s+|$)/u) // Re-add the dot.
.map((sentence, idx) => {
return /^\s*$/u.test(sentence) ? sentence : `${sentence}${puncts[idx] || ''}`;
});
};
const isNewLinePrecededByAPeriod = text => {
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;
});
};
const isCapitalized = str => {
return str[0] === str[0].toUpperCase();
};
const isTable = str => {
return str.charAt() === '|';
};
const capitalize = str => {
return str.charAt(0).toUpperCase() + str.slice(1);
};
const validateDescription = (description, reportOrig, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd) => {
if (!description) {
return false;
}
const paragraphs = extractParagraphs(description);
return paragraphs.some((paragraph, parIdx) => {
const sentences = extractSentences(paragraph, abbreviationsRegex);
const fix = fixer => {
let text = sourceCode.getText(jsdocNode);
if (!/[.:?!]$/u.test(paragraph)) {
const line = paragraph.split('\n').pop();
text = text.replace(new RegExp(`${_lodash.default.escapeRegExp(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.tag) {
const reg = new RegExp(`(@${_lodash.default.escapeRegExp(tag.tag)}.*)${_lodash.default.escapeRegExp(beginning)}`, 'u');
text = text.replace(reg, (_$0, $1) => {
return $1 + capitalize(beginning);
});
} else {
text = text.replace(new RegExp('((?:[.!?]|\\*|\\})\\s*)' + _lodash.default.escapeRegExp(beginning), 'u'), '$1' + capitalize(beginning));
}
}
return fixer.replaceText(jsdocNode, text);
};
const report = (msg, fixer, tagObj) => {
if ('line' in tagObj) {
tagObj.line += parIdx * 2;
} else {
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 !/^\s*$/u.test(sentence) && !isCapitalized(sentence) && !isTable(sentence);
})) {
report('Sentence should start with an uppercase character.', fix, tag);
}
const paragraphNoAbbreviations = paragraph.replace(abbreviationsRegex, '');
if (!/[.!?|]\s*$/u.test(paragraphNoAbbreviations)) {
report('Sentence 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 preceding line does not end the sentence.', null, tag);
return true;
}
return false;
});
};
var _default = (0, _iterateJsdoc.default)(({
sourceCode,
context,
jsdoc,
report,
jsdocNode,
utils
}) => {
const options = context.options[0] || {};
const {
abbreviations = [],
newlineBeforeCapsAssumesBadSentenceEnd = false
} = options;
const abbreviationsRegex = abbreviations.length ? new RegExp('\\b' + abbreviations.map(abbreviation => {
return _lodash.default.escapeRegExp(abbreviation.replace(/\.$/g, '') + '.');
}).join('|') + '(?:$|\\s)', 'gu') : '';
const {
description
} = utils.getDescription();
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 = _lodash.default.trimStart(utils.getTagDescription(tag), '- ').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#eslint-plugin-jsdoc-rules-require-description-complete-sentence'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireDescriptionCompleteSentence.js.map
File diff suppressed because one or more lines are too long
+112
View File
@@ -0,0 +1,112 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _lodash = _interopRequireDefault(require("lodash"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
context,
jsdoc,
report,
utils
}) => {
if (utils.avoidDocs()) {
return;
}
const {
exemptNoArguments = false
} = context.options[0] || {};
const targetTagName = 'example';
const functionExamples = _lodash.default.filter(jsdoc.tags, {
tag: targetTagName
});
if (!functionExamples.length) {
if (exemptNoArguments && utils.isIteratingFunction() && !utils.hasParams()) {
return;
}
utils.reportJSDoc(`Missing JSDoc @${targetTagName} declaration.`, null, () => {
utils.addTag(targetTagName);
});
return;
}
functionExamples.forEach(example => {
const exampleContent = _lodash.default.compact(`${example.name} ${utils.getTagDescription(example)}`.trim().split('\n'));
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#eslint-plugin-jsdoc-rules-require-example'
},
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'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
},
exemptNoArguments: {
default: false,
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireExample.js.map
File diff suppressed because one or more lines are too long
+147
View File
@@ -0,0 +1,147 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const defaultTags = {
file: {
initialCommentsOnly: true,
mustExist: true,
preventDuplicates: true
}
};
const setDefaults = state => {
// First iteration
if (!state.globalTags) {
state.globalTags = {};
state.hasDuplicates = {};
state.hasTag = {};
state.hasNonCommentBeforeTag = {};
}
};
var _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 = utils.getPreferredTagName({
tagName
});
const hasTag = 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 && obj.blocked) {
utils.reportSettings(`\`settings.jsdoc.tagNamePreference\` cannot block @${obj.tagName} ` + 'for the `require-file-overview` rule');
} else {
const targetTagName = obj && 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#eslint-plugin-jsdoc-rules-require-file-overview'
},
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];
}
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireFileOverview.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,124 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
sourceCode,
utils,
report,
context,
jsdoc,
jsdocNode
}) => {
const [mainCircumstance, {
tags
} = {}] = context.options;
const checkHyphens = (jsdocTag, targetTagName, circumstance = mainCircumstance) => {
const always = !circumstance || circumstance === 'always';
const desc = 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 = 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) {
report(`There must be no hyphen before @${targetTagName} description.`, fixer => {
const [unwantedPart] = /^\s*-\s*/u.exec(desc);
const replacement = sourceCode.getText(jsdocNode).replace(desc, desc.slice(unwantedPart.length));
return fixer.replaceText(jsdocNode, replacement);
}, jsdocTag);
}
};
utils.forEachPreferredTag('param', checkHyphens);
if (tags) {
const tagEntries = Object.entries(tags);
tagEntries.forEach(([tagName, circumstance]) => {
if (tagName === '*') {
const preferredParamTag = utils.getPreferredTagName({
tagName: 'param'
});
jsdoc.tags.forEach(({
tag
}) => {
if (tag === preferredParamTag || tagEntries.some(([tagNme]) => {
return tagNme !== '*' && tagNme === tag;
})) {
return;
}
utils.forEachPreferredTag(tag, (jsdocTag, targetTagName) => {
checkHyphens(jsdocTag, targetTagName, circumstance);
});
});
return;
}
utils.forEachPreferredTag(tagName, (jsdocTag, targetTagName) => {
checkHyphens(jsdocTag, targetTagName, circumstance);
});
});
}
}, {
iterateAllJsdocs: true,
meta: {
docs: {
description: 'Requires a hyphen before the `@param` description.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-hyphen-before-param-description'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireHyphenBeforeParamDescription.js.map
File diff suppressed because one or more lines are too long
+378
View File
@@ -0,0 +1,378 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _jsdoccomment = require("@es-joy/jsdoccomment");
var _lodash = _interopRequireDefault(require("lodash"));
var _exportParser = _interopRequireDefault(require("../exportParser"));
var _iterateJsdoc = require("../iterateJsdoc");
var _jsdocUtils = _interopRequireDefault(require("../jsdocUtils"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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'
}
},
type: 'object'
}]
},
type: 'array'
},
enableFixer: {
default: true,
type: 'boolean'
},
exemptEmptyConstructors: {
default: false,
type: 'boolean'
},
exemptEmptyFunctions: {
default: false,
type: 'boolean'
},
fixerMessage: {
default: '',
type: 'string'
},
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'
};
const getOption = (context, baseObject, option, key) => {
if (!_lodash.default.has(context, `options[0][${option}][${key}]`)) {
return baseObject.properties[key].default;
}
return context.options[0][option][key];
};
const getOptions = context => {
const {
publicOnly,
contexts = [],
exemptEmptyConstructors = true,
exemptEmptyFunctions = false,
enableFixer = true,
fixerMessage = ''
} = context.options[0] || {};
return {
contexts,
enableFixer,
exemptEmptyConstructors,
exemptEmptyFunctions,
fixerMessage,
publicOnly: (baseObj => {
if (!publicOnly) {
return false;
}
const properties = {};
Object.keys(baseObj.properties).forEach(prop => {
const opt = getOption(context, baseObj, 'publicOnly', prop);
properties[prop] = opt;
});
return properties;
})(OPTIONS_SCHEMA.properties.publicOnly.oneOf[1]),
require: (baseObj => {
const properties = {};
Object.keys(baseObj.properties).forEach(prop => {
const opt = getOption(context, baseObj, 'require', prop);
properties[prop] = opt;
});
return properties;
})(OPTIONS_SCHEMA.properties.require)
};
};
var _default = {
create(context) {
const sourceCode = context.getSourceCode();
const settings = (0, _iterateJsdoc.getSettings)(context);
if (!settings) {
return {};
}
const {
require: requireOption,
contexts,
publicOnly,
exemptEmptyFunctions,
exemptEmptyConstructors,
enableFixer,
fixerMessage
} = getOptions(context);
const checkJsDoc = (info, handler, node) => {
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 (_jsdocUtils.default.exemptSpeciaMethods({
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 && _jsdocUtils.default.isConstructor(node)) {
const functionParameterNames = _jsdocUtils.default.getFunctionParameterNames(node);
if (!functionParameterNames.length && !_jsdocUtils.default.hasReturnValue(node)) {
return;
}
}
const fix = 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 = (0, _jsdoccomment.getReducedASTNode)(node, sourceCode);
const decorator = (0, _jsdoccomment.getDecorator)(baseNode);
if (decorator) {
baseNode = decorator;
}
const indent = _jsdocUtils.default.getIndent({
text: sourceCode.getText(baseNode, baseNode.loc.start.column)
});
const {
inlineCommentBlock
} = contexts.find(({
context: ctxt
}) => {
return ctxt === node.type;
}) || {};
const insertion = (inlineCommentBlock ? `/** ${fixerMessage}` : `/**\n${indent}*${fixerMessage}\n${indent}`) + `*/${'\n'.repeat(lines)}${indent.slice(0, -1)}`;
return fixer.insertTextBefore(baseNode, insertion);
};
const report = () => {
const loc = {
end: node.loc.start + 1,
start: node.loc.start
};
context.report({
fix: enableFixer ? fix : null,
loc,
messageId: 'missingJsDoc',
node
});
};
if (publicOnly) {
var _publicOnly$ancestors, _publicOnly$esm, _publicOnly$cjs, _publicOnly$window;
const opt = {
ancestorsOnly: Boolean((_publicOnly$ancestors = publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.ancestorsOnly) !== null && _publicOnly$ancestors !== void 0 ? _publicOnly$ancestors : false),
esm: Boolean((_publicOnly$esm = publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.esm) !== null && _publicOnly$esm !== void 0 ? _publicOnly$esm : true),
initModuleExports: Boolean((_publicOnly$cjs = publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.cjs) !== null && _publicOnly$cjs !== void 0 ? _publicOnly$cjs : true),
initWindow: Boolean((_publicOnly$window = publicOnly === null || publicOnly === void 0 ? void 0 : publicOnly.window) !== null && _publicOnly$window !== void 0 ? _publicOnly$window : false)
};
const exported = _exportParser.default.isUncommentedExport(node, sourceCode, opt, settings);
if (exported) {
report();
}
} else {
report();
}
};
const hasOption = prop => {
return requireOption[prop] || contexts.some(ctxt => {
return typeof ctxt === 'object' ? ctxt.context === prop : ctxt === prop;
});
};
return { ..._jsdocUtils.default.getContextObject(_jsdocUtils.default.enforcedContexts(context, []), checkJsDoc),
ArrowFunctionExpression(node) {
if (!hasOption('ArrowFunctionExpression')) {
return;
}
if (['VariableDeclarator', 'AssignmentExpression', 'ExportDefaultDeclaration'].includes(node.parent.type) || ['Property', 'ObjectProperty', 'ClassProperty'].includes(node.parent.type) && node === 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('MethodDefinition') && node.parent.type === 'MethodDefinition') {
checkJsDoc({
isFunctionContext: true
}, null, node);
return;
}
if (!hasOption('FunctionExpression')) {
return;
}
if (['VariableDeclarator', 'AssignmentExpression', 'ExportDefaultDeclaration'].includes(node.parent.type) || ['Property', 'ObjectProperty', 'ClassProperty'].includes(node.parent.type) && node === node.parent.value) {
checkJsDoc({
isFunctionContext: true
}, null, node);
}
}
};
},
meta: {
docs: {
category: 'Stylistic Issues',
description: 'Require JSDoc comments',
recommended: 'true',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-jsdoc'
},
fixable: 'code',
messages: {
missingJsDoc: 'Missing JSDoc comment.'
},
schema: [OPTIONS_SCHEMA],
type: 'suggestion'
}
};
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireJsdoc.js.map
File diff suppressed because one or more lines are too long
+450
View File
@@ -0,0 +1,450 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _lodash = _interopRequireDefault(require("lodash"));
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const rootNamer = (desiredRoots, currentIndex) => {
let name;
let idx = currentIndex;
const incremented = desiredRoots.length <= 1;
if (incremented) {
const base = desiredRoots[0];
const suffix = idx++;
name = `${base}${suffix}`;
} else {
name = desiredRoots.shift();
}
return [name, incremented, () => {
return rootNamer(desiredRoots, idx);
}];
};
var _default = (0, _iterateJsdoc.default)(({
jsdoc,
utils,
context
}) => {
const preferredTagName = utils.getPreferredTagName({
tagName: 'param'
});
if (!preferredTagName) {
return;
}
const jsdocParameterNames = utils.getJsdocTagsDeep(preferredTagName);
const shallowJsdocParameterNames = jsdocParameterNames.filter(tag => {
return !tag.name.includes('.');
}).map((tag, idx) => {
return { ...tag,
idx
};
});
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 checkTypesRegex = utils.getRegexFromString(checkTypesPattern);
const missingTags = [];
const functionParameterNames = utils.getFunctionParameterNames(useDefaultObjectProperties);
const flattenedRoots = utils.flattenRoots(functionParameterNames).names;
const paramIndex = {};
const hasParamIndex = cur => {
return _lodash.default.has(paramIndex, utils.dropPathSegmentQuotes(String(cur)));
};
const getParamIndex = cur => {
return paramIndex[utils.dropPathSegmentQuotes(String(cur))];
};
const setParamIndex = (cur, idx) => {
paramIndex[utils.dropPathSegmentQuotes(String(cur))] = idx;
};
flattenedRoots.forEach((cur, idx) => {
setParamIndex(cur, idx);
});
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 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;
tags.forEach(({
source
}) => {
source.forEach(({
tokens: {
end
}
}) => {
if (!end) {
tagLineCount++;
}
});
});
return tagLineCount;
};
let [nextRootName, incremented, namer] = rootNamer([...unnamedRootBase], autoIncrementBase);
functionParameterNames.forEach((functionParameterName, functionParameterIdx) => {
let inc;
if (Array.isArray(functionParameterName)) {
const matchedJsdoc = shallowJsdocParameterNames[functionParameterIdx] || jsdocParameterNames[functionParameterIdx];
let rootName;
if (functionParameterName[0]) {
rootName = functionParameterName[0];
} else if (matchedJsdoc && matchedJsdoc.name) {
rootName = matchedJsdoc.name;
if (matchedJsdoc.type && matchedJsdoc.type.search(checkTypesRegex) === -1) {
return;
}
} else {
rootName = nextRootName;
inc = incremented;
[nextRootName, incremented, namer] = namer();
}
const {
hasRestElement,
hasPropertyRest,
rests,
names
} = functionParameterName[1];
const notCheckingNames = [];
if (!enableRestElementFixer && hasRestElement) {
return;
}
if (!checkDestructuredRoots) {
return;
}
names.forEach((paramName, idx) => {
// 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) {
return;
}
if (!checkRestProperty && rests[idx]) {
return;
}
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);
})) {
return;
}
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
});
}
});
return;
}
let funcParamName;
let type;
if (typeof functionParameterName === 'object') {
if (!enableRestElementFixer && functionParameterName.restElement) {
return;
}
funcParamName = functionParameterName.name;
type = '{...any}';
} else {
funcParamName = functionParameterName;
}
if (jsdocParameterNames && !jsdocParameterNames.find(({
name
}) => {
return name === funcParamName;
})) {
missingTags.push({
functionParameterIdx: getParamIndex(funcParamName),
functionParameterName: funcParamName,
inc,
type
});
}
});
const fix = ({
functionParameterIdx,
functionParameterName,
remove,
inc,
type
}) => {
if (inc && !enableRootFixer) {
return;
}
const createTokens = (tagIndex, sourceIndex, spliceCount) => {
// console.log(sourceIndex, tagIndex, jsdoc.tags, jsdoc.source);
const tokens = {
number: sourceIndex + 1,
tokens: {
delimiter: '*',
description: '',
end: '',
lineEnd: '',
name: functionParameterName,
newAdd: true,
postDelimiter: ' ',
postName: '',
postTag: ' ',
postType: type ? ' ' : '',
start: jsdoc.source[sourceIndex].tokens.start,
tag: `@${preferredTagName}`,
type: type !== null && type !== void 0 ? type : ''
}
};
jsdoc.tags.splice(tagIndex, spliceCount, {
name: functionParameterName,
newAdd: true,
source: [tokens],
tag: preferredTagName,
type: type !== null && type !== void 0 ? type : ''
});
const firstNumber = jsdoc.source[0].number;
jsdoc.source.splice(sourceIndex, spliceCount, tokens);
jsdoc.source.slice(sourceIndex).forEach((src, idx) => {
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);
}
};
const fixer = () => {
missingTags.forEach(missingTag => {
fix(missingTag);
});
};
if (missingTags.length && jsdoc.source.length === 1) {
utils.makeMultiline();
}
missingTags.forEach(({
functionParameterName
}) => {
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#eslint-plugin-jsdoc-rules-require-param'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireParam.js.map
File diff suppressed because one or more lines are too long
+59
View File
@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {
if (!jsdocParameter.description.trim()) {
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#eslint-plugin-jsdoc-rules-require-param-description'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireParamDescription.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/requireParamDescription.js"],"names":["report","utils","forEachPreferredTag","jsdocParameter","targetTagName","description","trim","name","contextDefaults","meta","docs","url","schema","additionalProperties","properties","contexts","items","anyOf","type","comment","context"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,MAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJA,EAAAA,KAAK,CAACC,mBAAN,CAA0B,OAA1B,EAAmC,CAACC,cAAD,EAAiBC,aAAjB,KAAmC;AACpE,QAAI,CAACD,cAAc,CAACE,WAAf,CAA2BC,IAA3B,EAAL,EAAwC;AACtCN,MAAAA,MAAM,CACH,kBAAiBI,aAAc,KAAID,cAAc,CAACI,IAAK,gBADpD,EAEJ,IAFI,EAGJJ,cAHI,CAAN;AAKD;AACF,GARD;AASD,CAbc,EAaZ;AACDK,EAAAA,eAAe,EAAE,IADhB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJL,MAAAA,WAAW,EAAE,4DADT;AAEJM,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,oBAAoB,EAAE,KADxB;AAEEC,MAAAA,UAAU,EAAE;AACVC,QAAAA,QAAQ,EAAE;AACRC,UAAAA,KAAK,EAAE;AACLC,YAAAA,KAAK,EAAE,CACL;AACEC,cAAAA,IAAI,EAAE;AADR,aADK,EAIL;AACEL,cAAAA,oBAAoB,EAAE,KADxB;AAEEC,cAAAA,UAAU,EAAE;AACVK,gBAAAA,OAAO,EAAE;AACPD,kBAAAA,IAAI,EAAE;AADC,iBADC;AAIVE,gBAAAA,OAAO,EAAE;AACPF,kBAAAA,IAAI,EAAE;AADC;AAJC,eAFd;AAUEA,cAAAA,IAAI,EAAE;AAVR,aAJK;AADF,WADC;AAoBRA,UAAAA,IAAI,EAAE;AApBE;AADA,OAFd;AA0BEA,MAAAA,IAAI,EAAE;AA1BR,KADM,CALJ;AAmCJA,IAAAA,IAAI,EAAE;AAnCF;AAFL,CAbY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {\n if (!jsdocParameter.description.trim()) {\n report(\n `Missing JSDoc @${targetTagName} \"${jsdocParameter.name}\" description.`,\n null,\n jsdocParameter,\n );\n }\n });\n}, {\n contextDefaults: true,\n meta: {\n docs: {\n description: 'Requires that each `@param` tag has a `description` value.',\n url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-param-description',\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"],"file":"requireParamDescription.js"}
+59
View File
@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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#eslint-plugin-jsdoc-rules-require-param-name'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireParamName.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/requireParamName.js"],"names":["report","utils","forEachPreferredTag","jsdocParameter","targetTagName","tag","name","type","contextDefaults","meta","docs","description","url","schema","additionalProperties","properties","contexts","items","anyOf","comment","context"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,MAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJA,EAAAA,KAAK,CAACC,mBAAN,CAA0B,OAA1B,EAAmC,CAACC,cAAD,EAAiBC,aAAjB,KAAmC;AACpE,QAAID,cAAc,CAACE,GAAf,IAAsBF,cAAc,CAACG,IAAf,KAAwB,EAAlD,EAAsD;AACpDN,MAAAA,MAAM,CACH,sCAAqCI,aAAc,IAAGD,cAAc,CAACI,IAAf,KAAwB,EAAxB,GAA6B,MAA7B,GAAsC,KAAM,GAD/F,EAEJ,IAFI,EAGJJ,cAHI,CAAN;AAKD;AACF,GARD;AASD,CAbc,EAaZ;AACDK,EAAAA,eAAe,EAAE,IADhB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,mDADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,oBAAoB,EAAE,KADxB;AAEEC,MAAAA,UAAU,EAAE;AACVC,QAAAA,QAAQ,EAAE;AACRC,UAAAA,KAAK,EAAE;AACLC,YAAAA,KAAK,EAAE,CACL;AACEX,cAAAA,IAAI,EAAE;AADR,aADK,EAIL;AACEO,cAAAA,oBAAoB,EAAE,KADxB;AAEEC,cAAAA,UAAU,EAAE;AACVI,gBAAAA,OAAO,EAAE;AACPZ,kBAAAA,IAAI,EAAE;AADC,iBADC;AAIVa,gBAAAA,OAAO,EAAE;AACPb,kBAAAA,IAAI,EAAE;AADC;AAJC,eAFd;AAUEA,cAAAA,IAAI,EAAE;AAVR,aAJK;AADF,WADC;AAoBRA,UAAAA,IAAI,EAAE;AApBE;AADA,OAFd;AA0BEA,MAAAA,IAAI,EAAE;AA1BR,KADM,CALJ;AAmCJA,IAAAA,IAAI,EAAE;AAnCF;AAFL,CAbY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\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#eslint-plugin-jsdoc-rules-require-param-name',\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"],"file":"requireParamName.js"}
+59
View File
@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
report,
utils
}) => {
utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {
if (!jsdocParameter.type) {
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#eslint-plugin-jsdoc-rules-require-param-type'
},
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'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireParamType.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/requireParamType.js"],"names":["report","utils","forEachPreferredTag","jsdocParameter","targetTagName","type","name","contextDefaults","meta","docs","description","url","schema","additionalProperties","properties","contexts","items","anyOf","comment","context"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,MAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJA,EAAAA,KAAK,CAACC,mBAAN,CAA0B,OAA1B,EAAmC,CAACC,cAAD,EAAiBC,aAAjB,KAAmC;AACpE,QAAI,CAACD,cAAc,CAACE,IAApB,EAA0B;AACxBL,MAAAA,MAAM,CACH,kBAAiBI,aAAc,KAAID,cAAc,CAACG,IAAK,SADpD,EAEJ,IAFI,EAGJH,cAHI,CAAN;AAKD;AACF,GARD;AASD,CAbc,EAaZ;AACDI,EAAAA,eAAe,EAAE,IADhB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,qDADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,MAAM,EAAE,CACN;AACEC,MAAAA,oBAAoB,EAAE,KADxB;AAEEC,MAAAA,UAAU,EAAE;AACVC,QAAAA,QAAQ,EAAE;AACRC,UAAAA,KAAK,EAAE;AACLC,YAAAA,KAAK,EAAE,CACL;AACEZ,cAAAA,IAAI,EAAE;AADR,aADK,EAIL;AACEQ,cAAAA,oBAAoB,EAAE,KADxB;AAEEC,cAAAA,UAAU,EAAE;AACVI,gBAAAA,OAAO,EAAE;AACPb,kBAAAA,IAAI,EAAE;AADC,iBADC;AAIVc,gBAAAA,OAAO,EAAE;AACPd,kBAAAA,IAAI,EAAE;AADC;AAJC,eAFd;AAUEA,cAAAA,IAAI,EAAE;AAVR,aAJK;AADF,WADC;AAoBRA,UAAAA,IAAI,EAAE;AApBE;AADA,OAFd;AA0BEA,MAAAA,IAAI,EAAE;AA1BR,KADM,CALJ;AAmCJA,IAAAA,IAAI,EAAE;AAnCF;AAFL,CAbY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nexport default iterateJsdoc(({\n report,\n utils,\n}) => {\n utils.forEachPreferredTag('param', (jsdocParameter, targetTagName) => {\n if (!jsdocParameter.type) {\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#eslint-plugin-jsdoc-rules-require-param-type',\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"],"file":"requireParamType.js"}
+56
View File
@@ -0,0 +1,56 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _iterateJsdoc.default)(({
utils
}) => {
const propertyAssociatedTags = utils.filterTags(({
tag
}) => {
return ['typedef', 'namespace'].includes(tag);
});
if (!propertyAssociatedTags.length) {
return;
}
const targetTagName = utils.getPreferredTagName({
tagName: 'property'
});
if (utils.hasATag([targetTagName])) {
return;
}
propertyAssociatedTags.forEach(propertyAssociatedTag => {
if (!['object', 'Object', 'PlainObject'].includes(propertyAssociatedTag.type)) {
return;
}
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#eslint-plugin-jsdoc-rules-require-property'
},
fixable: 'code',
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireProperty.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/requireProperty.js"],"names":["utils","propertyAssociatedTags","filterTags","tag","includes","length","targetTagName","getPreferredTagName","tagName","hasATag","forEach","propertyAssociatedTag","type","reportJSDoc","addTag","iterateAllJsdocs","meta","docs","description","url","fixable"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA;AAD2B,CAAD,KAEtB;AACJ,QAAMC,sBAAsB,GAAGD,KAAK,CAACE,UAAN,CAAiB,CAAC;AAACC,IAAAA;AAAD,GAAD,KAAW;AACzD,WAAO,CAAC,SAAD,EAAY,WAAZ,EAAyBC,QAAzB,CAAkCD,GAAlC,CAAP;AACD,GAF8B,CAA/B;;AAGA,MAAI,CAACF,sBAAsB,CAACI,MAA5B,EAAoC;AAClC;AACD;;AACD,QAAMC,aAAa,GAAGN,KAAK,CAACO,mBAAN,CAA0B;AAACC,IAAAA,OAAO,EAAE;AAAV,GAA1B,CAAtB;;AAEA,MAAIR,KAAK,CAACS,OAAN,CAAc,CAACH,aAAD,CAAd,CAAJ,EAAoC;AAClC;AACD;;AAEDL,EAAAA,sBAAsB,CAACS,OAAvB,CAAgCC,qBAAD,IAA2B;AACxD,QAAI,CAAC,CAAC,QAAD,EAAW,QAAX,EAAqB,aAArB,EAAoCP,QAApC,CAA6CO,qBAAqB,CAACC,IAAnE,CAAL,EAA+E;AAC7E;AACD;;AACDZ,IAAAA,KAAK,CAACa,WAAN,CAAmB,kBAAiBP,aAAc,GAAlD,EAAsD,IAAtD,EAA4D,MAAM;AAChEN,MAAAA,KAAK,CAACc,MAAN,CAAaR,aAAb;AACD,KAFD;AAGD,GAPD;AAQD,CAvBc,EAuBZ;AACDS,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,sIADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,OAAO,EAAE,MALL;AAMJR,IAAAA,IAAI,EAAE;AANF;AAFL,CAvBY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\n\nexport default iterateJsdoc(({\n utils,\n}) => {\n const propertyAssociatedTags = utils.filterTags(({tag}) => {\n return ['typedef', 'namespace'].includes(tag);\n });\n if (!propertyAssociatedTags.length) {\n return;\n }\n const targetTagName = utils.getPreferredTagName({tagName: 'property'});\n\n if (utils.hasATag([targetTagName])) {\n return;\n }\n\n propertyAssociatedTags.forEach((propertyAssociatedTag) => {\n if (!['object', 'Object', 'PlainObject'].includes(propertyAssociatedTag.type)) {\n return;\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#eslint-plugin-jsdoc-rules-require-property',\n },\n fixable: 'code',\n type: 'suggestion',\n },\n});\n"],"file":"requireProperty.js"}
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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#eslint-plugin-jsdoc-rules-require-property-description'
},
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requirePropertyDescription.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/requirePropertyDescription.js"],"names":["report","utils","forEachPreferredTag","jsdoc","targetTagName","description","trim","name","iterateAllJsdocs","meta","docs","url","type"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,MAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJA,EAAAA,KAAK,CAACC,mBAAN,CAA0B,UAA1B,EAAsC,CAACC,KAAD,EAAQC,aAAR,KAA0B;AAC9D,QAAI,CAACD,KAAK,CAACE,WAAN,CAAkBC,IAAlB,EAAL,EAA+B;AAC7BN,MAAAA,MAAM,CACH,kBAAiBI,aAAc,KAAID,KAAK,CAACI,IAAK,gBAD3C,EAEJ,IAFI,EAGJJ,KAHI,CAAN;AAKD;AACF,GARD;AASD,CAbc,EAaZ;AACDK,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJL,MAAAA,WAAW,EAAE,+DADT;AAEJM,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJC,IAAAA,IAAI,EAAE;AALF;AAFL,CAbY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\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#eslint-plugin-jsdoc-rules-require-property-description',\n },\n type: 'suggestion',\n },\n});\n"],"file":"requirePropertyDescription.js"}
+34
View File
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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#eslint-plugin-jsdoc-rules-require-property-name'
},
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requirePropertyName.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/requirePropertyName.js"],"names":["report","utils","forEachPreferredTag","jsdoc","targetTagName","tag","name","type","iterateAllJsdocs","meta","docs","description","url"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,MAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJA,EAAAA,KAAK,CAACC,mBAAN,CAA0B,UAA1B,EAAsC,CAACC,KAAD,EAAQC,aAAR,KAA0B;AAC9D,QAAID,KAAK,CAACE,GAAN,IAAaF,KAAK,CAACG,IAAN,KAAe,EAAhC,EAAoC;AAClCN,MAAAA,MAAM,CACH,sCAAqCI,aAAc,IAAGD,KAAK,CAACI,IAAN,KAAe,EAAf,GAAoB,MAApB,GAA6B,KAAM,GADtF,EAEJ,IAFI,EAGJJ,KAHI,CAAN;AAKD;AACF,GARD;AASD,CAbc,EAaZ;AACDK,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,yDADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJL,IAAAA,IAAI,EAAE;AALF;AAFL,CAbY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\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#eslint-plugin-jsdoc-rules-require-property-name',\n },\n type: 'suggestion',\n },\n});\n"],"file":"requirePropertyName.js"}
+34
View File
@@ -0,0 +1,34 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _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#eslint-plugin-jsdoc-rules-require-property-type'
},
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requirePropertyType.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../../src/rules/requirePropertyType.js"],"names":["report","utils","forEachPreferredTag","jsdoc","targetTagName","type","name","iterateAllJsdocs","meta","docs","description","url"],"mappings":";;;;;;;AAAA;;;;eAEe,2BAAa,CAAC;AAC3BA,EAAAA,MAD2B;AAE3BC,EAAAA;AAF2B,CAAD,KAGtB;AACJA,EAAAA,KAAK,CAACC,mBAAN,CAA0B,UAA1B,EAAsC,CAACC,KAAD,EAAQC,aAAR,KAA0B;AAC9D,QAAI,CAACD,KAAK,CAACE,IAAX,EAAiB;AACfL,MAAAA,MAAM,CACH,kBAAiBI,aAAc,KAAID,KAAK,CAACG,IAAK,SAD3C,EAEJ,IAFI,EAGJH,KAHI,CAAN;AAKD;AACF,GARD;AASD,CAbc,EAaZ;AACDI,EAAAA,gBAAgB,EAAE,IADjB;AAEDC,EAAAA,IAAI,EAAE;AACJC,IAAAA,IAAI,EAAE;AACJC,MAAAA,WAAW,EAAE,wDADT;AAEJC,MAAAA,GAAG,EAAE;AAFD,KADF;AAKJN,IAAAA,IAAI,EAAE;AALF;AAFL,CAbY,C","sourcesContent":["import iterateJsdoc from '../iterateJsdoc';\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#eslint-plugin-jsdoc-rules-require-property-type',\n },\n type: 'suggestion',\n },\n});\n"],"file":"requirePropertyType.js"}
+151
View File
@@ -0,0 +1,151 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* 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 {*} 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 = (0, _iterateJsdoc.default)(({
report,
utils,
context
}) => {
const {
forceRequireReturn = false,
forceReturnsWithAsync = 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;
}
const tagName = 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 (forceRequireReturn && (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()) {
report(`Missing JSDoc @${tagName} declaration.`);
}
}, {
contextDefaults: true,
meta: {
docs: {
description: 'Requires returns are documented.',
url: 'https://github.com/gajus/eslint-plugin-jsdoc#eslint-plugin-jsdoc-rules-require-returns'
},
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'
}
},
type: 'object'
}]
},
type: 'array'
},
exemptedBy: {
items: {
type: 'string'
},
type: 'array'
},
forceRequireReturn: {
default: false,
type: 'boolean'
},
forceReturnsWithAsync: {
default: false,
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireReturns.js.map
File diff suppressed because one or more lines are too long
+103
View File
@@ -0,0 +1,103 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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');
};
var _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 = 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;
} // In case a return value is declared in JSDoc, we also expect one in the code.
if ((reportMissingReturnForUndefinedTypes || utils.hasDefinedTypeTag(tags[0])) && !utils.hasValueOrExecutorHasNonEmptyResolveValue(exemptAsync) && (!exemptGenerators || !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#eslint-plugin-jsdoc-rules-require-returns-check'
},
schema: [{
additionalProperties: false,
properties: {
exemptAsync: {
default: true,
type: 'boolean'
},
exemptGenerators: {
type: 'boolean'
},
reportMissingReturnForUndefinedTypes: {
default: false,
type: 'boolean'
}
},
type: 'object'
}],
type: 'suggestion'
}
});
exports.default = _default;
module.exports = exports.default;
//# sourceMappingURL=requireReturnsCheck.js.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