diff --git a/crates/oxc_linter/src/rules/promise/catch_or_return.rs b/crates/oxc_linter/src/rules/promise/catch_or_return.rs index d58ff96fb49aa..42dc9c375773e 100644 --- a/crates/oxc_linter/src/rules/promise/catch_or_return.rs +++ b/crates/oxc_linter/src/rules/promise/catch_or_return.rs @@ -76,6 +76,7 @@ declare_oxc_lint!( /// function doSomethingElse() { /// return myPromise.then(doSomething) /// } + /// const arrowFunc = () => myPromise.then(doSomething) /// ``` CatchOrReturn, promise, @@ -137,6 +138,10 @@ impl Rule for CatchOrReturn { return; } + if is_arrow_function_expression_return(node, ctx) { + return; + } + if self.is_allowed_promise_termination(call_expr) { return; } @@ -223,6 +228,20 @@ fn is_cypress_call(call_expr: &CallExpression) -> bool { is_cypress_call(object_call_expr) } +fn is_arrow_function_expression_return(node: &AstNode, ctx: &LintContext) -> bool { + let parent = ctx.nodes().parent_node(node.id()); + + if !matches!(parent.kind(), AstKind::FunctionBody(_)) { + return false; + } + + if let AstKind::ArrowFunctionExpression(arrow_func) = ctx.nodes().parent_kind(parent.id()) { + return arrow_func.expression; + } + + false +} + #[test] fn test() { use crate::tester::Tester; @@ -313,6 +332,14 @@ fn test() { // Cypress ("cy.get('.myClass').then(go)", None), ("cy.get('button').click().then()", None), + ("const a = () => Promise.resolve(null)", None), + ("const b = () => Promise.resolve({ id: '' })", None), + ("const obj = { method: () => Promise.resolve(null) }", None), + ("const obj = { openLinkModalPrompt: () => Promise.resolve(null) }", None), + ("const arr = [() => Promise.resolve(null)]", None), + ("foo(() => Promise.resolve(null))", None), + ("const a = () => { return Promise.resolve(null); }", None), + ("function a() { const b = () => Promise.resolve(null); return b; }", None), ]; let fail = vec![ @@ -346,6 +373,8 @@ fn test() { ("frank().catch(go)", Some(serde_json::json!([{ "terminationMethod": "done" }]))), ("frank().catch(go).someOtherMethod()", None), ("frank()['catch'](go).someOtherMethod()", None), + ("const a = () => { Promise.resolve(null); }", None), + ("function a() { const b = () => { Promise.resolve(null); }; return b; }", None), ]; Tester::new(CatchOrReturn::NAME, CatchOrReturn::PLUGIN, pass, fail).test_and_snapshot(); diff --git a/crates/oxc_linter/src/snapshots/promise_catch_or_return.snap b/crates/oxc_linter/src/snapshots/promise_catch_or_return.snap index f7c212be37b07..b27fea88674dc 100644 --- a/crates/oxc_linter/src/snapshots/promise_catch_or_return.snap +++ b/crates/oxc_linter/src/snapshots/promise_catch_or_return.snap @@ -168,3 +168,17 @@ source: crates/oxc_linter/src/tester.rs · ────────────────────────────────────── ╰──── help: Return the promise or chain a `catch()`. + + ⚠ eslint-plugin-promise(catch-or-return): Expected `catch` or `return`. + ╭─[catch_or_return.tsx:1:19] + 1 │ const a = () => { Promise.resolve(null); } + · ───────────────────── + ╰──── + help: Return the promise or chain a `catch()`. + + ⚠ eslint-plugin-promise(catch-or-return): Expected `catch` or `return`. + ╭─[catch_or_return.tsx:1:34] + 1 │ function a() { const b = () => { Promise.resolve(null); }; return b; } + · ───────────────────── + ╰──── + help: Return the promise or chain a `catch()`.