• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Rule to enforce declarations in program or function body root.
3 * @author Brandon Mills
4 */
5
6"use strict";
7
8//------------------------------------------------------------------------------
9// Requirements
10//------------------------------------------------------------------------------
11
12const astUtils = require("./utils/ast-utils");
13
14//------------------------------------------------------------------------------
15// Rule Definition
16//------------------------------------------------------------------------------
17
18const validParent = new Set(["Program", "ExportNamedDeclaration", "ExportDefaultDeclaration"]);
19const validBlockStatementParent = new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
20
21module.exports = {
22    meta: {
23        type: "problem",
24
25        docs: {
26            description: "disallow variable or `function` declarations in nested blocks",
27            category: "Possible Errors",
28            recommended: true,
29            url: "https://eslint.org/docs/rules/no-inner-declarations"
30        },
31
32        schema: [
33            {
34                enum: ["functions", "both"]
35            }
36        ],
37
38        messages: {
39            moveDeclToRoot: "Move {{type}} declaration to {{body}} root."
40        }
41    },
42
43    create(context) {
44
45        /**
46         * Ensure that a given node is at a program or function body's root.
47         * @param {ASTNode} node Declaration node to check.
48         * @returns {void}
49         */
50        function check(node) {
51            const parent = node.parent;
52
53            if (
54                parent.type === "BlockStatement" && validBlockStatementParent.has(parent.parent.type)
55            ) {
56                return;
57            }
58
59            if (validParent.has(parent.type)) {
60                return;
61            }
62
63            const upperFunction = astUtils.getUpperFunction(parent);
64
65            context.report({
66                node,
67                messageId: "moveDeclToRoot",
68                data: {
69                    type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
70                    body: (upperFunction === null ? "program" : "function body")
71                }
72            });
73        }
74
75
76        return {
77
78            FunctionDeclaration: check,
79            VariableDeclaration(node) {
80                if (context.options[0] === "both" && node.kind === "var") {
81                    check(node);
82                }
83            }
84
85        };
86
87    }
88};
89