UNPKG

2.65 kBJavaScriptView Raw
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// Rule Definition
10//------------------------------------------------------------------------------
11
12module.exports = {
13 meta: {
14 type: "problem",
15
16 docs: {
17 description: "disallow variable or `function` declarations in nested blocks",
18 category: "Possible Errors",
19 recommended: true,
20 url: "https://eslint.org/docs/rules/no-inner-declarations"
21 },
22
23 schema: [
24 {
25 enum: ["functions", "both"]
26 }
27 ]
28 },
29
30 create(context) {
31
32 /**
33 * Find the nearest Program or Function ancestor node.
34 * @returns {Object} Ancestor's type and distance from node.
35 */
36 function nearestBody() {
37 const ancestors = context.getAncestors();
38 let ancestor = ancestors.pop(),
39 generation = 1;
40
41 while (ancestor && ["Program", "FunctionDeclaration",
42 "FunctionExpression", "ArrowFunctionExpression"
43 ].indexOf(ancestor.type) < 0) {
44 generation += 1;
45 ancestor = ancestors.pop();
46 }
47
48 return {
49
50 // Type of containing ancestor
51 type: ancestor.type,
52
53 // Separation between ancestor and node
54 distance: generation
55 };
56 }
57
58 /**
59 * Ensure that a given node is at a program or function body's root.
60 * @param {ASTNode} node Declaration node to check.
61 * @returns {void}
62 */
63 function check(node) {
64 const body = nearestBody(),
65 valid = ((body.type === "Program" && body.distance === 1) ||
66 body.distance === 2);
67
68 if (!valid) {
69 context.report({
70 node,
71 message: "Move {{type}} declaration to {{body}} root.",
72 data: {
73 type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
74 body: (body.type === "Program" ? "program" : "function body")
75 }
76 });
77 }
78 }
79
80 return {
81
82 FunctionDeclaration: check,
83 VariableDeclaration(node) {
84 if (context.options[0] === "both" && node.kind === "var") {
85 check(node);
86 }
87 }
88
89 };
90
91 }
92};