diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index f6e4c5b56..d1400ca8a 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -348,6 +348,7 @@ mod oxc { pub mod misrefactored_assign_op; pub mod missing_throw; pub mod no_accumulating_spread; + pub mod no_async_await; pub mod no_barrel_file; pub mod number_arg_out_of_range; pub mod only_used_in_recursion; @@ -719,6 +720,7 @@ oxc_macros::declare_all_lint_rules! { oxc::no_barrel_file, oxc::number_arg_out_of_range, oxc::only_used_in_recursion, + oxc::no_async_await, oxc::uninvoked_array_callback, nextjs::google_font_display, nextjs::google_font_preconnect, diff --git a/crates/oxc_linter/src/rules/oxc/no_async_await.rs b/crates/oxc_linter/src/rules/oxc/no_async_await.rs new file mode 100644 index 000000000..a33c664bf --- /dev/null +++ b/crates/oxc_linter/src/rules/oxc/no_async_await.rs @@ -0,0 +1,99 @@ +use oxc_ast::AstKind; +use oxc_diagnostics::OxcDiagnostic; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; + +use crate::{context::LintContext, rule::Rule, AstNode}; + +fn no_async_await_diagnostic(span0: Span) -> OxcDiagnostic { + OxcDiagnostic::warn("oxc(no-async-await): Unexpected async/await") + .with_help("Async/await is not allowed") + .with_labels([span0.into()]) +} + +#[derive(Debug, Default, Clone)] +pub struct NoAsyncAwait; + +declare_oxc_lint!( + /// ### What it does + /// + /// Disallows the use of async/await. + /// + /// ### Example + /// ```javascript + /// async function foo() { + /// await bar(); + /// return baz(); + /// } + /// ``` + NoAsyncAwait, + restriction +); + +impl Rule for NoAsyncAwait { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + match node.kind() { + AstKind::Function(func_decl) => { + if func_decl.r#async { + if let Some(AstKind::ObjectProperty(obj_prop)) = + ctx.nodes().parent_kind(node.id()) + { + ctx.diagnostic(no_async_await_diagnostic(Span::new( + obj_prop.span.start, + obj_prop.span.start + 5, // "async".len() + ))); + } else { + ctx.diagnostic(no_async_await_diagnostic(Span::new( + func_decl.span.start, + func_decl.span.start + 5, + ))); + } + } + } + AstKind::ArrowFunctionExpression(arrow_expr) => { + if arrow_expr.r#async { + if let Some(AstKind::ObjectProperty(obj_prop)) = + ctx.nodes().parent_kind(node.id()) + { + ctx.diagnostic(no_async_await_diagnostic(Span::new( + obj_prop.span.start, + obj_prop.span.start + 5, + ))); + } else { + ctx.diagnostic(no_async_await_diagnostic(Span::new( + arrow_expr.span.start, + arrow_expr.span.start + 5, + ))); + }; + } + } + _ => {} + } + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + "function foo () {}", + "const foo = () => {}", + "function foo () { return bar(); }", + "class Foo { foo() {} }", + ]; + + let fail = vec![ + "async function foo() {}", + "const foo = async () => {}", + "async () => {}", + "const test = async () => {};", + " + const test = { + async test() {} + }; + ", + ]; + + Tester::new(NoAsyncAwait::NAME, pass, fail).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_async_await.snap b/crates/oxc_linter/src/snapshots/no_async_await.snap new file mode 100644 index 000000000..5dab8c16f --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_async_await.snap @@ -0,0 +1,40 @@ +--- +source: crates/oxc_linter/src/tester.rs +expression: no_async_await +--- + ⚠ oxc(no-async-await): Unexpected async/await + ╭─[no_async_await.tsx:1:1] + 1 │ async function foo() {} + · ───── + ╰──── + help: Async/await is not allowed + + ⚠ oxc(no-async-await): Unexpected async/await + ╭─[no_async_await.tsx:1:13] + 1 │ const foo = async () => {} + · ───── + ╰──── + help: Async/await is not allowed + + ⚠ oxc(no-async-await): Unexpected async/await + ╭─[no_async_await.tsx:1:1] + 1 │ async () => {} + · ───── + ╰──── + help: Async/await is not allowed + + ⚠ oxc(no-async-await): Unexpected async/await + ╭─[no_async_await.tsx:1:14] + 1 │ const test = async () => {}; + · ───── + ╰──── + help: Async/await is not allowed + + ⚠ oxc(no-async-await): Unexpected async/await + ╭─[no_async_await.tsx:3:17] + 2 │ const test = { + 3 │ async test() {} + · ───── + 4 │ }; + ╰──── + help: Async/await is not allowed