Skip to content

Commit

Permalink
feat: update no-inner-declarations for class static blocks (#15290)
Browse files Browse the repository at this point in the history
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 de69cec
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 9 deletions.
32 changes: 29 additions & 3 deletions docs/rules/no-inner-declarations.md
Expand Up @@ -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

Expand All @@ -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:
Expand All @@ -96,6 +104,12 @@ function doSomethingElse() {
function doAnotherThing() { }
}

class C {
static {
function doSomething() { }
}
}

if (test) {
asyncCall(id, function (err, data) { });
}
Expand Down Expand Up @@ -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;

Expand All @@ -146,6 +166,12 @@ if (test) {
function doAnotherThing() {
var baz = 81;
}

class C {
static {
var something;
}
}
```

## When Not To Use It
Expand Down
30 changes: 26 additions & 4 deletions lib/rules/no-inner-declarations.js
Expand Up @@ -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",
Expand Down Expand Up @@ -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)
}
});
}
Expand Down
70 changes: 68 additions & 2 deletions tests/lib/rules/no-inner-declarations.js
Expand Up @@ -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
Expand Down Expand Up @@ -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.