From 13c05aefb0e6531d320629e04b7207a3baebacb0 Mon Sep 17 00:00:00 2001 From: Joshua Chen Date: Tue, 17 May 2022 01:19:46 +0800 Subject: [PATCH] feat(eslint-plugin): [no-empty-function] new allow option overrideMethods (#4923) --- .../docs/rules/no-empty-function.md | 19 +++++++++++++- .../src/rules/no-empty-function.ts | 16 +++++++++++- .../tests/rules/no-empty-function.test.ts | 25 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-empty-function.md b/packages/eslint-plugin/docs/rules/no-empty-function.md index 0920bf6f3c7..b25459f6a5d 100644 --- a/packages/eslint-plugin/docs/rules/no-empty-function.md +++ b/packages/eslint-plugin/docs/rules/no-empty-function.md @@ -28,7 +28,8 @@ This rule adds the following options: type AdditionalAllowOptionEntries = | 'private-constructors' | 'protected-constructors' - | 'decoratedFunctions'; + | 'decoratedFunctions' + | 'overrideMethods'; type AllowOptionEntries = | BaseNoEmptyFunctionAllowOptionEntries @@ -77,6 +78,22 @@ class Foo { } ``` +### allow: `overrideMethods` + +Examples of correct code for the `{ "allow": ["overrideMethods"] }` option: + +```ts +abstract class Base { + protected greet(): void { + console.log('Hello!'); + } +} + +class Foo extends Base { + protected override greet(): void {} +} +``` + ## How to Use ```jsonc diff --git a/packages/eslint-plugin/src/rules/no-empty-function.ts b/packages/eslint-plugin/src/rules/no-empty-function.ts index 806312b2117..d3a9f74b770 100644 --- a/packages/eslint-plugin/src/rules/no-empty-function.ts +++ b/packages/eslint-plugin/src/rules/no-empty-function.ts @@ -30,6 +30,7 @@ const schema = util.deepMerge( 'asyncFunctions', 'asyncMethods', 'decoratedFunctions', + 'overrideMethods', ], }, }, @@ -63,6 +64,7 @@ export default util.createRule({ ); const isAllowedPrivateConstructors = allow.includes('private-constructors'); const isAllowedDecoratedFunctions = allow.includes('decoratedFunctions'); + const isAllowedOverrideMethods = allow.includes('overrideMethods'); /** * Check if the method body is empty @@ -138,12 +140,24 @@ export default util.createRule({ return false; } + function isAllowedEmptyOverrideMethod( + node: TSESTree.FunctionExpression, + ): boolean { + return ( + isAllowedOverrideMethods && + isBodyEmpty(node) && + node.parent?.type === AST_NODE_TYPES.MethodDefinition && + node.parent.override === true + ); + } + return { ...rules, FunctionExpression(node): void { if ( isAllowedEmptyConstructor(node) || - isAllowedEmptyDecoratedFunctions(node) + isAllowedEmptyDecoratedFunctions(node) || + isAllowedEmptyOverrideMethod(node) ) { return; } diff --git a/packages/eslint-plugin/tests/rules/no-empty-function.test.ts b/packages/eslint-plugin/tests/rules/no-empty-function.test.ts index d9f37deaaf1..7d29b0fa5a2 100644 --- a/packages/eslint-plugin/tests/rules/no-empty-function.test.ts +++ b/packages/eslint-plugin/tests/rules/no-empty-function.test.ts @@ -72,6 +72,14 @@ class Foo { `, options: [{ allow: ['decoratedFunctions'] }], }, + { + code: ` +class Foo extends Base { + override foo() {} +} + `, + options: [{ allow: ['overrideMethods'] }], + }, ], invalid: [ @@ -192,5 +200,22 @@ class Foo { }, ], }, + { + code: ` +class Foo extends Base { + override foo() {} +} + `, + errors: [ + { + messageId: 'unexpected', + data: { + name: "method 'foo'", + }, + line: 3, + column: 18, + }, + ], + }, ], });