.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-labels.js
1 /**
2  * @fileoverview Disallow Labeled Statements
3  * @author Nicholas C. Zakas
4  */
5 "use strict";
6
7 //------------------------------------------------------------------------------
8 // Requirements
9 //------------------------------------------------------------------------------
10
11 const astUtils = require("./utils/ast-utils");
12
13 //------------------------------------------------------------------------------
14 // Rule Definition
15 //------------------------------------------------------------------------------
16
17 module.exports = {
18     meta: {
19         type: "suggestion",
20
21         docs: {
22             description: "disallow labeled statements",
23             category: "Best Practices",
24             recommended: false,
25             url: "https://eslint.org/docs/rules/no-labels"
26         },
27
28         schema: [
29             {
30                 type: "object",
31                 properties: {
32                     allowLoop: {
33                         type: "boolean",
34                         default: false
35                     },
36                     allowSwitch: {
37                         type: "boolean",
38                         default: false
39                     }
40                 },
41                 additionalProperties: false
42             }
43         ],
44
45         messages: {
46             unexpectedLabel: "Unexpected labeled statement.",
47             unexpectedLabelInBreak: "Unexpected label in break statement.",
48             unexpectedLabelInContinue: "Unexpected label in continue statement."
49         }
50     },
51
52     create(context) {
53         const options = context.options[0];
54         const allowLoop = options && options.allowLoop;
55         const allowSwitch = options && options.allowSwitch;
56         let scopeInfo = null;
57
58         /**
59          * Gets the kind of a given node.
60          * @param {ASTNode} node A node to get.
61          * @returns {string} The kind of the node.
62          */
63         function getBodyKind(node) {
64             if (astUtils.isLoop(node)) {
65                 return "loop";
66             }
67             if (node.type === "SwitchStatement") {
68                 return "switch";
69             }
70             return "other";
71         }
72
73         /**
74          * Checks whether the label of a given kind is allowed or not.
75          * @param {string} kind A kind to check.
76          * @returns {boolean} `true` if the kind is allowed.
77          */
78         function isAllowed(kind) {
79             switch (kind) {
80                 case "loop": return allowLoop;
81                 case "switch": return allowSwitch;
82                 default: return false;
83             }
84         }
85
86         /**
87          * Checks whether a given name is a label of a loop or not.
88          * @param {string} label A name of a label to check.
89          * @returns {boolean} `true` if the name is a label of a loop.
90          */
91         function getKind(label) {
92             let info = scopeInfo;
93
94             while (info) {
95                 if (info.label === label) {
96                     return info.kind;
97                 }
98                 info = info.upper;
99             }
100
101             /* istanbul ignore next: syntax error */
102             return "other";
103         }
104
105         //--------------------------------------------------------------------------
106         // Public
107         //--------------------------------------------------------------------------
108
109         return {
110             LabeledStatement(node) {
111                 scopeInfo = {
112                     label: node.label.name,
113                     kind: getBodyKind(node.body),
114                     upper: scopeInfo
115                 };
116             },
117
118             "LabeledStatement:exit"(node) {
119                 if (!isAllowed(scopeInfo.kind)) {
120                     context.report({
121                         node,
122                         messageId: "unexpectedLabel"
123                     });
124                 }
125
126                 scopeInfo = scopeInfo.upper;
127             },
128
129             BreakStatement(node) {
130                 if (node.label && !isAllowed(getKind(node.label.name))) {
131                     context.report({
132                         node,
133                         messageId: "unexpectedLabelInBreak"
134                     });
135                 }
136             },
137
138             ContinueStatement(node) {
139                 if (node.label && !isAllowed(getKind(node.label.name))) {
140                     context.report({
141                         node,
142                         messageId: "unexpectedLabelInContinue"
143                     });
144                 }
145             }
146         };
147
148     }
149 };