.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-underscore-dangle.js
1 /**
2  * @fileoverview Rule to flag dangling underscores in variable declarations.
3  * @author Matt DuVall <http://www.mattduvall.com>
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 dangling underscores in identifiers",
18             category: "Stylistic Issues",
19             recommended: false,
20             url: "https://eslint.org/docs/rules/no-underscore-dangle"
21         },
22
23         schema: [
24             {
25                 type: "object",
26                 properties: {
27                     allow: {
28                         type: "array",
29                         items: {
30                             type: "string"
31                         }
32                     },
33                     allowAfterThis: {
34                         type: "boolean",
35                         default: false
36                     },
37                     allowAfterSuper: {
38                         type: "boolean",
39                         default: false
40                     },
41                     allowAfterThisConstructor: {
42                         type: "boolean",
43                         default: false
44                     },
45                     enforceInMethodNames: {
46                         type: "boolean",
47                         default: false
48                     },
49                     allowFunctionParams: {
50                         type: "boolean",
51                         default: true
52                     }
53                 },
54                 additionalProperties: false
55             }
56         ],
57
58         messages: {
59             unexpectedUnderscore: "Unexpected dangling '_' in '{{identifier}}'."
60         }
61     },
62
63     create(context) {
64
65         const options = context.options[0] || {};
66         const ALLOWED_VARIABLES = options.allow ? options.allow : [];
67         const allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false;
68         const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
69         const allowAfterThisConstructor = typeof options.allowAfterThisConstructor !== "undefined" ? options.allowAfterThisConstructor : false;
70         const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;
71         const allowFunctionParams = typeof options.allowFunctionParams !== "undefined" ? options.allowFunctionParams : true;
72
73         //-------------------------------------------------------------------------
74         // Helpers
75         //-------------------------------------------------------------------------
76
77         /**
78          * Check if identifier is present inside the allowed option
79          * @param {string} identifier name of the node
80          * @returns {boolean} true if its is present
81          * @private
82          */
83         function isAllowed(identifier) {
84             return ALLOWED_VARIABLES.some(ident => ident === identifier);
85         }
86
87         /**
88          * Check if identifier has a dangling underscore
89          * @param {string} identifier name of the node
90          * @returns {boolean} true if its is present
91          * @private
92          */
93         function hasDanglingUnderscore(identifier) {
94             const len = identifier.length;
95
96             return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_");
97         }
98
99         /**
100          * Check if identifier is a special case member expression
101          * @param {string} identifier name of the node
102          * @returns {boolean} true if its is a special case
103          * @private
104          */
105         function isSpecialCaseIdentifierForMemberExpression(identifier) {
106             return identifier === "__proto__";
107         }
108
109         /**
110          * Check if identifier is a special case variable expression
111          * @param {string} identifier name of the node
112          * @returns {boolean} true if its is a special case
113          * @private
114          */
115         function isSpecialCaseIdentifierInVariableExpression(identifier) {
116
117             // Checks for the underscore library usage here
118             return identifier === "_";
119         }
120
121         /**
122          * Check if a node is a member reference of this.constructor
123          * @param {ASTNode} node node to evaluate
124          * @returns {boolean} true if it is a reference on this.constructor
125          * @private
126          */
127         function isThisConstructorReference(node) {
128             return node.object.type === "MemberExpression" &&
129                 node.object.property.name === "constructor" &&
130                 node.object.object.type === "ThisExpression";
131         }
132
133         /**
134          * Check if function parameter has a dangling underscore.
135          * @param {ASTNode} node function node to evaluate
136          * @returns {void}
137          * @private
138          */
139         function checkForDanglingUnderscoreInFunctionParameters(node) {
140             if (!allowFunctionParams) {
141                 node.params.forEach(param => {
142                     const { type } = param;
143                     let nodeToCheck;
144
145                     if (type === "RestElement") {
146                         nodeToCheck = param.argument;
147                     } else if (type === "AssignmentPattern") {
148                         nodeToCheck = param.left;
149                     } else {
150                         nodeToCheck = param;
151                     }
152
153                     if (nodeToCheck.type === "Identifier") {
154                         const identifier = nodeToCheck.name;
155
156                         if (hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
157                             context.report({
158                                 node: param,
159                                 messageId: "unexpectedUnderscore",
160                                 data: {
161                                     identifier
162                                 }
163                             });
164                         }
165                     }
166                 });
167             }
168         }
169
170         /**
171          * Check if function has a dangling underscore
172          * @param {ASTNode} node node to evaluate
173          * @returns {void}
174          * @private
175          */
176         function checkForDanglingUnderscoreInFunction(node) {
177             if (node.type === "FunctionDeclaration" && node.id) {
178                 const identifier = node.id.name;
179
180                 if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
181                     context.report({
182                         node,
183                         messageId: "unexpectedUnderscore",
184                         data: {
185                             identifier
186                         }
187                     });
188                 }
189             }
190             checkForDanglingUnderscoreInFunctionParameters(node);
191         }
192
193         /**
194          * Check if variable expression has a dangling underscore
195          * @param {ASTNode} node node to evaluate
196          * @returns {void}
197          * @private
198          */
199         function checkForDanglingUnderscoreInVariableExpression(node) {
200             const identifier = node.id.name;
201
202             if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) &&
203                 !isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) {
204                 context.report({
205                     node,
206                     messageId: "unexpectedUnderscore",
207                     data: {
208                         identifier
209                     }
210                 });
211             }
212         }
213
214         /**
215          * Check if member expression has a dangling underscore
216          * @param {ASTNode} node node to evaluate
217          * @returns {void}
218          * @private
219          */
220         function checkForDanglingUnderscoreInMemberExpression(node) {
221             const identifier = node.property.name,
222                 isMemberOfThis = node.object.type === "ThisExpression",
223                 isMemberOfSuper = node.object.type === "Super",
224                 isMemberOfThisConstructor = isThisConstructorReference(node);
225
226             if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) &&
227                 !(isMemberOfThis && allowAfterThis) &&
228                 !(isMemberOfSuper && allowAfterSuper) &&
229                 !(isMemberOfThisConstructor && allowAfterThisConstructor) &&
230                 !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) {
231                 context.report({
232                     node,
233                     messageId: "unexpectedUnderscore",
234                     data: {
235                         identifier
236                     }
237                 });
238             }
239         }
240
241         /**
242          * Check if method declaration or method property has a dangling underscore
243          * @param {ASTNode} node node to evaluate
244          * @returns {void}
245          * @private
246          */
247         function checkForDanglingUnderscoreInMethod(node) {
248             const identifier = node.key.name;
249             const isMethod = node.type === "MethodDefinition" || node.type === "Property" && node.method;
250
251             if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasDanglingUnderscore(identifier) && !isAllowed(identifier)) {
252                 context.report({
253                     node,
254                     messageId: "unexpectedUnderscore",
255                     data: {
256                         identifier
257                     }
258                 });
259             }
260         }
261
262         //--------------------------------------------------------------------------
263         // Public API
264         //--------------------------------------------------------------------------
265
266         return {
267             FunctionDeclaration: checkForDanglingUnderscoreInFunction,
268             VariableDeclarator: checkForDanglingUnderscoreInVariableExpression,
269             MemberExpression: checkForDanglingUnderscoreInMemberExpression,
270             MethodDefinition: checkForDanglingUnderscoreInMethod,
271             Property: checkForDanglingUnderscoreInMethod,
272             FunctionExpression: checkForDanglingUnderscoreInFunction,
273             ArrowFunctionExpression: checkForDanglingUnderscoreInFunction
274         };
275
276     }
277 };