Skip to content

Commit

Permalink
Update: add enforceInMethodNames to no-underscore-dangle (fixes eslin…
Browse files Browse the repository at this point in the history
…t#7065)

When enforceInMethodNames is true, the rule checks for dangling
underscores in method names too. This includes methods of classes
and method properties of objects.

The rule is false by default.
  • Loading branch information
gabro committed Feb 7, 2017
1 parent c596690 commit 565016b
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 3 deletions.
25 changes: 25 additions & 0 deletions docs/rules/no-underscore-dangle.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ This rule has an object option:
* `"allow"` allows specified identifiers to have dangling underscores
* `"allowAfterThis": false` (default) disallows dangling underscores in members of the `this` object
* `"allowAfterSuper": false` (default) disallows dangling underscores in members of the `super` object
* `"enforceInMethodNames": false (default) allows dangling underscores in method names`

### allow

Expand Down Expand Up @@ -76,6 +77,30 @@ var a = super.foo_;
super._bar();
```

### enforceInMethodNames

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

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

class Foo {
_bar() {}
}

class Foo {
bar_() {}
}

const o = {
_bar() {}
};

const o = {
bar_() = {}
};
```

## When Not To Use It

If you want to allow dangling underscores in identifiers, then you can safely turn this rule off.
49 changes: 48 additions & 1 deletion lib/rules/no-underscore-dangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ module.exports = {
},
allowAfterSuper: {
type: "boolean"
},
enforceInMethodNames: {
type: "boolean"
}
},
additionalProperties: false
Expand All @@ -45,6 +48,7 @@ module.exports = {
const ALLOWED_VARIABLES = options.allow ? options.allow : [];
const allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false;
const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;

//-------------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -162,14 +166,57 @@ module.exports = {
}
}

/**
* Check if method declaration has a underscore at the end
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForTrailingUnderscoreInMethodDefinition(node) {
const identifier = node.key.name;

if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && enforceInMethodNames) {
context.report({
node,
message: "Unexpected dangling '_' in '{{identifier}}'",
data: {
identifier
}
});
}
}

/**
* Check if method property has a underscore at the end
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForTrailingUnderscoreInMethodProperty(node) {
const identifier = node.key.name;
const isMethod = node.method;

if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && enforceInMethodNames && isMethod) {
context.report({
node,
message: "Unexpected dangling '_' in '{{identifier}}'",
data: {
identifier
}
});
}
}

//--------------------------------------------------------------------------
// Public API
//--------------------------------------------------------------------------

return {
FunctionDeclaration: checkForTrailingUnderscoreInFunctionDeclaration,
VariableDeclarator: checkForTrailingUnderscoreInVariableExpression,
MemberExpression: checkForTrailingUnderscoreInMemberExpression
MemberExpression: checkForTrailingUnderscoreInMemberExpression,
MethodDefinition: checkForTrailingUnderscoreInMethodDefinition,
Property: checkForTrailingUnderscoreInMethodProperty
};

}
Expand Down
12 changes: 10 additions & 2 deletions tests/lib/rules/no-underscore-dangle.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ ruleTester.run("no-underscore-dangle", rule, {
{ code: "foo._bar;", options: [{ allow: ["_bar"] }] },
{ code: "function _foo() {}", options: [{ allow: ["_foo"] }] },
{ code: "this._bar;", options: [{ allowAfterThis: true }] },
{ code: "class foo { constructor() { super._bar; } }", parserOptions: { ecmaVersion: 6 }, options: [{ allowAfterSuper: true }] }
{ code: "class foo { constructor() { super._bar; } }", parserOptions: { ecmaVersion: 6 }, options: [{ allowAfterSuper: true }] },
{ code: "class foo { _onClick() { } }", parserOptions: { ecmaVersion: 6 }},
{ code: "class foo { onClick_() { } }", parserOptions: { ecmaVersion: 6 }},
{ code: "const o = { _onClick() { } }", parserOptions: { ecmaVersion: 6 }},
{ code: "const o = { onClick_() { } }", parserOptions: { ecmaVersion: 6 }}
],
invalid: [
{ code: "var _foo = 1", errors: [{ message: "Unexpected dangling '_' in '_foo'.", type: "VariableDeclarator" }] },
Expand All @@ -43,6 +47,10 @@ ruleTester.run("no-underscore-dangle", rule, {
{ code: "foo._bar;", errors: [{ message: "Unexpected dangling '_' in '_bar'.", type: "MemberExpression" }] },
{ code: "this._prop;", errors: [{ message: "Unexpected dangling '_' in '_prop'.", type: "MemberExpression" }] },
{ code: "class foo { constructor() { super._prop; } }", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in '_prop'.", type: "MemberExpression" }] },
{ code: "class foo { constructor() { this._prop; } }", options: [{ allowAfterSuper: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in '_prop'.", type: "MemberExpression" }] }
{ code: "class foo { constructor() { this._prop; } }", options: [{ allowAfterSuper: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in '_prop'.", type: "MemberExpression" }] },
{ code: "class foo { _onClick() { } }", options: [{enforceInMethodNames: true}], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in '_onClick'", type: "MethodDefinition" }] },
{ code: "class foo { onClick_() { } }", options: [{enforceInMethodNames: true}], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in 'onClick_'", type: "MethodDefinition" }] },
{ code: "const o = { _onClick() { } }", options: [{enforceInMethodNames: true}], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in '_onClick'", type: "Property" }] },
{ code: "const o = { onClick_() { } }", options: [{enforceInMethodNames: true}], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in 'onClick_'", type: "Property" }] }
]
});

0 comments on commit 565016b

Please sign in to comment.