Skip to content

Commit

Permalink
Update: add enforceInMethodNames to no-underscore-dangle (fixes #7065)
Browse files Browse the repository at this point in the history
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 Jun 22, 2017
1 parent c596690 commit 171eedf
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
25 changes: 25 additions & 0 deletions docs/rules/no-underscore-dangle.md
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.
29 changes: 28 additions & 1 deletion lib/rules/no-underscore-dangle.js
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,37 @@ module.exports = {
}
}

/**
* Check if method declaration or method property has a underscore at the end
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
function checkForTrailingUnderscoreInMethod(node) {
const identifier = node.key.name;
const isMethod = node.type === "MethodDefinition" || node.type === "Property" && node.method;

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

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

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

}
Expand Down
12 changes: 10 additions & 2 deletions tests/lib/rules/no-underscore-dangle.js
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 171eedf

Please sign in to comment.