204 lines
5.9 KiB
JavaScript
Executable file
204 lines
5.9 KiB
JavaScript
Executable file
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = void 0;
|
|
|
|
var _lodash = require("lodash");
|
|
|
|
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc"));
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
/**
|
|
* Aux method until we consider the dev envs support `String.prototype.matchAll` (Node 12+).
|
|
*
|
|
* @param {string} string String that will be checked.
|
|
* @param {RegExp} regexp Regular expression to run.
|
|
* @param {Function} callback Function to be called each iteration.
|
|
* @param {int} limit Limit of matches that we want to exec.
|
|
*
|
|
* @todo [engine:node@>=12]: Remove function and use `String.prototype.matchAll` instead.
|
|
*/
|
|
const matchAll = (string, regexp, callback, limit) => {
|
|
let result;
|
|
let index = 0;
|
|
|
|
while ((result = regexp.exec(string)) && index <= limit - 1) {
|
|
// eslint-disable-next-line promise/prefer-await-to-callbacks
|
|
callback(result, index++);
|
|
}
|
|
};
|
|
/**
|
|
* Get the full description from a line.
|
|
*
|
|
* @param {string} lineString The line string.
|
|
*
|
|
* @returns {string} The full description.
|
|
*/
|
|
|
|
|
|
const getFullDescription = lineString => {
|
|
return /(?:\S+\s+){4}(.*)/.exec(lineString)[1];
|
|
};
|
|
/**
|
|
* Get the expected positions for each part.
|
|
*
|
|
* @param {int[]} partsMaxLength Max length of each part.
|
|
* @param {int} indentLevel JSDoc indent level.
|
|
*
|
|
* @returns {int[]} Expected position for each part.
|
|
*/
|
|
|
|
|
|
const getExpectedPositions = (partsMaxLength, indentLevel) => {
|
|
// eslint-disable-next-line unicorn/no-reduce
|
|
return partsMaxLength.reduce((acc, cur, index) => {
|
|
return [...acc, cur + acc[index] + 1];
|
|
}, [indentLevel]);
|
|
};
|
|
/**
|
|
* Check is not aligned.
|
|
*
|
|
* @param {int[]} expectedPositions Expected position for each part.
|
|
* @param {Array[]} partsMatrix Parts matrix.
|
|
*
|
|
* @returns {boolean}
|
|
*/
|
|
|
|
|
|
const isNotAligned = (expectedPositions, partsMatrix) => {
|
|
return partsMatrix.some(line => {
|
|
return line.some(({
|
|
position
|
|
}, partIndex) => {
|
|
return position !== expectedPositions[partIndex];
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Fix function creator for the report. It creates a function which fix
|
|
* the JSDoc with the correct alignment.
|
|
*
|
|
* @param {object} comment Comment node.
|
|
* @param {int[]} expectedPositions Array with the expected positions.
|
|
* @param {Array[]} partsMatrix Parts matrix.
|
|
* @param {RegExp} lineRegExp Line regular expression.
|
|
* @param {string} tagIndentation Tag indentation.
|
|
*
|
|
* @returns {Function} Function which fixes the JSDoc alignment.
|
|
*/
|
|
|
|
|
|
const createFixer = (comment, expectedPositions, partsMatrix, lineRegExp, tagIndentation) => {
|
|
return fixer => {
|
|
let lineIndex = 0; // Replace every line with the correct spacings.
|
|
|
|
const fixed = comment.value.replace(lineRegExp, () => {
|
|
// eslint-disable-next-line unicorn/no-reduce
|
|
return partsMatrix[lineIndex++].reduce((acc, {
|
|
string
|
|
}, index) => {
|
|
const spacings = ' '.repeat(expectedPositions[index] - acc.length);
|
|
return acc + (index === 0 ? tagIndentation : spacings) + string;
|
|
}, '');
|
|
});
|
|
return fixer.replaceText(comment, '/*' + fixed + '*/');
|
|
};
|
|
};
|
|
/**
|
|
* Check comment per tag.
|
|
*
|
|
* @param {object} comment Comment node.
|
|
* @param {string} tag Tag string.
|
|
* @param {string} tagIndentation Tag indentation.
|
|
* @param {Function} report Report function.
|
|
*/
|
|
|
|
|
|
const checkCommentPerTag = (comment, tag, tagIndentation, report) => {
|
|
const lineRegExp = new RegExp(`.*@${tag}[\\s].*`, 'gm');
|
|
const lines = comment.value.match(lineRegExp);
|
|
|
|
if (!lines) {
|
|
return;
|
|
}
|
|
/**
|
|
* A matrix containing the current position and the string of each part for each line.
|
|
* 0 - Asterisk.
|
|
* 1 - Tag.
|
|
* 2 - Type.
|
|
* 3 - Variable name.
|
|
* 4 - Description (Optional).
|
|
*/
|
|
|
|
|
|
const partsMatrix = [];
|
|
/**
|
|
* The max length of each part, comparing all the lines.
|
|
*/
|
|
|
|
const partsMaxLength = []; // Loop (lines x parts) to populate partsMatrix and partsMaxLength.
|
|
|
|
lines.forEach((lineString, lineIndex) => {
|
|
// All line parts until the first word of the description (if description exists).
|
|
matchAll(lineString, /\S+/g, ({
|
|
0: match,
|
|
index: position
|
|
}, partIndex) => {
|
|
(0, _lodash.set)(partsMatrix, [lineIndex, partIndex], {
|
|
position,
|
|
string: partIndex === 4 ? getFullDescription(lineString) : match
|
|
});
|
|
const partLength = match.length;
|
|
const maxLength = partsMaxLength[partIndex];
|
|
partsMaxLength[partIndex] = maxLength > partLength ? maxLength : partLength;
|
|
}, 5);
|
|
});
|
|
const expectedPositions = getExpectedPositions(partsMaxLength, tagIndentation.length);
|
|
|
|
if (isNotAligned(expectedPositions, partsMatrix)) {
|
|
report('Expected JSDoc block lines to be aligned.', createFixer(comment, expectedPositions, partsMatrix, lineRegExp, tagIndentation));
|
|
}
|
|
};
|
|
|
|
var _default = (0, _iterateJsdoc.default)(({
|
|
jsdocNode,
|
|
report,
|
|
context,
|
|
indent
|
|
}) => {
|
|
if (context.options[0] === 'never') {
|
|
report('The `never` option is not yet implemented for this rule.');
|
|
return;
|
|
}
|
|
|
|
if (context.options[0] !== 'always') {
|
|
return;
|
|
} // `indent` is whitespace from line 1 (`/**`), so slice and account for "/".
|
|
|
|
|
|
const tagIndentation = indent + ' ';
|
|
['param', 'arg', 'argument', 'property', 'prop'].forEach(tag => {
|
|
checkCommentPerTag(jsdocNode, tag, tagIndentation, report);
|
|
});
|
|
}, {
|
|
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'
|
|
}],
|
|
type: 'layout'
|
|
}
|
|
});
|
|
|
|
exports.default = _default;
|
|
module.exports = exports.default;
|
|
//# sourceMappingURL=checkLineAlignment.js.map
|