diff --git a/docs/rules/max-statements.md b/docs/rules/max-statements.md index 6ef87c2f82f..c2a67331063 100644 --- a/docs/rules/max-statements.md +++ b/docs/rules/max-statements.md @@ -112,6 +112,30 @@ let foo = () => { } ``` +Note that this rule does not apply to class static blocks, and that statements in class static blocks do not count as statements in the enclosing function. + +Examples of **correct** code for this rule with `{ "max": 2 }` option: + +```js +/*eslint max-statements: ["error", 2]*/ + +function foo() { + let one; + let two = class { + static { + let three; + let four; + let five; + if (six) { + let seven; + let eight; + let nine; + } + } + }; +} +``` + ### ignoreTopLevelFunctions Examples of additional **correct** code for this rule with the `{ "max": 10 }, { "ignoreTopLevelFunctions": true }` options: diff --git a/lib/rules/max-statements.js b/lib/rules/max-statements.js index 6f48c9218a9..969e40bbd85 100644 --- a/lib/rules/max-statements.js +++ b/lib/rules/max-statements.js @@ -123,6 +123,14 @@ module.exports = { function endFunction(node) { const count = functionStack.pop(); + /* + * This rule does not apply to class static blocks, but we have to track them so + * that stataments in them do not count as statements in the enclosing function. + */ + if (node.type === "StaticBlock") { + return; + } + if (ignoreTopLevelFunctions && functionStack.length === 0) { topLevelFunctions.push({ node, count }); } else { @@ -148,12 +156,14 @@ module.exports = { FunctionDeclaration: startFunction, FunctionExpression: startFunction, ArrowFunctionExpression: startFunction, + StaticBlock: startFunction, BlockStatement: countStatements, "FunctionDeclaration:exit": endFunction, "FunctionExpression:exit": endFunction, "ArrowFunctionExpression:exit": endFunction, + "StaticBlock:exit": endFunction, "Program:exit"() { if (topLevelFunctions.length === 1) { diff --git a/tests/lib/rules/max-statements.js b/tests/lib/rules/max-statements.js index fd939e592cc..decdd8a56dc 100644 --- a/tests/lib/rules/max-statements.js +++ b/tests/lib/rules/max-statements.js @@ -33,7 +33,33 @@ ruleTester.run("max-statements", rule, { { code: "var foo = { thing() { var bar = 1; var baz = 2; } }", options: [2], parserOptions: { ecmaVersion: 6 } }, { code: "var foo = { ['thing']() { var bar = 1; var baz = 2; } }", options: [2], parserOptions: { ecmaVersion: 6 } }, { code: "var foo = { thing: () => { var bar = 1; var baz = 2; } }", options: [2], parserOptions: { ecmaVersion: 6 } }, - { code: "var foo = { thing: function() { var bar = 1; var baz = 2; } }", options: [{ max: 2 }] } + { code: "var foo = { thing: function() { var bar = 1; var baz = 2; } }", options: [{ max: 2 }] }, + + // this rule does not apply to class static blocks, and statements in them should not count as statements in the enclosing function + { code: "class C { static { one; two; three; { four; five; six; } } }", options: [2], parserOptions: { ecmaVersion: 2022 } }, + { code: "function foo() { class C { static { one; two; three; { four; five; six; } } } }", options: [2], parserOptions: { ecmaVersion: 2022 } }, + { code: "class C { static { one; two; three; function foo() { 1; 2; } four; five; six; } }", options: [2], parserOptions: { ecmaVersion: 2022 } }, + { code: "class C { static { { one; two; three; function foo() { 1; 2; } four; five; six; } } }", options: [2], parserOptions: { ecmaVersion: 2022 } }, + { + code: "function top_level() { 1; /* 2 */ class C { static { one; two; three; { four; five; six; } } } 3;}", + options: [2, { ignoreTopLevelFunctions: true }], + parserOptions: { ecmaVersion: 2022 } + }, + { + code: "function top_level() { 1; 2; } class C { static { one; two; three; { four; five; six; } } }", + options: [1, { ignoreTopLevelFunctions: true }], + parserOptions: { ecmaVersion: 2022 } + }, + { + code: "class C { static { one; two; three; { four; five; six; } } } function top_level() { 1; 2; } ", + options: [1, { ignoreTopLevelFunctions: true }], + parserOptions: { ecmaVersion: 2022 } + }, + { + code: "function foo() { let one; let two = class { static { let three; let four; let five; if (six) { let seven; let eight; let nine; } } }; }", + options: [2], + parserOptions: { ecmaVersion: 2022 } + } ], invalid: [ { @@ -143,6 +169,30 @@ ruleTester.run("max-statements", rule, { code: "function foo() { 1; }", options: [{ max: 0 }], errors: [{ messageId: "exceed", data: { name: "Function 'foo'", count: 1, max: 0 } }] + }, + { + code: "function foo() { foo_1; /* foo_ 2 */ class C { static { one; two; three; four; { five; six; seven; eight; } } } foo_3 }", + options: [2], + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "exceed", data: { name: "Function 'foo'", count: 3, max: 2 } }] + }, + { + code: "class C { static { one; two; three; four; function not_top_level() { 1; 2; 3; } five; six; seven; eight; } }", + options: [2, { ignoreTopLevelFunctions: true }], + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "exceed", data: { name: "Function 'not_top_level'", count: 3, max: 2 } }] + }, + { + code: "class C { static { { one; two; three; four; function not_top_level() { 1; 2; 3; } five; six; seven; eight; } } }", + options: [2, { ignoreTopLevelFunctions: true }], + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "exceed", data: { name: "Function 'not_top_level'", count: 3, max: 2 } }] + }, + { + code: "class C { static { { one; two; three; four; } function not_top_level() { 1; 2; 3; } { five; six; seven; eight; } } }", + options: [2, { ignoreTopLevelFunctions: true }], + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "exceed", data: { name: "Function 'not_top_level'", count: 3, max: 2 } }] } ] });