UNPKG

2.88 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to flag blocks with no reason to exist
3 * @author Brandon Mills
4 * @copyright 2015 Roberto Vidal. All rights reserved.
5 * @copyright 2014 Brandon Mills. All rights reserved.
6 */
7
8"use strict";
9
10//------------------------------------------------------------------------------
11// Rule Definition
12//------------------------------------------------------------------------------
13
14module.exports = function(context) {
15
16 // A stack of lone blocks to be checked for block-level bindings
17 var loneBlocks = [],
18 ruleDef;
19
20 /**
21 * Reports a node as invalid.
22 * @param {ASTNode} node - The node to be reported.
23 * @returns {void}
24 */
25 function report(node) {
26 var parent = context.getAncestors().pop();
27 context.report(node, parent.type === "Program" ?
28 "Block is redundant." :
29 "Nested block is redundant."
30 );
31 }
32
33 /**
34 * Checks for any ocurrence of BlockStatement > BlockStatement or Program > BlockStatement
35 * @returns {boolean} True if the current node is a lone block.
36 */
37 function isLoneBlock() {
38 var parent = context.getAncestors().pop();
39 return parent.type === "BlockStatement" || parent.type === "Program";
40 }
41
42 /**
43 * Checks the enclosing block of the current node for block-level bindings,
44 * and "marks it" as valid if any.
45 * @returns {void}
46 */
47 function markLoneBlock() {
48 if (loneBlocks.length === 0) {
49 return;
50 }
51
52 var block = context.getAncestors().pop();
53
54 if (loneBlocks[loneBlocks.length - 1] === block) {
55 loneBlocks.pop();
56 }
57 }
58
59 // Default rule definition: report all lone blocks
60 ruleDef = {
61 BlockStatement: function(node) {
62 if (isLoneBlock(node)) {
63 report(node);
64 }
65 }
66 };
67
68 // ES6: report blocks without block-level bindings
69 if (context.parserOptions.ecmaVersion >= 6) {
70 ruleDef = {
71 "BlockStatement": function(node) {
72 if (isLoneBlock(node)) {
73 loneBlocks.push(node);
74 }
75 },
76 "BlockStatement:exit": function(node) {
77 if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) {
78 loneBlocks.pop();
79 report(node);
80 }
81 }
82 };
83
84 ruleDef.VariableDeclaration = function(node) {
85 if (node.kind === "let" || node.kind === "const") {
86 markLoneBlock(node);
87 }
88 };
89
90 ruleDef.FunctionDeclaration = function(node) {
91 if (context.getScope().isStrict) {
92 markLoneBlock(node);
93 }
94 };
95
96 ruleDef.ClassDeclaration = markLoneBlock;
97 }
98
99 return ruleDef;
100};
101
102module.exports.schema = [];