Skip to content

Commit

Permalink
feat: add enforceInClassFields option to no-underscore-dangle (#15818)
Browse files Browse the repository at this point in the history
* fix: no-underscore-dangle support for class fields (es2022)

* resolving code review suggestions

* resolving code review suggestions
  • Loading branch information
robertotcestari committed May 4, 2022
1 parent 2dc8d15 commit ab37d3b
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
29 changes: 29 additions & 0 deletions docs/src/rules/no-underscore-dangle.md
Expand Up @@ -54,6 +54,7 @@ This rule has an object option:
* `"allowAfterSuper": false` (default) disallows dangling underscores in members of the `super` object
* `"allowAfterThisConstructor": false` (default) disallows dangling underscores in members of the `this.constructor` object
* `"enforceInMethodNames": false` (default) allows dangling underscores in method names
* `"enforceInClassFields": false` (default) allows dangling underscores in es2022 class fields names
* `"allowFunctionParams": true` (default) allows dangling underscores in function parameter names

### allow
Expand Down Expand Up @@ -124,6 +125,34 @@ const o = {
};
```

### enforceInClassFields

Examples of **incorrect** code for this rule with the `{ "enforceInClassFields": true }` option:

```js
/*eslint no-underscore-dangle: ["error", { "enforceInClassFields": true }]*/

class Foo {
_bar;
}

class Foo {
_bar = () => {};
}

class Foo {
bar_;
}

class Foo {
#_bar;
}

class Foo {
#bar_;
}
```

### allowFunctionParams

Examples of **incorrect** code for this rule with the `{ "allowFunctionParams": false }` option:
Expand Down
31 changes: 30 additions & 1 deletion lib/rules/no-underscore-dangle.js
Expand Up @@ -49,6 +49,10 @@ module.exports = {
allowFunctionParams: {
type: "boolean",
default: true
},
enforceInClassFields: {
type: "boolean",
default: false
}
},
additionalProperties: false
Expand All @@ -68,6 +72,7 @@ module.exports = {
const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
const allowAfterThisConstructor = typeof options.allowAfterThisConstructor !== "undefined" ? options.allowAfterThisConstructor : false;
const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;
const enforceInClassFields = typeof options.enforceInClassFields !== "undefined" ? options.enforceInClassFields : false;
const allowFunctionParams = typeof options.allowFunctionParams !== "undefined" ? options.allowFunctionParams : true;

//-------------------------------------------------------------------------
Expand Down Expand Up @@ -261,6 +266,30 @@ module.exports = {
}
}

/**
* Check if a class field has a dangling underscore
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForDanglingUnderscoreInClassField(node) {
const identifier = node.key.name;

if (typeof identifier !== "undefined" && hasDanglingUnderscore(identifier) &&
enforceInClassFields &&
!isAllowed(identifier)) {
context.report({
node,
messageId: "unexpectedUnderscore",
data: {
identifier: node.key.type === "PrivateIdentifier"
? `#${identifier}`
: identifier
}
});
}
}

//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------
Expand All @@ -270,7 +299,7 @@ module.exports = {
VariableDeclarator: checkForDanglingUnderscoreInVariableExpression,
MemberExpression: checkForDanglingUnderscoreInMemberExpression,
MethodDefinition: checkForDanglingUnderscoreInMethod,
PropertyDefinition: checkForDanglingUnderscoreInMethod,
PropertyDefinition: checkForDanglingUnderscoreInClassField,
Property: checkForDanglingUnderscoreInMethod,
FunctionExpression: checkForDanglingUnderscoreInFunction,
ArrowFunctionExpression: checkForDanglingUnderscoreInFunction
Expand Down
29 changes: 28 additions & 1 deletion tests/lib/rules/no-underscore-dangle.js
Expand Up @@ -71,7 +71,10 @@ ruleTester.run("no-underscore-dangle", rule, {
{ code: "function foo( { _bar = 0 } = {}) {}", options: [{ allowFunctionParams: false }], parserOptions: { ecmaVersion: 6 } },
{ code: "function foo(...[_bar]) {}", options: [{ allowFunctionParams: false }], parserOptions: { ecmaVersion: 2016 } },
{ code: "class foo { _field; }", parserOptions: { ecmaVersion: 2022 } },
{ code: "class foo { #_field; }", parserOptions: { ecmaVersion: 2022 } }
{ code: "class foo { _field; }", options: [{ enforceInClassFields: false }], parserOptions: { ecmaVersion: 2022 } },
{ code: "class foo { #_field; }", parserOptions: { ecmaVersion: 2022 } },
{ code: "class foo { #_field; }", options: [{ enforceInClassFields: false }], parserOptions: { ecmaVersion: 2022 } },
{ code: "class foo { _field; }", options: [{}], parserOptions: { ecmaVersion: 2022 } }
],
invalid: [
{ code: "var _foo = 1", errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "_foo" }, type: "VariableDeclarator" }] },
Expand Down Expand Up @@ -109,6 +112,30 @@ ruleTester.run("no-underscore-dangle", rule, {
options: [{ enforceInMethodNames: true }],
parserOptions: { ecmaVersion: 2022 },
errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "#bar_" } }]
},
{
code: "class foo { _field; }",
options: [{ enforceInClassFields: true }],
parserOptions: { ecmaVersion: 2022 },
errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "_field" } }]
},
{
code: "class foo { #_field; }",
options: [{ enforceInClassFields: true }],
parserOptions: { ecmaVersion: 2022 },
errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "#_field" } }]
},
{
code: "class foo { field_; }",
options: [{ enforceInClassFields: true }],
parserOptions: { ecmaVersion: 2022 },
errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "field_" } }]
},
{
code: "class foo { #field_; }",
options: [{ enforceInClassFields: true }],
parserOptions: { ecmaVersion: 2022 },
errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "#field_" } }]
}
]
});

0 comments on commit ab37d3b

Please sign in to comment.