.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-lone-blocks.js
1 /**
2  * @fileoverview Rule to flag blocks with no reason to exist
3  * @author Brandon Mills
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Rule Definition
10 //------------------------------------------------------------------------------
11
12 module.exports = {
13     meta: {
14         type: "suggestion",
15
16         docs: {
17             description: "disallow unnecessary nested blocks",
18             category: "Best Practices",
19             recommended: false,
20             url: "https://eslint.org/docs/rules/no-lone-blocks"
21         },
22
23         schema: [],
24
25         messages: {
26             redundantBlock: "Block is redundant.",
27             redundantNestedBlock: "Nested block is redundant."
28         }
29     },
30
31     create(context) {
32
33         // A stack of lone blocks to be checked for block-level bindings
34         const loneBlocks = [];
35         let ruleDef;
36
37         /**
38          * Reports a node as invalid.
39          * @param {ASTNode} node The node to be reported.
40          * @returns {void}
41          */
42         function report(node) {
43             const messageId = node.parent.type === "BlockStatement" ? "redundantNestedBlock" : "redundantBlock";
44
45             context.report({
46                 node,
47                 messageId
48             });
49         }
50
51         /**
52          * Checks for any occurrence of a BlockStatement in a place where lists of statements can appear
53          * @param {ASTNode} node The node to check
54          * @returns {boolean} True if the node is a lone block.
55          */
56         function isLoneBlock(node) {
57             return node.parent.type === "BlockStatement" ||
58                 node.parent.type === "Program" ||
59
60                 // Don't report blocks in switch cases if the block is the only statement of the case.
61                 node.parent.type === "SwitchCase" && !(node.parent.consequent[0] === node && node.parent.consequent.length === 1);
62         }
63
64         /**
65          * Checks the enclosing block of the current node for block-level bindings,
66          * and "marks it" as valid if any.
67          * @returns {void}
68          */
69         function markLoneBlock() {
70             if (loneBlocks.length === 0) {
71                 return;
72             }
73
74             const block = context.getAncestors().pop();
75
76             if (loneBlocks[loneBlocks.length - 1] === block) {
77                 loneBlocks.pop();
78             }
79         }
80
81         // Default rule definition: report all lone blocks
82         ruleDef = {
83             BlockStatement(node) {
84                 if (isLoneBlock(node)) {
85                     report(node);
86                 }
87             }
88         };
89
90         // ES6: report blocks without block-level bindings, or that's only child of another block
91         if (context.parserOptions.ecmaVersion >= 6) {
92             ruleDef = {
93                 BlockStatement(node) {
94                     if (isLoneBlock(node)) {
95                         loneBlocks.push(node);
96                     }
97                 },
98                 "BlockStatement:exit"(node) {
99                     if (loneBlocks.length > 0 && loneBlocks[loneBlocks.length - 1] === node) {
100                         loneBlocks.pop();
101                         report(node);
102                     } else if (
103                         node.parent.type === "BlockStatement" &&
104                         node.parent.body.length === 1
105                     ) {
106                         report(node);
107                     }
108                 }
109             };
110
111             ruleDef.VariableDeclaration = function(node) {
112                 if (node.kind === "let" || node.kind === "const") {
113                     markLoneBlock();
114                 }
115             };
116
117             ruleDef.FunctionDeclaration = function() {
118                 if (context.getScope().isStrict) {
119                     markLoneBlock();
120                 }
121             };
122
123             ruleDef.ClassDeclaration = markLoneBlock;
124         }
125
126         return ruleDef;
127     }
128 };