Skip to content

Commit

Permalink
Update: no-inner-declarations false negative in non-block (fixes #12222
Browse files Browse the repository at this point in the history
…) (#13062)

* Fix: consistencies for blockstmt no-inner-fn (fix #12222)

* Chore: added some more tests

* Chore: allowing named and default exports and tests

* Chore: simply the check conditions

* Chore: simplify checks and ancestor loop

* Chore: using getUpperFunction to get body

* chore: added tests and minor changes

* Docs: eg for both non-blockstatement

* Chore: right docs example and test refactore
  • Loading branch information
anikethsaha committed Mar 31, 2020
1 parent 6631ef1 commit 85b7254
Show file tree
Hide file tree
Showing 3 changed files with 264 additions and 104 deletions.
9 changes: 9 additions & 0 deletions docs/rules/no-inner-declarations.md
Expand Up @@ -81,6 +81,8 @@ function doSomethingElse() {
function doAnotherThing() { }
}
}

if (foo) function f(){}
```

Examples of **correct** code for this rule with the default `"functions"` option:
Expand All @@ -102,6 +104,8 @@ var fn;
if (test) {
fn = function fnExpression() { };
}

if (foo) var a;
```

### both
Expand All @@ -120,6 +124,11 @@ function doAnotherThing() {
var bar = 81;
}
}


if (foo) var a;

if (foo) function f(){}
```

Examples of **correct** code for this rule with the `"both"` option:
Expand Down
70 changes: 31 additions & 39 deletions lib/rules/no-inner-declarations.js
Expand Up @@ -5,10 +5,19 @@

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const astUtils = require("./utils/ast-utils");

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

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

module.exports = {
meta: {
type: "problem",
Expand All @@ -33,54 +42,37 @@ module.exports = {

create(context) {

/**
* Find the nearest Program or Function ancestor node.
* @returns {Object} Ancestor's type and distance from node.
*/
function nearestBody() {
const ancestors = context.getAncestors();
let ancestor = ancestors.pop(),
generation = 1;

while (ancestor && ["Program", "FunctionDeclaration",
"FunctionExpression", "ArrowFunctionExpression"
].indexOf(ancestor.type) < 0) {
generation += 1;
ancestor = ancestors.pop();
}

return {

// Type of containing ancestor
type: ancestor.type,

// Separation between ancestor and node
distance: generation
};
}

/**
* Ensure that a given node is at a program or function body's root.
* @param {ASTNode} node Declaration node to check.
* @returns {void}
*/
function check(node) {
const body = nearestBody(),
valid = ((body.type === "Program" && body.distance === 1) ||
body.distance === 2);

if (!valid) {
context.report({
node,
messageId: "moveDeclToRoot",
data: {
type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
body: (body.type === "Program" ? "program" : "function body")
}
});
const parent = node.parent;

if (
parent.type === "BlockStatement" && validBlockStatementParent.has(parent.parent.type)
) {
return;
}

if (validParent.has(parent.type)) {
return;
}

const upperFunction = astUtils.getUpperFunction(parent);

context.report({
node,
messageId: "moveDeclToRoot",
data: {
type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
body: (upperFunction === null ? "program" : "function body")
}
});
}


return {

FunctionDeclaration: check,
Expand Down

0 comments on commit 85b7254

Please sign in to comment.