minor adjustment to readme
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-underscore-dangle.js
1 /**
2  * @fileoverview Rule to flag trailing 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                 },
50                 additionalProperties: false
51             }
52         ]
53     },
54
55     create(context) {
56
57         const options = context.options[0] || {};
58         const ALLOWED_VARIABLES = options.allow ? options.allow : [];
59         const allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false;
60         const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
61         const allowAfterThisConstructor = typeof options.allowAfterThisConstructor !== "undefined" ? options.allowAfterThisConstructor : false;
62         const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;
63
64         //-------------------------------------------------------------------------
65         // Helpers
66         //-------------------------------------------------------------------------
67
68         /**
69          * Check if identifier is present inside the allowed option
70          * @param {string} identifier name of the node
71          * @returns {boolean} true if its is present
72          * @private
73          */
74         function isAllowed(identifier) {
75             return ALLOWED_VARIABLES.some(ident => ident === identifier);
76         }
77
78         /**
79          * Check if identifier has a underscore at the end
80          * @param {string} identifier name of the node
81          * @returns {boolean} true if its is present
82          * @private
83          */
84         function hasTrailingUnderscore(identifier) {
85             const len = identifier.length;
86
87             return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_");
88         }
89
90         /**
91          * Check if identifier is a special case member expression
92          * @param {string} identifier name of the node
93          * @returns {boolean} true if its is a special case
94          * @private
95          */
96         function isSpecialCaseIdentifierForMemberExpression(identifier) {
97             return identifier === "__proto__";
98         }
99
100         /**
101          * Check if identifier is a special case variable expression
102          * @param {string} identifier name of the node
103          * @returns {boolean} true if its is a special case
104          * @private
105          */
106         function isSpecialCaseIdentifierInVariableExpression(identifier) {
107
108             // Checks for the underscore library usage here
109             return identifier === "_";
110         }
111
112         /**
113          * Check if a node is a member reference of this.constructor
114          * @param {ASTNode} node node to evaluate
115          * @returns {boolean} true if it is a reference on this.constructor
116          * @private
117          */
118         function isThisConstructorReference(node) {
119             return node.object.type === "MemberExpression" &&
120                 node.object.property.name === "constructor" &&
121                 node.object.object.type === "ThisExpression";
122         }
123
124         /**
125          * Check if function has a underscore at the end
126          * @param {ASTNode} node node to evaluate
127          * @returns {void}
128          * @private
129          */
130         function checkForTrailingUnderscoreInFunctionDeclaration(node) {
131             if (node.id) {
132                 const identifier = node.id.name;
133
134                 if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) {
135                     context.report({
136                         node,
137                         message: "Unexpected dangling '_' in '{{identifier}}'.",
138                         data: {
139                             identifier
140                         }
141                     });
142                 }
143             }
144         }
145
146         /**
147          * Check if variable expression has a underscore at the end
148          * @param {ASTNode} node node to evaluate
149          * @returns {void}
150          * @private
151          */
152         function checkForTrailingUnderscoreInVariableExpression(node) {
153             const identifier = node.id.name;
154
155             if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) &&
156                 !isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) {
157                 context.report({
158                     node,
159                     message: "Unexpected dangling '_' in '{{identifier}}'.",
160                     data: {
161                         identifier
162                     }
163                 });
164             }
165         }
166
167         /**
168          * Check if member expression has a underscore at the end
169          * @param {ASTNode} node node to evaluate
170          * @returns {void}
171          * @private
172          */
173         function checkForTrailingUnderscoreInMemberExpression(node) {
174             const identifier = node.property.name,
175                 isMemberOfThis = node.object.type === "ThisExpression",
176                 isMemberOfSuper = node.object.type === "Super",
177                 isMemberOfThisConstructor = isThisConstructorReference(node);
178
179             if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) &&
180                 !(isMemberOfThis && allowAfterThis) &&
181                 !(isMemberOfSuper && allowAfterSuper) &&
182                 !(isMemberOfThisConstructor && allowAfterThisConstructor) &&
183                 !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) {
184                 context.report({
185                     node,
186                     message: "Unexpected dangling '_' in '{{identifier}}'.",
187                     data: {
188                         identifier
189                     }
190                 });
191             }
192         }
193
194         /**
195          * Check if method declaration or method property has a underscore at the end
196          * @param {ASTNode} node node to evaluate
197          * @returns {void}
198          * @private
199          */
200         function checkForTrailingUnderscoreInMethod(node) {
201             const identifier = node.key.name;
202             const isMethod = node.type === "MethodDefinition" || node.type === "Property" && node.method;
203
204             if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasTrailingUnderscore(identifier)) {
205                 context.report({
206                     node,
207                     message: "Unexpected dangling '_' in '{{identifier}}'.",
208                     data: {
209                         identifier
210                     }
211                 });
212             }
213         }
214
215         //--------------------------------------------------------------------------
216         // Public API
217         //--------------------------------------------------------------------------
218
219         return {
220             FunctionDeclaration: checkForTrailingUnderscoreInFunctionDeclaration,
221             VariableDeclarator: checkForTrailingUnderscoreInVariableExpression,
222             MemberExpression: checkForTrailingUnderscoreInMemberExpression,
223             MethodDefinition: checkForTrailingUnderscoreInMethod,
224             Property: checkForTrailingUnderscoreInMethod
225         };
226
227     }
228 };