From c6a312e5e185672822e607574fac663d6ce7fa1e Mon Sep 17 00:00:00 2001 From: yeonjuan Date: Mon, 19 Feb 2024 23:40:21 +0900 Subject: [PATCH 1/6] fix(eslint-plugin): [explicit-function-return-type] improved checking for allowHigherOrderFunctions option --- .../rules/explicit-function-return-type.ts | 97 ++++++++++++------- .../rules/explicit-module-boundary-types.ts | 96 +++++++++++++----- .../src/util/explicitReturnTypeUtils.ts | 57 ++++++----- .../explicit-function-return-type.test.ts | 73 ++++++++++++++ .../explicit-module-boundary-types.test.ts | 43 ++++++++ 5 files changed, 281 insertions(+), 85 deletions(-) diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index d135f4c1a0d3..146ac1838fc5 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -2,6 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { createRule } from '../util'; +import type { FunctionInfo } from '../util/explicitReturnTypeUtils'; import { ancestorHasReturnType, checkFunctionReturnType, @@ -22,6 +23,11 @@ type Options = [ ]; type MessageIds = 'missingReturnType'; +type FunctionNode = + | TSESTree.ArrowFunctionExpression + | TSESTree.FunctionDeclaration + | TSESTree.FunctionExpression; + export default createRule({ name: 'explicit-function-return-type', meta: { @@ -98,6 +104,19 @@ export default createRule({ }, ], create(context, [options]) { + const functionInfoStack: FunctionInfo[] = []; + + function enterFunction(node: FunctionNode): void { + functionInfoStack.push({ + node, + returns: [], + }); + } + + function popFunctionInfo(): FunctionInfo { + return functionInfoStack.pop()!; + } + function isAllowedFunction( node: | TSESTree.ArrowFunctionExpression @@ -168,41 +187,49 @@ export default createRule({ return node.parent.type === AST_NODE_TYPES.CallExpression; } - return { - 'ArrowFunctionExpression, FunctionExpression'( - node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression, - ): void { - if ( - options.allowConciseArrowFunctionExpressionsStartingWithVoid && - node.type === AST_NODE_TYPES.ArrowFunctionExpression && - node.expression && - node.body.type === AST_NODE_TYPES.UnaryExpression && - node.body.operator === 'void' - ) { - return; - } + function exitFunctionExpression( + node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression, + ): void { + const info = popFunctionInfo(); - if (isAllowedFunction(node)) { - return; - } + if ( + options.allowConciseArrowFunctionExpressionsStartingWithVoid && + node.type === AST_NODE_TYPES.ArrowFunctionExpression && + node.expression && + node.body.type === AST_NODE_TYPES.UnaryExpression && + node.body.operator === 'void' + ) { + return; + } - if ( - options.allowTypedFunctionExpressions && - (isValidFunctionExpressionReturnType(node, options) || - ancestorHasReturnType(node)) - ) { - return; - } + if (isAllowedFunction(node)) { + return; + } - checkFunctionReturnType(node, options, context.sourceCode, loc => - context.report({ - node, - loc, - messageId: 'missingReturnType', - }), - ); - }, - FunctionDeclaration(node): void { + if ( + options.allowTypedFunctionExpressions && + (isValidFunctionExpressionReturnType(node, options) || + ancestorHasReturnType(node)) + ) { + return; + } + + checkFunctionReturnType(info, options, context.sourceCode, loc => + context.report({ + node, + loc, + messageId: 'missingReturnType', + }), + ); + } + + return { + 'ArrowFunctionExpression, FunctionExpression': enterFunction, + 'ArrowFunctionExpression:exit': exitFunctionExpression, + 'FunctionExpression:exit': exitFunctionExpression, + FunctionDeclaration: enterFunction, + 'FunctionDeclaration:exit'(node): void { + const info = popFunctionInfo(); if (isAllowedFunction(node)) { return; } @@ -210,7 +237,7 @@ export default createRule({ return; } - checkFunctionReturnType(node, options, context.sourceCode, loc => + checkFunctionReturnType(info, options, context.sourceCode, loc => context.report({ node, loc, @@ -218,6 +245,10 @@ export default createRule({ }), ); }, + ReturnStatement(node): void { + const current = functionInfoStack[functionInfoStack.length - 1]; + current.returns.push(node); + }, }; }, }); diff --git a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts index f04a71de8b63..9598454ea51b 100644 --- a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts +++ b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts @@ -5,6 +5,7 @@ import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import { createRule, isFunction } from '../util'; import type { FunctionExpression, + FunctionInfo, FunctionNode, } from '../util/explicitReturnTypeUtils'; import { @@ -101,8 +102,11 @@ export default createRule({ // tracks all of the functions we've already checked const checkedFunctions = new Set(); - // tracks functions that were found whilst traversing - const foundFunctions: FunctionNode[] = []; + const functionStack: FunctionNode[] = []; + const functionReturnsMap = new Map< + FunctionNode, + TSESTree.ReturnStatement[] + >(); // all nodes visited, avoids infinite recursion for cyclic references // (such as class member referring to itself) @@ -119,11 +123,17 @@ export default createRule({ any of them are part of a higher-order function */ + function getReturnsInFunction( + node: FunctionNode, + ): TSESTree.ReturnStatement[] { + return functionReturnsMap.get(node) ?? []; + } + return { - ExportDefaultDeclaration(node): void { + 'ExportDefaultDeclaration:exit'(node): void { checkNode(node.declaration); }, - 'ExportNamedDeclaration:not([source])'( + 'ExportNamedDeclaration:not([source]):exit'( node: TSESTree.ExportNamedDeclaration, ): void { if (node.declaration) { @@ -134,21 +144,35 @@ export default createRule({ } } }, - TSExportAssignment(node): void { + 'TSExportAssignment:exit'(node): void { checkNode(node.expression); }, 'ArrowFunctionExpression, FunctionDeclaration, FunctionExpression'( node: FunctionNode, ): void { - foundFunctions.push(node); + functionStack.push(node); + functionReturnsMap.set(node, []); + }, + 'ArrowFunctionExpression:exit'(): void { + functionStack.pop(); + }, + 'FunctionDeclaration:exit'(): void { + functionStack.pop(); + }, + 'FunctionExpression:exit'(): void { + functionStack.pop(); }, 'Program:exit'(): void { - for (const func of foundFunctions) { - if (isExportedHigherOrderFunction(func)) { - checkNode(func); + for (const [node, returns] of functionReturnsMap) { + if (isExportedHigherOrderFunction({ node, returns })) { + checkNode(node); } } }, + ReturnStatement(node): void { + const current = functionStack[functionStack.length - 1]; + functionReturnsMap.get(current)?.push(node); + }, }; function checkParameters( @@ -265,7 +289,9 @@ export default createRule({ return false; } - function isExportedHigherOrderFunction(node: FunctionNode): boolean { + function isExportedHigherOrderFunction({ + node, + }: FunctionInfo): boolean { let current: TSESTree.Node | undefined = node.parent; while (current) { if (current.type === AST_NODE_TYPES.ReturnStatement) { @@ -274,9 +300,12 @@ export default createRule({ continue; } + if (!isFunction(current)) { + return false; + } + const returns = getReturnsInFunction(current); if ( - !isFunction(current) || - !doesImmediatelyReturnFunctionExpression(current) + !doesImmediatelyReturnFunctionExpression({ node: current, returns }) ) { return false; } @@ -335,8 +364,10 @@ export default createRule({ switch (node.type) { case AST_NODE_TYPES.ArrowFunctionExpression: - case AST_NODE_TYPES.FunctionExpression: - return checkFunctionExpression(node); + case AST_NODE_TYPES.FunctionExpression: { + const returns = getReturnsInFunction(node); + return checkFunctionExpression({ node, returns }); + } case AST_NODE_TYPES.ArrayExpression: for (const element of node.elements) { @@ -360,8 +391,10 @@ export default createRule({ } return; - case AST_NODE_TYPES.FunctionDeclaration: - return checkFunction(node); + case AST_NODE_TYPES.FunctionDeclaration: { + const returns = getReturnsInFunction(node); + return checkFunction({ node, returns }); + } case AST_NODE_TYPES.MethodDefinition: case AST_NODE_TYPES.TSAbstractMethodDefinition: @@ -419,7 +452,10 @@ export default createRule({ checkParameters(node); } - function checkFunctionExpression(node: FunctionExpression): void { + function checkFunctionExpression({ + node, + returns, + }: FunctionInfo): void { if (checkedFunctions.has(node)) { return; } @@ -434,7 +470,7 @@ export default createRule({ } checkFunctionExpressionReturnType( - node, + { node, returns }, options, context.sourceCode, loc => { @@ -449,7 +485,10 @@ export default createRule({ checkParameters(node); } - function checkFunction(node: TSESTree.FunctionDeclaration): void { + function checkFunction({ + node, + returns, + }: FunctionInfo): void { if (checkedFunctions.has(node)) { return; } @@ -459,13 +498,18 @@ export default createRule({ return; } - checkFunctionReturnType(node, options, context.sourceCode, loc => { - context.report({ - node, - loc, - messageId: 'missingReturnType', - }); - }); + checkFunctionReturnType( + { node, returns }, + options, + context.sourceCode, + loc => { + context.report({ + node, + loc, + messageId: 'missingReturnType', + }); + }, + ); checkParameters(node); } diff --git a/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts b/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts index 512ff62202b9..1cfc834c1c1b 100644 --- a/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts +++ b/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts @@ -1,5 +1,9 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; -import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'; +import { + AST_NODE_TYPES, + ASTUtils, + ESLintUtils, +} from '@typescript-eslint/utils'; import { isConstructor, isSetter, isTypeAssertion } from './astUtils'; import { getFunctionHeadLoc } from './getFunctionHeadLoc'; @@ -9,6 +13,11 @@ type FunctionExpression = | TSESTree.FunctionExpression; type FunctionNode = FunctionExpression | TSESTree.FunctionDeclaration; +export interface FunctionInfo { + node: T; + returns: TSESTree.ReturnStatement[]; +} + /** * Checks if a node is a variable declarator with a type annotation. * ``` @@ -134,26 +143,22 @@ function isPropertyOfObjectWithType( * ``` */ function doesImmediatelyReturnFunctionExpression({ - body, -}: FunctionNode): boolean { - // Check if body is a block with a single statement - if (body.type === AST_NODE_TYPES.BlockStatement && body.body.length === 1) { - const [statement] = body.body; - - // Check if that statement is a return statement with an argument - if ( - statement.type === AST_NODE_TYPES.ReturnStatement && - !!statement.argument - ) { - // If so, check that returned argument as body - body = statement.argument; - } + node, + returns, +}: FunctionInfo): boolean { + if ( + node.type === AST_NODE_TYPES.ArrowFunctionExpression && + ASTUtils.isFunction(node.body) + ) { + return true; } - // Check if the body being returned is a function expression - return ( - body.type === AST_NODE_TYPES.ArrowFunctionExpression || - body.type === AST_NODE_TYPES.FunctionExpression + if (returns.length === 0) { + return false; + } + + return returns.every( + node => node.argument && ASTUtils.isFunction(node.argument), ); } @@ -251,12 +256,12 @@ function isValidFunctionExpressionReturnType( * Check that the function expression or declaration is valid. */ function isValidFunctionReturnType( - node: FunctionNode, + { node, returns }: FunctionInfo, options: Options, ): boolean { if ( options.allowHigherOrderFunctions && - doesImmediatelyReturnFunctionExpression(node) + doesImmediatelyReturnFunctionExpression({ node, returns }) ) { return true; } @@ -272,12 +277,12 @@ function isValidFunctionReturnType( * Checks if a function declaration/expression has a return type. */ function checkFunctionReturnType( - node: FunctionNode, + { node, returns }: FunctionInfo, options: Options, sourceCode: TSESLint.SourceCode, report: (loc: TSESTree.SourceLocation) => void, ): void { - if (isValidFunctionReturnType(node, options)) { + if (isValidFunctionReturnType({ node, returns }, options)) { return; } @@ -288,16 +293,16 @@ function checkFunctionReturnType( * Checks if a function declaration/expression has a return type. */ function checkFunctionExpressionReturnType( - node: FunctionExpression, + info: FunctionInfo, options: Options, sourceCode: TSESLint.SourceCode, report: (loc: TSESTree.SourceLocation) => void, ): void { - if (isValidFunctionExpressionReturnType(node, options)) { + if (isValidFunctionExpressionReturnType(info.node, options)) { return; } - checkFunctionReturnType(node, options, sourceCode, report); + checkFunctionReturnType(info, options, sourceCode, report); } /** diff --git a/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts b/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts index 8b0a05d6b5b4..9080804fdee6 100644 --- a/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts +++ b/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts @@ -267,6 +267,17 @@ const myObj = { }, { code: ` +() => { + const foo = 'foo'; + return function (): string { + return foo; + }; +}; + `, + options: [{ allowHigherOrderFunctions: true }], + }, + { + code: ` function fn() { return (): void => {}; } @@ -276,6 +287,31 @@ function fn() { { code: ` function fn() { + return function (): void {}; +} + `, + options: [{ allowHigherOrderFunctions: true }], + }, + { + code: ` +function fn() { + const bar = () => (): number => 1; + return function (): void {}; +} + `, + options: [{ allowHigherOrderFunctions: true }], + }, + { + code: ` +function fn(arg: boolean) { + if (arg) { + return () => (): number => 1; + } else { + return function (): string { + return 'foo'; + }; + } + return function (): void {}; } `, @@ -1230,6 +1266,43 @@ function fn() { }, { code: ` +function fn() { + const bar = () => (): number => 1; + const baz = () => () => 'baz'; + return function (): void {}; +} + `, + options: [{ allowHigherOrderFunctions: true }], + errors: [ + { + messageId: 'missingReturnType', + line: 4, + endLine: 4, + column: 24, + endColumn: 26, + }, + ], + }, + { + code: ` +function fn(arg: boolean) { + if (arg) return 'string'; + return function (): void {}; +} + `, + options: [{ allowHigherOrderFunctions: true }], + errors: [ + { + messageId: 'missingReturnType', + line: 2, + endLine: 2, + column: 1, + endColumn: 12, + }, + ], + }, + { + code: ` function FunctionDeclaration() { return function FunctionExpression_Within_FunctionDeclaration() { return function FunctionExpression_Within_FunctionExpression() { diff --git a/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts b/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts index 8a945ceca631..b96cb31d74ed 100644 --- a/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts +++ b/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts @@ -316,6 +316,28 @@ export default () => () => { }, { code: ` +export default () => () => { + const foo = 'foo'; + return (): void => { + return; + }; +}; + `, + options: [{ allowHigherOrderFunctions: true }], + }, + { + code: ` +export default () => () => { + const foo = () => (): string => 'foo'; + return (): void => { + return; + }; +}; + `, + options: [{ allowHigherOrderFunctions: true }], + }, + { + code: ` export class Accumulator { private count: number = 0; @@ -1728,6 +1750,27 @@ export function foo(outer) { }, ], }, + { + code: ` +export function foo(outer: boolean) { + if (outer) { + return 'string'; + } + return function (inner): void {}; +} + `, + options: [{ allowHigherOrderFunctions: true }], + errors: [ + { + messageId: 'missingReturnType', + line: 2, + column: 8, + data: { + name: 'inner', + }, + }, + ], + }, // test a few different argument patterns { code: ` From 7e6df4a3f88c3b41a20033611f246791942b54d1 Mon Sep 17 00:00:00 2001 From: yeonjuan Date: Wed, 21 Feb 2024 21:01:10 +0900 Subject: [PATCH 2/6] refactor --- .../rules/explicit-function-return-type.ts | 4 +- .../rules/explicit-module-boundary-types.ts | 41 +++++++++---------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index 146ac1838fc5..a5cba460cb95 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -224,10 +224,10 @@ export default createRule({ } return { - 'ArrowFunctionExpression, FunctionExpression': enterFunction, + 'ArrowFunctionExpression, FunctionExpression, FunctionDeclaration': + enterFunction, 'ArrowFunctionExpression:exit': exitFunctionExpression, 'FunctionExpression:exit': exitFunctionExpression, - FunctionDeclaration: enterFunction, 'FunctionDeclaration:exit'(node): void { const info = popFunctionInfo(); if (isAllowedFunction(node)) { diff --git a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts index 9598454ea51b..8260a2659597 100644 --- a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts +++ b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts @@ -112,6 +112,21 @@ export default createRule({ // (such as class member referring to itself) const alreadyVisited = new Set(); + function getReturnsInFunction( + node: FunctionNode, + ): TSESTree.ReturnStatement[] { + return functionReturnsMap.get(node) ?? []; + } + + function enterFunction(node: FunctionNode) { + functionStack.push(node); + functionReturnsMap.set(node, []); + } + + function exitFunction() { + functionStack.pop(); + } + /* # How the rule works: @@ -123,12 +138,6 @@ export default createRule({ any of them are part of a higher-order function */ - function getReturnsInFunction( - node: FunctionNode, - ): TSESTree.ReturnStatement[] { - return functionReturnsMap.get(node) ?? []; - } - return { 'ExportDefaultDeclaration:exit'(node): void { checkNode(node.declaration); @@ -147,21 +156,11 @@ export default createRule({ 'TSExportAssignment:exit'(node): void { checkNode(node.expression); }, - 'ArrowFunctionExpression, FunctionDeclaration, FunctionExpression'( - node: FunctionNode, - ): void { - functionStack.push(node); - functionReturnsMap.set(node, []); - }, - 'ArrowFunctionExpression:exit'(): void { - functionStack.pop(); - }, - 'FunctionDeclaration:exit'(): void { - functionStack.pop(); - }, - 'FunctionExpression:exit'(): void { - functionStack.pop(); - }, + 'ArrowFunctionExpression, FunctionDeclaration, FunctionExpression': + enterFunction, + 'ArrowFunctionExpression:exit': exitFunction, + 'FunctionDeclaration:exit': exitFunction, + 'FunctionExpression:exit': exitFunction, 'Program:exit'(): void { for (const [node, returns] of functionReturnsMap) { if (isExportedHigherOrderFunction({ node, returns })) { From 7f75d3a01db159e8e4a0fa4e311ec774f2a59980 Mon Sep 17 00:00:00 2001 From: yeonjuan Date: Wed, 21 Feb 2024 21:39:19 +0900 Subject: [PATCH 3/6] fix lint errors --- .../eslint-plugin/src/rules/explicit-module-boundary-types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts index 8260a2659597..c8981e403941 100644 --- a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts +++ b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts @@ -118,12 +118,12 @@ export default createRule({ return functionReturnsMap.get(node) ?? []; } - function enterFunction(node: FunctionNode) { + function enterFunction(node: FunctionNode): void { functionStack.push(node); functionReturnsMap.set(node, []); } - function exitFunction() { + function exitFunction(): void { functionStack.pop(); } From a61981a8c73fcbc9f9aaad314ac08aeeef098127 Mon Sep 17 00:00:00 2001 From: yeonjuan Date: Sun, 10 Mar 2024 11:31:03 +0900 Subject: [PATCH 4/6] apply reviews --- .../src/rules/explicit-function-return-type.ts | 18 +++++++++++------- .../explicit-function-return-type.test.ts | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index a5cba460cb95..ae19fcf0c9cd 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -1,7 +1,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import { AST_NODE_TYPES } from '@typescript-eslint/utils'; -import { createRule } from '../util'; +import { createRule, nullThrows } from '../util'; import type { FunctionInfo } from '../util/explicitReturnTypeUtils'; import { ancestorHasReturnType, @@ -113,8 +113,11 @@ export default createRule({ }); } - function popFunctionInfo(): FunctionInfo { - return functionInfoStack.pop()!; + function popFunctionInfo(exitNodeType: string): FunctionInfo { + return nullThrows( + functionInfoStack.pop(), + `Stack should exist on ${exitNodeType} exit`, + ); } function isAllowedFunction( @@ -190,7 +193,7 @@ export default createRule({ function exitFunctionExpression( node: TSESTree.ArrowFunctionExpression | TSESTree.FunctionExpression, ): void { - const info = popFunctionInfo(); + const info = popFunctionInfo('function expression'); if ( options.allowConciseArrowFunctionExpressionsStartingWithVoid && @@ -229,7 +232,7 @@ export default createRule({ 'ArrowFunctionExpression:exit': exitFunctionExpression, 'FunctionExpression:exit': exitFunctionExpression, 'FunctionDeclaration:exit'(node): void { - const info = popFunctionInfo(); + const info = popFunctionInfo('function declaration'); if (isAllowedFunction(node)) { return; } @@ -246,8 +249,9 @@ export default createRule({ ); }, ReturnStatement(node): void { - const current = functionInfoStack[functionInfoStack.length - 1]; - current.returns.push(node); + const current: FunctionInfo | undefined = + functionInfoStack[functionInfoStack.length - 1]; + current?.returns.push(node); }, }; }, diff --git a/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts b/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts index 9080804fdee6..2036927e0ca9 100644 --- a/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts +++ b/packages/eslint-plugin/tests/rules/explicit-function-return-type.test.ts @@ -8,6 +8,7 @@ const ruleTester = new RuleTester({ ruleTester.run('explicit-function-return-type', rule, { valid: [ + 'return;', { code: ` function test(): void { From 3dfe1541d445f842d09ad8e041f2fd806149c8d1 Mon Sep 17 00:00:00 2001 From: yeonjuan Date: Sun, 10 Mar 2024 14:51:20 +0900 Subject: [PATCH 5/6] fix lint error --- .../eslint-plugin/src/rules/explicit-function-return-type.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index ae19fcf0c9cd..13f98065e900 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -249,9 +249,8 @@ export default createRule({ ); }, ReturnStatement(node): void { - const current: FunctionInfo | undefined = - functionInfoStack[functionInfoStack.length - 1]; - current?.returns.push(node); + const current = functionInfoStack[functionInfoStack.length - 1]; + (current as FunctionInfo | undefined)?.returns.push(node); }, }; }, From 68ebb69fe3031b3ff86263934067fa059df49c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josh=20Goldberg=20=E2=9C=A8?= Date: Mon, 18 Mar 2024 08:14:45 -0400 Subject: [PATCH 6/6] Update packages/eslint-plugin/src/rules/explicit-function-return-type.ts --- .../eslint-plugin/src/rules/explicit-function-return-type.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts index 13f98065e900..9904dc2e5336 100644 --- a/packages/eslint-plugin/src/rules/explicit-function-return-type.ts +++ b/packages/eslint-plugin/src/rules/explicit-function-return-type.ts @@ -249,8 +249,7 @@ export default createRule({ ); }, ReturnStatement(node): void { - const current = functionInfoStack[functionInfoStack.length - 1]; - (current as FunctionInfo | undefined)?.returns.push(node); + functionInfoStack.at(-1)?.returns.push(node); }, }; },