123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- /**
- * @fileoverview Specify the maximum number of statements allowed per line.
- * @author Kenneth Williams
- */
- "use strict";
- //------------------------------------------------------------------------------
- // Requirements
- //------------------------------------------------------------------------------
- const astUtils = require("./utils/ast-utils");
- //------------------------------------------------------------------------------
- // Rule Definition
- //------------------------------------------------------------------------------
- /** @type {import('../shared/types').Rule} */
- module.exports = {
- meta: {
- type: "layout",
- docs: {
- description: "Enforce a maximum number of statements allowed per line",
- recommended: false,
- url: "https://eslint.org/docs/rules/max-statements-per-line"
- },
- schema: [
- {
- type: "object",
- properties: {
- max: {
- type: "integer",
- minimum: 1,
- default: 1
- }
- },
- additionalProperties: false
- }
- ],
- messages: {
- exceed: "This line has {{numberOfStatementsOnThisLine}} {{statements}}. Maximum allowed is {{maxStatementsPerLine}}."
- }
- },
- create(context) {
- const sourceCode = context.getSourceCode(),
- options = context.options[0] || {},
- maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1;
- let lastStatementLine = 0,
- numberOfStatementsOnThisLine = 0,
- firstExtraStatement;
- //--------------------------------------------------------------------------
- // Helpers
- //--------------------------------------------------------------------------
- const SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/u;
- /**
- * Reports with the first extra statement, and clears it.
- * @returns {void}
- */
- function reportFirstExtraStatementAndClear() {
- if (firstExtraStatement) {
- context.report({
- node: firstExtraStatement,
- messageId: "exceed",
- 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
- };
- }
- };
|