|                                                                                                                                                                                                 |  | /** * @fileoverview enforce a maximum file length * @author Alberto Rodríguez */"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/** * Creates an array of numbers from `start` up to, but not including, `end` * @param {number} start The start of the range * @param {number} end The end of the range * @returns {number[]} The range of numbers */function range(start, end) {    return [...Array(end - start).keys()].map(x => x + start);}
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */module.exports = {    meta: {        type: "suggestion",
        docs: {            description: "Enforce a maximum number of lines per file",            recommended: false,            url: "https://eslint.org/docs/latest/rules/max-lines"        },
        schema: [            {                oneOf: [                    {                        type: "integer",                        minimum: 0                    },                    {                        type: "object",                        properties: {                            max: {                                type: "integer",                                minimum: 0                            },                            skipComments: {                                type: "boolean"                            },                            skipBlankLines: {                                type: "boolean"                            }                        },                        additionalProperties: false                    }                ]            }        ],        messages: {            exceed:                "File has too many lines ({{actual}}). Maximum allowed is {{max}}."        }    },
    create(context) {        const option = context.options[0];        let max = 300;
        if (            typeof option === "object" &&            Object.prototype.hasOwnProperty.call(option, "max")        ) {            max = option.max;        } else if (typeof option === "number") {            max = option;        }
        const skipComments = option && option.skipComments;        const skipBlankLines = option && option.skipBlankLines;
        const sourceCode = context.sourceCode;
        /**         * Returns whether or not a token is a comment node type         * @param {Token} token The token to check         * @returns {boolean} True if the token is a comment node         */        function isCommentNodeType(token) {            return token && (token.type === "Block" || token.type === "Line");        }
        /**         * Returns the line numbers of a comment that don't have any code on the same line         * @param {Node} comment The comment node to check         * @returns {number[]} The line numbers         */        function getLinesWithoutCode(comment) {            let start = comment.loc.start.line;            let end = comment.loc.end.line;
            let token;
            token = comment;            do {                token = sourceCode.getTokenBefore(token, {                    includeComments: true                });            } while (isCommentNodeType(token));
            if (token && astUtils.isTokenOnSameLine(token, comment)) {                start += 1;            }
            token = comment;            do {                token = sourceCode.getTokenAfter(token, {                    includeComments: true                });            } while (isCommentNodeType(token));
            if (token && astUtils.isTokenOnSameLine(comment, token)) {                end -= 1;            }
            if (start <= end) {                return range(start, end + 1);            }            return [];        }
        return {            "Program:exit"() {                let lines = sourceCode.lines.map((text, i) => ({                    lineNumber: i + 1,                    text                }));
                /*                 * If file ends with a linebreak, `sourceCode.lines` will have one extra empty line at the end.                 * That isn't a real line, so we shouldn't count it.                 */                if (lines.length > 1 && lines[lines.length - 1].text === "") {                    lines.pop();                }
                if (skipBlankLines) {                    lines = lines.filter(l => l.text.trim() !== "");                }
                if (skipComments) {                    const comments = sourceCode.getAllComments();
                    const commentLines = new Set(comments.flatMap(getLinesWithoutCode));
                    lines = lines.filter(                        l => !commentLines.has(l.lineNumber)                    );                }
                if (lines.length > max) {                    const loc = {                        start: {                            line: lines[max].lineNumber,                            column: 0                        },                        end: {                            line: sourceCode.lines.length,                            column: sourceCode.lines[sourceCode.lines.length - 1].length                        }                    };
                    context.report({                        loc,                        messageId: "exceed",                        data: {                            max,                            actual: lines.length                        }                    });                }            }        };    }};
 |