Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update: allowFunctionParams option in no-underscore-dangle (fixes 12579) #13545

Merged
merged 20 commits into from Aug 14, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 20 additions & 5 deletions docs/rules/no-underscore-dangle.md
Expand Up @@ -39,11 +39,12 @@ var file = __filename;

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
* `"allowAfterThisConstructor": false` (default) disallows dangling underscores in members of the `this.constructor` object
* `"enforceInMethodNames": false` (default) allows dangling underscores in method names
- `"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
- `"allowAfterThisConstructor": false` (default) disallows dangling underscores in members of the `this.constructor` object
- `"enforceInMethodNames": false` (default) allows dangling underscores in method names
- `"allowFunctionParams": false` (default) disallows dangling underscores in first letter of function parameter name

### allow

Expand Down Expand Up @@ -113,6 +114,20 @@ const o = {
};
```

### allowFunctionParams

Examples of **correct** code for this rule with the `{ "allowFunctionParams": true }` option:
sunghyunjo marked this conversation as resolved.
Show resolved Hide resolved

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

function foo (_bar) {}

const foo = function onClick (_bar) {}

const foo = (_bar) {};
sunghyunjo marked this conversation as resolved.
Show resolved Hide resolved
```

## When Not To Use It

If you want to allow dangling underscores in identifiers, then you can safely turn this rule off.
32 changes: 31 additions & 1 deletion lib/rules/no-underscore-dangle.js
Expand Up @@ -45,6 +45,10 @@ module.exports = {
enforceInMethodNames: {
type: "boolean",
default: false
},
allowFunctionParams: {
type: "boolean",
default: false
}
},
additionalProperties: false
Expand All @@ -64,6 +68,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 allowFunctionParams = typeof options.allowFunctionParams !== "undefined" ? options.allowFunctionParams : false;

//-------------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -125,6 +130,28 @@ module.exports = {
node.object.object.type === "ThisExpression";
}

/**
* Check if function parameter has a underscore at the beginning.
sunghyunjo marked this conversation as resolved.
Show resolved Hide resolved
* @param {ASTNode} node node to evaluate
sunghyunjo marked this conversation as resolved.
Show resolved Hide resolved
* @returns {boolean} true if function parameter name has a underscore at the beginning.
* @private
*/
function checkForFollowingUnderscoreInFunctionParameter(node) {
sunghyunjo marked this conversation as resolved.
Show resolved Hide resolved
if (!allowFunctionParams && node.params) {
sunghyunjo marked this conversation as resolved.
Show resolved Hide resolved
const identifier = node.params.name;

if (typeof identifier !== "undefined" && identifier.indexOf("_") === 0) {
sunghyunjo marked this conversation as resolved.
Show resolved Hide resolved
context.report({
node,
messageId: "unexpectedUnderscore",
data: {
identifier
}
});
}
}
}

/**
* Check if function has a underscore at the end
* @param {ASTNode} node node to evaluate
Expand All @@ -145,6 +172,7 @@ module.exports = {
});
}
}
checkForFollowingUnderscoreInFunctionParameter(node);
sunghyunjo marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down Expand Up @@ -225,7 +253,9 @@ module.exports = {
VariableDeclarator: checkForTrailingUnderscoreInVariableExpression,
MemberExpression: checkForTrailingUnderscoreInMemberExpression,
MethodDefinition: checkForTrailingUnderscoreInMethod,
Property: checkForTrailingUnderscoreInMethod
Property: checkForTrailingUnderscoreInMethod,
FunctionExpression: checkForFollowingUnderscoreInFunctionParameter,
ArrowFunctionExpression: checkForFollowingUnderscoreInFunctionParameter
};

}
Expand Down
14 changes: 12 additions & 2 deletions tests/lib/rules/no-underscore-dangle.js
Expand Up @@ -26,6 +26,7 @@ ruleTester.run("no-underscore-dangle", rule, {
"console.log(__filename); console.log(__dirname);",
"var _ = require('underscore');",
"var a = b._;",
"function foo(bar) {}",
{ code: "export default function() {}", parserOptions: { ecmaVersion: 6, sourceType: "module" } },
{ code: "var _foo = 1", options: [{ allow: ["_foo"] }] },
{ code: "var __proto__ = 1;", options: [{ allow: ["__proto__"] }] },
Expand All @@ -40,7 +41,15 @@ ruleTester.run("no-underscore-dangle", rule, {
{ code: "const o = { _onClick() { } }", options: [{ allow: ["_onClick"], enforceInMethodNames: true }], parserOptions: { ecmaVersion: 6 } },
{ code: "const o = { _foo: 'bar' }", parserOptions: { ecmaVersion: 6 } },
{ code: "const o = { foo_: 'bar' }", parserOptions: { ecmaVersion: 6 } },
{ code: "this.constructor._bar", options: [{ allowAfterThisConstructor: true }] }
{ code: "this.constructor._bar", options: [{ allowAfterThisConstructor: true }] },
{ code: "const foo = { onClick(bar) { } }", parserOptions: { ecmaVersion: 6 } },
{ code: "const foo = (bar) => {}", parserOptions: { ecmaVersion: 6 } },
{ code: "function foo(_bar) {}", options: [{ allowFunctionParams: true }] },
{ code: "const foo = { onClick(_bar) { } }", options: [{ allowFunctionParams: true }], parserOptions: { ecmaVersion: 6 } },
{ code: "const foo = (_bar) => {}", options: [{ allowFunctionParams: true }], parserOptions: { ecmaVersion: 6 } },
{ code: "function foo(bar) {}", options: [{ allowFunctionParams: false }], parserOptions: { ecmaVersion: 6 } },
{ code: "const foo = { onClick(bar) { } }", options: [{ allowFunctionParams: false }], parserOptions: { ecmaVersion: 6 } },
{ code: "const foo = (bar) => {}", options: [{ allowFunctionParams: false }], parserOptions: { ecmaVersion: 6 } }
],
invalid: [
{ code: "var _foo = 1", errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "_foo" }, type: "VariableDeclarator" }] },
Expand All @@ -57,6 +66,7 @@ ruleTester.run("no-underscore-dangle", rule, {
{ code: "const o = { _onClick() { } }", options: [{ enforceInMethodNames: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "_onClick" }, type: "Property" }] },
{ code: "const o = { onClick_() { } }", options: [{ enforceInMethodNames: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "onClick_" }, type: "Property" }] },
{ code: "this.constructor._bar", errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "_bar" }, type: "MemberExpression" }] },
{ code: "foo.constructor._bar", options: [{ allowAfterThisConstructor: true }], errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "_bar" }, type: "MemberExpression" }] }
{ code: "function foo(_bar) {}", errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "_bar" }, type: "FunctionDeclaration" }] },
{ code: "function foo(_bar) {}", options: [{ allowFunctionParams: false }], errors: [{ messageId: "unexpectedUnderscore", data: { identifier: "_bar" }, type: "FunctionDeclaration" }] }
]
});