.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-unsafe-finally.js
1 /**
2  * @fileoverview Rule to flag unsafe statements in finally block
3  * @author Onur Temizkan
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Helpers
10 //------------------------------------------------------------------------------
11
12 const SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/u;
13 const SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/u;
14 const SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/u;
15
16
17 //------------------------------------------------------------------------------
18 // Rule Definition
19 //------------------------------------------------------------------------------
20
21 module.exports = {
22     meta: {
23         type: "problem",
24
25         docs: {
26             description: "disallow control flow statements in `finally` blocks",
27             category: "Possible Errors",
28             recommended: true,
29             url: "https://eslint.org/docs/rules/no-unsafe-finally"
30         },
31
32         schema: [],
33
34         messages: {
35             unsafeUsage: "Unsafe usage of {{nodeType}}."
36         }
37     },
38     create(context) {
39
40         /**
41          * Checks if the node is the finalizer of a TryStatement
42          * @param {ASTNode} node node to check.
43          * @returns {boolean} - true if the node is the finalizer of a TryStatement
44          */
45         function isFinallyBlock(node) {
46             return node.parent.type === "TryStatement" && node.parent.finalizer === node;
47         }
48
49         /**
50          * Climbs up the tree if the node is not a sentinel node
51          * @param {ASTNode} node node to check.
52          * @param {string} label label of the break or continue statement
53          * @returns {boolean} - return whether the node is a finally block or a sentinel node
54          */
55         function isInFinallyBlock(node, label) {
56             let labelInside = false;
57             let sentinelNodeType;
58
59             if (node.type === "BreakStatement" && !node.label) {
60                 sentinelNodeType = SENTINEL_NODE_TYPE_BREAK;
61             } else if (node.type === "ContinueStatement") {
62                 sentinelNodeType = SENTINEL_NODE_TYPE_CONTINUE;
63             } else {
64                 sentinelNodeType = SENTINEL_NODE_TYPE_RETURN_THROW;
65             }
66
67             for (
68                 let currentNode = node;
69                 currentNode && !sentinelNodeType.test(currentNode.type);
70                 currentNode = currentNode.parent
71             ) {
72                 if (currentNode.parent.label && label && (currentNode.parent.label.name === label.name)) {
73                     labelInside = true;
74                 }
75                 if (isFinallyBlock(currentNode)) {
76                     if (label && labelInside) {
77                         return false;
78                     }
79                     return true;
80                 }
81             }
82             return false;
83         }
84
85         /**
86          * Checks whether the possibly-unsafe statement is inside a finally block.
87          * @param {ASTNode} node node to check.
88          * @returns {void}
89          */
90         function check(node) {
91             if (isInFinallyBlock(node, node.label)) {
92                 context.report({
93                     messageId: "unsafeUsage",
94                     data: {
95                         nodeType: node.type
96                     },
97                     node,
98                     line: node.loc.line,
99                     column: node.loc.column
100                 });
101             }
102         }
103
104         return {
105             ReturnStatement: check,
106             ThrowStatement: check,
107             BreakStatement: check,
108             ContinueStatement: check
109         };
110     }
111 };