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
#7234)

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 option is false by default.
  • Loading branch information
gabro authored and not-an-aardvark committed Jul 16, 2017
1 parent 128591f commit 3c231fa
Show file tree
Hide file tree
Showing 3 changed files with 65 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
14 changes: 12 additions & 2 deletions tests/lib/rules/no-underscore-dangle.js
Expand Up @@ -32,7 +32,13 @@ 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 } },
{ code: "const o = { _foo: 'bar' }", parserOptions: { ecmaVersion: 6 } },
{ code: "const o = { foo_: 'bar' }", parserOptions: { ecmaVersion: 6 } }
],
invalid: [
{ code: "var _foo = 1", errors: [{ message: "Unexpected dangling '_' in '_foo'.", type: "VariableDeclarator" }] },
Expand All @@ -43,6 +49,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 3c231fa

Please sign in to comment.