From b176702ccd43b4e31011c2935a85b5668cb98d4a Mon Sep 17 00:00:00 2001 From: yeonjuan Date: Thu, 25 Jan 2024 02:19:36 +0900 Subject: [PATCH] apply reviews --- .../src/rules/consistent-return.ts | 42 +++++++++---- .../tests/rules/consistent-return.test.ts | 59 +++++++++++++++++++ .../eslint-plugin/typings/eslint-rules.d.ts | 5 ++ 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/packages/eslint-plugin/src/rules/consistent-return.ts b/packages/eslint-plugin/src/rules/consistent-return.ts index 197c6bab2975..1e278fa18572 100644 --- a/packages/eslint-plugin/src/rules/consistent-return.ts +++ b/packages/eslint-plugin/src/rules/consistent-return.ts @@ -38,11 +38,18 @@ export default createRule({ const services = getParserServices(context); const checker = services.program.getTypeChecker(); const rules = baseRule.create(context); + const functions: FunctionNode[] = []; - let functionNode: FunctionNode | null; + function enterFunction(node: FunctionNode): void { + functions.push(node); + } + + function exitFunction(): void { + functions.pop(); + } - function setFunctionNode(node: FunctionNode): void { - functionNode = node; + function getCurrentFunction(): FunctionNode | null { + return functions[functions.length - 1] ?? null; } function isReturnPromiseVoid( @@ -79,14 +86,29 @@ export default createRule({ return { ...rules, - FunctionDeclaration: setFunctionNode, - FunctionExpression: setFunctionNode, - ArrowFunctionExpression: setFunctionNode, + FunctionDeclaration: enterFunction, + FunctionExpression: enterFunction, + ArrowFunctionExpression: enterFunction, + 'FunctionDeclaration:exit'(node): void { + exitFunction(); + rules['FunctionDeclaration:exit'](node); + }, + 'FunctionExpression:exit'(node): void { + exitFunction(); + rules['FunctionExpression:exit'](node); + }, + 'ArrowFunctionExpression:exit'(node): void { + exitFunction(); + rules['ArrowFunctionExpression:exit'](node); + }, ReturnStatement(node): void { - if (!node.argument && functionNode) { - if (isReturnVoidOrThenableVoid(functionNode)) { - return; - } + const functionNode = getCurrentFunction(); + if ( + !node.argument && + functionNode && + isReturnVoidOrThenableVoid(functionNode) + ) { + return; } rules.ReturnStatement(node); }, diff --git a/packages/eslint-plugin/tests/rules/consistent-return.test.ts b/packages/eslint-plugin/tests/rules/consistent-return.test.ts index e8e8e3e1323c..51d338907237 100644 --- a/packages/eslint-plugin/tests/rules/consistent-return.test.ts +++ b/packages/eslint-plugin/tests/rules/consistent-return.test.ts @@ -114,6 +114,32 @@ ruleTester.run('consistent-return', rule, { } } `, + ` + declare function bar(): void; + function foo(flag: boolean): void { + function fn(): string { + return '1'; + } + if (flag) { + return bar(); + } + return; + } + `, + ` + class Foo { + foo(flag: boolean): void { + const bar = (): void => { + if (flag) return; + return this.foo(); + }; + if (flag) { + return this.bar(); + } + return; + } + } + `, ], invalid: [ { @@ -155,6 +181,39 @@ ruleTester.run('consistent-return', rule, { }, ], }, + { + code: ` + declare function foo(): void; + function bar(flag: boolean): undefined { + function baz(): undefined { + if (flag) return; + return undefined; + } + if (flag) return baz(); + return; + } + `, + errors: [ + { + messageId: 'unexpectedReturnValue', + data: { name: "Function 'baz'" }, + type: AST_NODE_TYPES.ReturnStatement, + line: 6, + column: 13, + endLine: 6, + endColumn: 30, + }, + { + messageId: 'missingReturnValue', + data: { name: "Function 'bar'" }, + type: AST_NODE_TYPES.ReturnStatement, + line: 9, + column: 11, + endLine: 9, + endColumn: 18, + }, + ], + }, { code: ` function foo(flag: boolean): Promise { diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 939d8fc60fce..23d58999d6cc 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -37,6 +37,11 @@ declare module 'eslint/lib/rules/consistent-return' { ], { ReturnStatement(node: TSESTree.ReturnStatement): void; + 'FunctionDeclaration:exit'(node: TSESTree.FunctionDeclaration): void; + 'FunctionExpression:exit'(node: TSESTree.FunctionExpression): void; + 'ArrowFunctionExpression:exit'( + node: TSESTree.ArrowFunctionExpression, + ): void; } >; export = rule;