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

New: Rule class-methods-use-this option exceptMethods accepts regex #12305

Closed
wants to merge 13 commits into from
11 changes: 10 additions & 1 deletion docs/rules/class-methods-use-this.md
Expand Up @@ -91,11 +91,13 @@ class A {
### Exceptions

```
"class-methods-use-this": [<enabled>, { "exceptMethods": [<...exceptions>] }]
"class-methods-use-this": [<enabled>, { "exceptMethods": [<...exceptions>], "exceptMethodsForRegex": [<...exceptions>] }]
```

The `exceptMethods` option allows you to pass an array of method names for which you would like to ignore warnings. For example, you might have a spec from an external library that requires you to overwrite a method as a regular function (and not as a static method) and does not use `this` inside the function body. In this case, you can add that method to ignore in the warnings.

The option `exceptMethodsForRegex` works like exceptMethods just for regular expressions.

Examples of **incorrect** code for this rule when used without exceptMethods:

```js
Expand All @@ -116,6 +118,13 @@ class A {
foo() {
}
}

/*eslint class-methods-use-this: ["error", { "exceptMethodsForRegex": ["^foo.*"] }] */

class B {
foobar() {
}
}
```

## Further Reading
Expand Down
10 changes: 9 additions & 1 deletion lib/rules/class-methods-use-this.js
Expand Up @@ -34,6 +34,12 @@ module.exports = {
items: {
type: "string"
}
},
exceptMethodsForRegex: {
type: "array",
items: {
type: "string"
}
}
},
additionalProperties: false
Expand All @@ -45,7 +51,9 @@ module.exports = {
},
create(context) {
const config = Object.assign({}, context.options[0]);

const exceptMethods = new Set(config.exceptMethods || []);
const exceptMethodsForRegex = (config.exceptMethodsForRegex || []).map(e => new RegExp(e, "u"));

const stack = [];

Expand Down Expand Up @@ -77,7 +85,7 @@ module.exports = {
*/
function isIncludedInstanceMethod(node) {
return isInstanceMethod(node) &&
(node.computed || !exceptMethods.has(node.key.name));
(node.computed || (!exceptMethods.has(node.key.name) && !exceptMethodsForRegex.find(e => e.test(node.key.name))));
}

/**
Expand Down
24 changes: 24 additions & 0 deletions tests/lib/rules/class-methods-use-this.js
Expand Up @@ -98,6 +98,14 @@ ruleTester.run("class-methods-use-this", rule, {
{ type: "FunctionExpression", line: 1, column: 34, messageId: "missingThis", data: { name: "method 'hasOwnProperty'" } }
]
},
{
code: "class A { foobar() {} hasOwnProperty() {} }",
options: [{ exceptMethodsForRegex: ["^foo.*"] }],
parserOptions: { ecmaVersion: 6 },
errors: [
{ type: "FunctionExpression", line: 1, column: 37, messageId: "missingThis", data: { name: "method 'hasOwnProperty'" } }
]
},
{
code: "class A { [foo]() {} }",
options: [{ exceptMethods: ["foo"] }],
Expand All @@ -106,6 +114,22 @@ ruleTester.run("class-methods-use-this", rule, {
{ type: "FunctionExpression", line: 1, column: 16, messageId: "missingThis", data: { name: "method" } }
]
},
{
code: "class A { [foobar]() {} }",
options: [{ exceptMethodsForRegex: ["^foo.*"] }],
parserOptions: { ecmaVersion: 6 },
errors: [
{ type: "FunctionExpression", line: 1, column: 19, messageId: "missingThis", data: { name: "method" } }
]
},
{
code: "class A { foo() {} bar() {} afoobar() {} }",
options: [{ exceptMethods: ["bar"], exceptMethodsForRegex: ["^afoo.*"] }],
parserOptions: { ecmaVersion: 6 },
errors: [
{ type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
]
},
{
code: "class A { foo(){} 'bar'(){} 123(){} [`baz`](){} [a](){} [f(a)](){} get quux(){} set[a](b){} *quuux(){} }",
parserOptions: { ecmaVersion: 6 },
Expand Down