2 * @fileoverview Rule to flag dangling underscores in variable declarations.
3 * @author Matt DuVall <http://www.mattduvall.com>
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
17 description
: "disallow dangling underscores in identifiers",
18 category
: "Stylistic Issues",
20 url
: "https://eslint.org/docs/rules/no-underscore-dangle"
41 allowAfterThisConstructor
: {
45 enforceInMethodNames
: {
49 allowFunctionParams
: {
54 additionalProperties
: false
59 unexpectedUnderscore
: "Unexpected dangling '_' in '{{identifier}}'."
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;
73 //-------------------------------------------------------------------------
75 //-------------------------------------------------------------------------
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
83 function isAllowed(identifier
) {
84 return ALLOWED_VARIABLES
.some(ident
=> ident
=== identifier
);
88 * Check if identifier has a dangling underscore
89 * @param {string} identifier name of the node
90 * @returns {boolean} true if its is present
93 function hasDanglingUnderscore(identifier
) {
94 const len
= identifier
.length
;
96 return identifier
!== "_" && (identifier
[0] === "_" || identifier
[len
- 1] === "_");
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
105 function isSpecialCaseIdentifierForMemberExpression(identifier
) {
106 return identifier
=== "__proto__";
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
115 function isSpecialCaseIdentifierInVariableExpression(identifier
) {
117 // Checks for the underscore library usage here
118 return identifier
=== "_";
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
127 function isThisConstructorReference(node
) {
128 return node
.object
.type
=== "MemberExpression" &&
129 node
.object
.property
.name
=== "constructor" &&
130 node
.object
.object
.type
=== "ThisExpression";
134 * Check if function parameter has a dangling underscore.
135 * @param {ASTNode} node function node to evaluate
139 function checkForDanglingUnderscoreInFunctionParameters(node
) {
140 if (!allowFunctionParams
) {
141 node
.params
.forEach(param
=> {
142 const { type
} = param
;
145 if (type
=== "RestElement") {
146 nodeToCheck
= param
.argument
;
147 } else if (type
=== "AssignmentPattern") {
148 nodeToCheck
= param
.left
;
153 if (nodeToCheck
.type
=== "Identifier") {
154 const identifier
= nodeToCheck
.name
;
156 if (hasDanglingUnderscore(identifier
) && !isAllowed(identifier
)) {
159 messageId
: "unexpectedUnderscore",
171 * Check if function has a dangling underscore
172 * @param {ASTNode} node node to evaluate
176 function checkForDanglingUnderscoreInFunction(node
) {
177 if (node
.type
=== "FunctionDeclaration" && node
.id
) {
178 const identifier
= node
.id
.name
;
180 if (typeof identifier
!== "undefined" && hasDanglingUnderscore(identifier
) && !isAllowed(identifier
)) {
183 messageId
: "unexpectedUnderscore",
190 checkForDanglingUnderscoreInFunctionParameters(node
);
194 * Check if variable expression has a dangling underscore
195 * @param {ASTNode} node node to evaluate
199 function checkForDanglingUnderscoreInVariableExpression(node
) {
200 const identifier
= node
.id
.name
;
202 if (typeof identifier
!== "undefined" && hasDanglingUnderscore(identifier
) &&
203 !isSpecialCaseIdentifierInVariableExpression(identifier
) && !isAllowed(identifier
)) {
206 messageId
: "unexpectedUnderscore",
215 * Check if member expression has a dangling underscore
216 * @param {ASTNode} node node to evaluate
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
);
226 if (typeof identifier
!== "undefined" && hasDanglingUnderscore(identifier
) &&
227 !(isMemberOfThis
&& allowAfterThis
) &&
228 !(isMemberOfSuper
&& allowAfterSuper
) &&
229 !(isMemberOfThisConstructor
&& allowAfterThisConstructor
) &&
230 !isSpecialCaseIdentifierForMemberExpression(identifier
) && !isAllowed(identifier
)) {
233 messageId
: "unexpectedUnderscore",
242 * Check if method declaration or method property has a dangling underscore
243 * @param {ASTNode} node node to evaluate
247 function checkForDanglingUnderscoreInMethod(node
) {
248 const identifier
= node
.key
.name
;
249 const isMethod
= node
.type
=== "MethodDefinition" || node
.type
=== "Property" && node
.method
;
251 if (typeof identifier
!== "undefined" && enforceInMethodNames
&& isMethod
&& hasDanglingUnderscore(identifier
) && !isAllowed(identifier
)) {
254 messageId
: "unexpectedUnderscore",
262 //--------------------------------------------------------------------------
264 //--------------------------------------------------------------------------
267 FunctionDeclaration
: checkForDanglingUnderscoreInFunction
,
268 VariableDeclarator
: checkForDanglingUnderscoreInVariableExpression
,
269 MemberExpression
: checkForDanglingUnderscoreInMemberExpression
,
270 MethodDefinition
: checkForDanglingUnderscoreInMethod
,
271 Property
: checkForDanglingUnderscoreInMethod
,
272 FunctionExpression
: checkForDanglingUnderscoreInFunction
,
273 ArrowFunctionExpression
: checkForDanglingUnderscoreInFunction