Skip to content
Permalink
Browse files
feat: update no-inner-declarations for class static blocks (#15290)
Updates the `no-inner-declarations` rule to allow declarations at the top level of class static blocks.

Refs #15016
  • Loading branch information
mdjermanovic committed Nov 21, 2021
1 parent e2fe7ef commit de69cec834411aeb276a525c11dc10f628df2f51
Showing with 123 additions and 9 deletions.
  1. +29 −3 docs/rules/no-inner-declarations.md
  2. +26 −4 lib/rules/no-inner-declarations.js
  3. +68 −2 tests/lib/rules/no-inner-declarations.js
@@ -56,7 +56,7 @@ function doSomething() {

## Rule Details

This rule requires that function declarations and, optionally, variable declarations be in the root of a program or the body of a function.
This rule requires that function declarations and, optionally, variable declarations be in the root of a program, or in the root of the body of a function, or in the root of the body of a class static block.

## Options

@@ -83,6 +83,14 @@ function doSomethingElse() {
}
if (foo) function f(){}
class C {
static {
if (test) {
function doSomething() { }
}
}
}
```

Examples of **correct** code for this rule with the default `"functions"` option:
@@ -96,6 +104,12 @@ function doSomethingElse() {
function doAnotherThing() { }
}
class C {
static {
function doSomething() { }
}
}
if (test) {
asyncCall(id, function (err, data) { });
}
@@ -125,17 +139,23 @@ function doAnotherThing() {
}
}
if (foo) var a;
if (foo) function f(){}
class C {
static {
if (test) {
var something;
}
}
}
```

Examples of **correct** code for this rule with the `"both"` option:

```js
/*eslint no-inner-declarations: ["error", "both"]*/
/*eslint-env es6*/
var bar = 42;
@@ -146,6 +166,12 @@ if (test) {
function doAnotherThing() {
var baz = 81;
}
class C {
static {
var something;
}
}
```

## When Not To Use It
@@ -15,9 +15,33 @@ const astUtils = require("./utils/ast-utils");
// Rule Definition
//------------------------------------------------------------------------------

const validParent = new Set(["Program", "ExportNamedDeclaration", "ExportDefaultDeclaration"]);
const validParent = new Set(["Program", "StaticBlock", "ExportNamedDeclaration", "ExportDefaultDeclaration"]);
const validBlockStatementParent = new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);

/**
* Finds the nearest enclosing context where this rule allows declarations and returns its description.
* @param {ASTNode} node Node to search from.
* @returns {string} Description. One of "program", "function body", "class static block body".
*/
function getAllowedBodyDescription(node) {
let { parent } = node;

while (parent) {

if (parent.type === "StaticBlock") {
return "class static block body";
}

if (astUtils.isFunction(parent)) {
return "function body";
}

({ parent } = parent);
}

return "program";
}

module.exports = {
meta: {
type: "problem",
@@ -59,14 +83,12 @@ module.exports = {
return;
}

const upperFunction = astUtils.getUpperFunction(parent);

context.report({
node,
messageId: "moveDeclToRoot",
data: {
type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
body: (upperFunction === null ? "program" : "function body")
body: getAllowedBodyDescription(node)
}
});
}
@@ -73,8 +73,27 @@ ruleTester.run("no-inner-declarations", rule, {
{
code: "module.exports = function foo(){}",
options: ["both"]
},
{
code: "class C { method() { function foo() {} } }",
options: ["both"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { method() { var x; } }",
options: ["both"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { static { function foo() {} } }",
options: ["both"],
parserOptions: { ecmaVersion: 2022 }
},
{
code: "class C { static { var x; } }",
options: ["both"],
parserOptions: { ecmaVersion: 2022 }
}

],

// Examples of code that should trigger the rule
@@ -271,7 +290,54 @@ ruleTester.run("no-inner-declarations", rule, {
},
type: "VariableDeclaration"
}]
}, {
code: "class C { method() { if(test) { var foo; } } }",
options: ["both"],
parserOptions: { ecmaVersion: 6 },
errors: [{
messageId: "moveDeclToRoot",
data: {
type: "variable",
body: "function body"
},
type: "VariableDeclaration"
}]
}, {
code: "class C { static { if (test) { function foo() {} } } }",
options: ["both"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "moveDeclToRoot",
data: {
type: "function",
body: "class static block body"
},
type: "FunctionDeclaration"
}]
}, {
code: "class C { static { if (test) { var foo; } } }",
options: ["both"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "moveDeclToRoot",
data: {
type: "variable",
body: "class static block body"
},
type: "VariableDeclaration"
}]
}, {
code: "class C { static { if (test) { if (anotherTest) { var foo; } } } }",
options: ["both"],
parserOptions: { ecmaVersion: 2022 },
errors: [{
messageId: "moveDeclToRoot",
data: {
type: "variable",
body: "class static block body"
},
type: "VariableDeclaration"
}]
}

]
});

0 comments on commit de69cec

Please sign in to comment.