| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | /** * @fileoverview Specify the maximum number of statements allowed per line. * @author Kenneth Williams */"use strict";//------------------------------------------------------------------------------// Requirements//------------------------------------------------------------------------------const astUtils = require("../ast-utils");//------------------------------------------------------------------------------// Rule Definition//------------------------------------------------------------------------------module.exports = {    meta: {        docs: {            description: "enforce a maximum number of statements allowed per line",            category: "Stylistic Issues",            recommended: false,            url: "https://eslint.org/docs/rules/max-statements-per-line"        },        schema: [            {                type: "object",                properties: {                    max: {                        type: "integer",                        minimum: 1                    }                },                additionalProperties: false            }        ]    },    create(context) {        const sourceCode = context.getSourceCode(),            options = context.options[0] || {},            maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1,            message = "This line has {{numberOfStatementsOnThisLine}} {{statements}}. Maximum allowed is {{maxStatementsPerLine}}.";        let lastStatementLine = 0,            numberOfStatementsOnThisLine = 0,            firstExtraStatement;        //--------------------------------------------------------------------------        // Helpers        //--------------------------------------------------------------------------        const SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/;        /**         * Reports with the first extra statement, and clears it.         *         * @returns {void}         */        function reportFirstExtraStatementAndClear() {            if (firstExtraStatement) {                context.report({                    node: firstExtraStatement,                    message,                    data: {                        numberOfStatementsOnThisLine,                        maxStatementsPerLine,                        statements: numberOfStatementsOnThisLine === 1 ? "statement" : "statements"                    }                });            }            firstExtraStatement = null;        }        /**         * Gets the actual last token of a given node.         *         * @param {ASTNode} node - A node to get. This is a node except EmptyStatement.         * @returns {Token} The actual last token.         */        function getActualLastToken(node) {            return sourceCode.getLastToken(node, astUtils.isNotSemicolonToken);        }        /**         * Addresses a given node.         * It updates the state of this rule, then reports the node if the node violated this rule.         *         * @param {ASTNode} node - A node to check.         * @returns {void}         */        function enterStatement(node) {            const line = node.loc.start.line;            /*             * Skip to allow non-block statements if this is direct child of control statements.             * `if (a) foo();` is counted as 1.             * But `if (a) foo(); else foo();` should be counted as 2.             */            if (SINGLE_CHILD_ALLOWED.test(node.parent.type) &&                node.parent.alternate !== node            ) {                return;            }            // Update state.            if (line === lastStatementLine) {                numberOfStatementsOnThisLine += 1;            } else {                reportFirstExtraStatementAndClear();                numberOfStatementsOnThisLine = 1;                lastStatementLine = line;            }            // Reports if the node violated this rule.            if (numberOfStatementsOnThisLine === maxStatementsPerLine + 1) {                firstExtraStatement = firstExtraStatement || node;            }        }        /**         * Updates the state of this rule with the end line of leaving node to check with the next statement.         *         * @param {ASTNode} node - A node to check.         * @returns {void}         */        function leaveStatement(node) {            const line = getActualLastToken(node).loc.end.line;            // Update state.            if (line !== lastStatementLine) {                reportFirstExtraStatementAndClear();                numberOfStatementsOnThisLine = 1;                lastStatementLine = line;            }        }        //--------------------------------------------------------------------------        // Public API        //--------------------------------------------------------------------------        return {            BreakStatement: enterStatement,            ClassDeclaration: enterStatement,            ContinueStatement: enterStatement,            DebuggerStatement: enterStatement,            DoWhileStatement: enterStatement,            ExpressionStatement: enterStatement,            ForInStatement: enterStatement,            ForOfStatement: enterStatement,            ForStatement: enterStatement,            FunctionDeclaration: enterStatement,            IfStatement: enterStatement,            ImportDeclaration: enterStatement,            LabeledStatement: enterStatement,            ReturnStatement: enterStatement,            SwitchStatement: enterStatement,            ThrowStatement: enterStatement,            TryStatement: enterStatement,            VariableDeclaration: enterStatement,            WhileStatement: enterStatement,            WithStatement: enterStatement,            ExportNamedDeclaration: enterStatement,            ExportDefaultDeclaration: enterStatement,            ExportAllDeclaration: enterStatement,            "BreakStatement:exit": leaveStatement,            "ClassDeclaration:exit": leaveStatement,            "ContinueStatement:exit": leaveStatement,            "DebuggerStatement:exit": leaveStatement,            "DoWhileStatement:exit": leaveStatement,            "ExpressionStatement:exit": leaveStatement,            "ForInStatement:exit": leaveStatement,            "ForOfStatement:exit": leaveStatement,            "ForStatement:exit": leaveStatement,            "FunctionDeclaration:exit": leaveStatement,            "IfStatement:exit": leaveStatement,            "ImportDeclaration:exit": leaveStatement,            "LabeledStatement:exit": leaveStatement,            "ReturnStatement:exit": leaveStatement,            "SwitchStatement:exit": leaveStatement,            "ThrowStatement:exit": leaveStatement,            "TryStatement:exit": leaveStatement,            "VariableDeclaration:exit": leaveStatement,            "WhileStatement:exit": leaveStatement,            "WithStatement:exit": leaveStatement,            "ExportNamedDeclaration:exit": leaveStatement,            "ExportDefaultDeclaration:exit": leaveStatement,            "ExportAllDeclaration:exit": leaveStatement,            "Program:exit": reportFirstExtraStatementAndClear        };    }};
 |