diff --git a/docs/rules/class-methods-use-this.md b/docs/rules/class-methods-use-this.md index 89f6762b222..9b551e70ff0 100644 --- a/docs/rules/class-methods-use-this.md +++ b/docs/rules/class-methods-use-this.md @@ -91,11 +91,13 @@ class A { ### Exceptions ``` -"class-methods-use-this": [, { "exceptMethods": [<...exceptions>] }] +"class-methods-use-this": [, { "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 @@ -116,6 +118,13 @@ class A { foo() { } } + +/*eslint class-methods-use-this: ["error", { "exceptMethodsForRegex": ["^foo.*"] }] */ + +class B { + foobar() { + } +} ``` ## Further Reading diff --git a/lib/rules/class-methods-use-this.js b/lib/rules/class-methods-use-this.js index 4bf17090abc..97ef493e0d7 100644 --- a/lib/rules/class-methods-use-this.js +++ b/lib/rules/class-methods-use-this.js @@ -34,6 +34,12 @@ module.exports = { items: { type: "string" } + }, + exceptMethodsForRegex: { + type: "array", + items: { + type: "string" + } } }, additionalProperties: false @@ -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 = []; @@ -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)))); } /** diff --git a/tests/lib/rules/class-methods-use-this.js b/tests/lib/rules/class-methods-use-this.js index 5238b9d68b7..5ff01045b20 100644 --- a/tests/lib/rules/class-methods-use-this.js +++ b/tests/lib/rules/class-methods-use-this.js @@ -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"] }], @@ -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 },