From 5d1658dce940ef6a5dec93f6aba6e0980a11cc22 Mon Sep 17 00:00:00 2001 From: Nbiba Bedis Date: Mon, 2 Oct 2023 03:15:07 +0100 Subject: [PATCH 1/6] linttuppp --- rust-toolchain.toml | 3 - src/rules/no_sync_fn_in_async_fn.rs | 173 ++++++++++++++++++++++++++-- 2 files changed, 166 insertions(+), 10 deletions(-) delete mode 100644 rust-toolchain.toml diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index 5299106e2..000000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,3 +0,0 @@ -[toolchain] -channel = "1.70.0" -components = ["clippy", "rustfmt"] diff --git a/src/rules/no_sync_fn_in_async_fn.rs b/src/rules/no_sync_fn_in_async_fn.rs index 72ba755ce..8a7b00b49 100644 --- a/src/rules/no_sync_fn_in_async_fn.rs +++ b/src/rules/no_sync_fn_in_async_fn.rs @@ -5,9 +5,13 @@ use crate::Program; use deno_ast::view::NodeTrait; use deno_ast::{view as ast_view, SourceRanged}; use if_chain::if_chain; +use deno_ast::view::{CallExpr, Callee, Expr, ParenExpr, VarDeclarator}; +use deno_ast::{SourceRange }; +use crate::swc_util::StringRepr; + #[derive(Debug)] -pub struct NoSyncFnInAsyncFn; +pub struct NoSyncFnInAsyncFn ; const CODE: &str = "no-sync-fn-in-async-fn"; const MESSAGE: &str = @@ -27,7 +31,7 @@ impl LintRule for NoSyncFnInAsyncFn { context: &mut Context, program: Program<'_>, ) { - NoSyncFnInAsyncFnHandler.traverse(program, context); + NoSyncFnInAsyncFnHandler::default().traverse(program, context); } #[cfg(feature = "docs")] @@ -58,14 +62,59 @@ fn extract_symbol<'a>( } } -struct NoSyncFnInAsyncFnHandler; - -impl Handler for NoSyncFnInAsyncFnHandler { - fn member_expr( +#[derive(Default)] +struct NoSyncFnInAsyncFnHandler { + blocking_fns: Vec, +} +impl NoSyncFnInAsyncFnHandler{ + fn maybe_add_diagnostic( &mut self, - member_expr: &ast_view::MemberExpr, + node: deno_ast::view::Node, ctx: &mut Context, ) { + // if we detect one of the blocking functions inside an async context, add lint + dbg!("a"); + dbg!(&self.blocking_fns); + dbg!(&node.text()); + if_chain! { + if self.blocking_fns.contains(&node.text().to_string()); + if inside_async_fn(node); + then { + dbg!("azea"); + self.add_diagnostic(node.range(), ctx) + } + } + } + + fn add_diagnostic(&mut self, range: SourceRange, ctx: &mut Context) { + ctx.add_diagnostic_with_hint( + range, + CODE, + MESSAGE, + format!("hello world"), + ); + } + + fn handle_paren_callee(&mut self, p: &ParenExpr, ctx: &mut Context) { + match p.expr { + // Nested paren callee ((eval))('var foo = 0;') + Expr::Paren(paren) => self.handle_paren_callee(paren, ctx), + // Single argument callee: (eval)('var foo = 0;') + Expr::Ident(ident) => { + self.maybe_add_diagnostic(p.expr.as_node(), ctx); + } + // Multiple arguments callee: (0, eval)('var foo = 0;') + Expr::Seq(seq) => { + for expr in &seq.exprs { + if let Expr::Ident(ident) = expr { + self.maybe_add_diagnostic(expr.as_node(), ctx); + } + } + } + _ => {} + } + } +} fn inside_async_fn(node: ast_view::Node) -> bool { use deno_ast::view::Node::*; match node { @@ -82,12 +131,51 @@ impl Handler for NoSyncFnInAsyncFnHandler { } } +impl Handler for NoSyncFnInAsyncFnHandler { + fn member_expr( + &mut self, + member_expr: &ast_view::MemberExpr, + ctx: &mut Context, + ) { + fn inside_sync_fn(node: ast_view::Node) -> Option { + use deno_ast::view::Node::*; + match node { + FnDecl(decl) if !decl.function.is_async() => Some(decl.ident.text().into()), + FnExpr(decl) if !decl.function.is_async() => decl.ident.map(|id|id.text().into()), + _ => { + let parent = match node.parent() { + Some(p) => p, + None => return None, + }; + inside_sync_fn(parent) + } + } + } + // Not check chained member expressions (e.g. `foo.bar.baz`) if member_expr.parent().is::() { return; } use deno_ast::view::Expr; + + // if we're calling a deno Sync api inside a function + // add that function to blocking functions list + if_chain! { + if let Expr::Ident(obj) = &member_expr.obj; + if ctx.scope().is_global(&obj.inner.to_id()); + let obj_symbol: &str = obj.sym(); + if obj_symbol == "Deno"; + if let Some(prop_symbol) = extract_symbol(&member_expr.prop); + if prop_symbol.strip_suffix("Sync").is_some(); + if let Some(sync_fn) = inside_sync_fn(member_expr.as_node()); + then { + dbg!(member_expr.text()); + self.blocking_fns.push(sync_fn); + } + } + + // if we detect deno sync api in an async context add lint if_chain! { if let Expr::Ident(obj) = &member_expr.obj; if ctx.scope().is_global(&obj.inner.to_id()); @@ -106,13 +194,84 @@ impl Handler for NoSyncFnInAsyncFnHandler { ); } } + } + + // // if we detect one of the blocking functions inside an async context, add lint + // if_chain! { + // if inside_async_fn(member_expr.as_node()); + // then { + // dbg!("{}",member_expr.text()); + // // ctx.add_diagnostic_with_hint( + // // member_expr.range(), + // // CODE, + // // MESSAGE, + // // format!("Consider changing this to an async equivalent: `await Deno.{}(..)`", + // // async_name), + // // ); + // } + // } + + fn var_declarator(&mut self, v: &VarDeclarator, ctx: &mut Context) { + if let Some(expr) = &v.init { + if let Expr::Ident(ident) = expr { + self.maybe_add_diagnostic(expr.as_node(), ctx); + } + + } } + + fn call_expr(&mut self, call_expr: &CallExpr, ctx: &mut Context) { + if let Callee::Expr(expr) = &call_expr.callee { + match expr { + Expr::Ident(ident) => { + self.maybe_add_diagnostic(expr.as_node(), ctx) + } + Expr::Paren(paren) => self.handle_paren_callee(paren, ctx), + _ => {} + } + } + } + + + } #[cfg(test)] mod tests { use super::*; + #[test] + fn hello() { + //TODO: is this fixable, this doesn't fail + // bacuse the parsing is done from top to bottom + assert_lint_ok! { + NoSyncFnInAsyncFn, + r#" + + async function foo2() { + foo() + } + function foo() { + Deno.readTextFileSync(""); + }"# + } + dbg!("reached here incorrectly"); + + // this fails cool + assert_lint_ok! { + NoSyncFnInAsyncFn, + r#" + function foo() { + Deno.readTextFileSync(""); + }" + async function foo2() { + foo() + } + + # + } + } + #[test] fn no_sync_fn_in_async_fn_is_valid() { assert_lint_ok! { From 6bd112841eeca9a2a6026167ac6d2feac26f8a98 Mon Sep 17 00:00:00 2001 From: Nbiba Bedis Date: Mon, 2 Oct 2023 03:26:10 +0100 Subject: [PATCH 2/6] traverse twice --- src/rules/no_sync_fn_in_async_fn.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/rules/no_sync_fn_in_async_fn.rs b/src/rules/no_sync_fn_in_async_fn.rs index 8a7b00b49..8e3248d3c 100644 --- a/src/rules/no_sync_fn_in_async_fn.rs +++ b/src/rules/no_sync_fn_in_async_fn.rs @@ -31,7 +31,9 @@ impl LintRule for NoSyncFnInAsyncFn { context: &mut Context, program: Program<'_>, ) { - NoSyncFnInAsyncFnHandler::default().traverse(program, context); + let mut rule = NoSyncFnInAsyncFnHandler::default(); + rule.traverse(program, context); + rule.traverse(program, context); } #[cfg(feature = "docs")] @@ -242,8 +244,6 @@ mod tests { #[test] fn hello() { - //TODO: is this fixable, this doesn't fail - // bacuse the parsing is done from top to bottom assert_lint_ok! { NoSyncFnInAsyncFn, r#" @@ -255,9 +255,7 @@ mod tests { Deno.readTextFileSync(""); }"# } - dbg!("reached here incorrectly"); - // this fails cool assert_lint_ok! { NoSyncFnInAsyncFn, r#" From 80925b24361e4a1171d7bce49a5d5b62a8b5bc3e Mon Sep 17 00:00:00 2001 From: Nbiba Bedis Date: Mon, 2 Oct 2023 03:26:33 +0100 Subject: [PATCH 3/6] fmt --- src/rules/fresh_handler_export.rs | 4 +- src/rules/fresh_server_event_handlers.rs | 4 +- src/rules/no_sync_fn_in_async_fn.rs | 118 +++++++++++------------ 3 files changed, 61 insertions(+), 65 deletions(-) diff --git a/src/rules/fresh_handler_export.rs b/src/rules/fresh_handler_export.rs index 619d80055..b4bd3c149 100644 --- a/src/rules/fresh_handler_export.rs +++ b/src/rules/fresh_handler_export.rs @@ -60,7 +60,9 @@ impl Handler for Visitor { let id = match export_decl.decl { Decl::Var(var_decl) => { if let Some(first) = var_decl.decls.first() { - let Pat::Ident(name_ident) = first.name else {return}; + let Pat::Ident(name_ident) = first.name else { + return; + }; name_ident.id } else { return; diff --git a/src/rules/fresh_server_event_handlers.rs b/src/rules/fresh_server_event_handlers.rs index 73dc64367..6a9ff762f 100644 --- a/src/rules/fresh_server_event_handlers.rs +++ b/src/rules/fresh_server_event_handlers.rs @@ -91,7 +91,9 @@ impl Handler for Visitor { _ => return, }; - let JSXExpr::Expr(expr_value) = expr.expr else {return}; + let JSXExpr::Expr(expr_value) = expr.expr else { + return; + }; // If we pass a function expression or an arrow function expression // then we know for sure that we can't render that. diff --git a/src/rules/no_sync_fn_in_async_fn.rs b/src/rules/no_sync_fn_in_async_fn.rs index 8e3248d3c..638b3f758 100644 --- a/src/rules/no_sync_fn_in_async_fn.rs +++ b/src/rules/no_sync_fn_in_async_fn.rs @@ -1,17 +1,16 @@ // Copyright 2020-2021 the Deno authors. All rights reserved. MIT license. use super::{Context, LintRule}; use crate::handler::{Handler, Traverse}; +use crate::swc_util::StringRepr; use crate::Program; use deno_ast::view::NodeTrait; +use deno_ast::view::{CallExpr, Callee, Expr, ParenExpr, VarDeclarator}; +use deno_ast::SourceRange; use deno_ast::{view as ast_view, SourceRanged}; use if_chain::if_chain; -use deno_ast::view::{CallExpr, Callee, Expr, ParenExpr, VarDeclarator}; -use deno_ast::{SourceRange }; -use crate::swc_util::StringRepr; - #[derive(Debug)] -pub struct NoSyncFnInAsyncFn ; +pub struct NoSyncFnInAsyncFn; const CODE: &str = "no-sync-fn-in-async-fn"; const MESSAGE: &str = @@ -31,7 +30,7 @@ impl LintRule for NoSyncFnInAsyncFn { context: &mut Context, program: Program<'_>, ) { - let mut rule = NoSyncFnInAsyncFnHandler::default(); + let mut rule = NoSyncFnInAsyncFnHandler::default(); rule.traverse(program, context); rule.traverse(program, context); } @@ -68,8 +67,8 @@ fn extract_symbol<'a>( struct NoSyncFnInAsyncFnHandler { blocking_fns: Vec, } -impl NoSyncFnInAsyncFnHandler{ - fn maybe_add_diagnostic( +impl NoSyncFnInAsyncFnHandler { + fn maybe_add_diagnostic( &mut self, node: deno_ast::view::Node, ctx: &mut Context, @@ -89,12 +88,7 @@ impl NoSyncFnInAsyncFnHandler{ } fn add_diagnostic(&mut self, range: SourceRange, ctx: &mut Context) { - ctx.add_diagnostic_with_hint( - range, - CODE, - MESSAGE, - format!("hello world"), - ); + ctx.add_diagnostic_with_hint(range, CODE, MESSAGE, format!("hello world")); } fn handle_paren_callee(&mut self, p: &ParenExpr, ctx: &mut Context) { @@ -117,21 +111,21 @@ impl NoSyncFnInAsyncFnHandler{ } } } - fn inside_async_fn(node: ast_view::Node) -> bool { - use deno_ast::view::Node::*; - match node { - FnDecl(decl) => decl.function.is_async(), - FnExpr(decl) => decl.function.is_async(), - ArrowExpr(decl) => decl.is_async(), - _ => { - let parent = match node.parent() { - Some(p) => p, - None => return false, - }; - inside_async_fn(parent) - } - } +fn inside_async_fn(node: ast_view::Node) -> bool { + use deno_ast::view::Node::*; + match node { + FnDecl(decl) => decl.function.is_async(), + FnExpr(decl) => decl.function.is_async(), + ArrowExpr(decl) => decl.is_async(), + _ => { + let parent = match node.parent() { + Some(p) => p, + None => return false, + }; + inside_async_fn(parent) } + } +} impl Handler for NoSyncFnInAsyncFnHandler { fn member_expr( @@ -142,8 +136,12 @@ impl Handler for NoSyncFnInAsyncFnHandler { fn inside_sync_fn(node: ast_view::Node) -> Option { use deno_ast::view::Node::*; match node { - FnDecl(decl) if !decl.function.is_async() => Some(decl.ident.text().into()), - FnExpr(decl) if !decl.function.is_async() => decl.ident.map(|id|id.text().into()), + FnDecl(decl) if !decl.function.is_async() => { + Some(decl.ident.text().into()) + } + FnExpr(decl) if !decl.function.is_async() => { + decl.ident.map(|id| id.text().into()) + } _ => { let parent = match node.parent() { Some(p) => p, @@ -196,46 +194,40 @@ impl Handler for NoSyncFnInAsyncFnHandler { ); } } - } - - // // if we detect one of the blocking functions inside an async context, add lint - // if_chain! { - // if inside_async_fn(member_expr.as_node()); - // then { - // dbg!("{}",member_expr.text()); - // // ctx.add_diagnostic_with_hint( - // // member_expr.range(), - // // CODE, - // // MESSAGE, - // // format!("Consider changing this to an async equivalent: `await Deno.{}(..)`", - // // async_name), - // // ); - // } - // } + } + + // // if we detect one of the blocking functions inside an async context, add lint + // if_chain! { + // if inside_async_fn(member_expr.as_node()); + // then { + // dbg!("{}",member_expr.text()); + // // ctx.add_diagnostic_with_hint( + // // member_expr.range(), + // // CODE, + // // MESSAGE, + // // format!("Consider changing this to an async equivalent: `await Deno.{}(..)`", + // // async_name), + // // ); + // } + // } - fn var_declarator(&mut self, v: &VarDeclarator, ctx: &mut Context) { + fn var_declarator(&mut self, v: &VarDeclarator, ctx: &mut Context) { if let Some(expr) = &v.init { - if let Expr::Ident(ident) = expr { - self.maybe_add_diagnostic(expr.as_node(), ctx); - } - + if let Expr::Ident(ident) = expr { + self.maybe_add_diagnostic(expr.as_node(), ctx); + } } } fn call_expr(&mut self, call_expr: &CallExpr, ctx: &mut Context) { if let Callee::Expr(expr) = &call_expr.callee { match expr { - Expr::Ident(ident) => { - self.maybe_add_diagnostic(expr.as_node(), ctx) - } + Expr::Ident(ident) => self.maybe_add_diagnostic(expr.as_node(), ctx), Expr::Paren(paren) => self.handle_paren_callee(paren, ctx), _ => {} } } } - - - } #[cfg(test)] @@ -257,8 +249,8 @@ mod tests { } assert_lint_ok! { - NoSyncFnInAsyncFn, - r#" + NoSyncFnInAsyncFn, + r#" function foo() { Deno.readTextFileSync(""); }" @@ -279,24 +271,24 @@ mod tests { Deno.readTextFileSync(""); } "#, - r#" + r#" const foo = (things) => { Deno.readTextFileSync(""); } "#, - r#" + r#" const foo = function(things) { Deno.readTextFileSync(""); } "#, - r#" + r#" class Foo { foo(things) { Deno.readTextFileSync(""); } } "#, - } + } } #[test] From fd7fb12e14a8119fefdf430839ef1dbbe5c4cc52 Mon Sep 17 00:00:00 2001 From: Nbiba Bedis Date: Mon, 2 Oct 2023 03:30:21 +0100 Subject: [PATCH 4/6] clean --- src/rules/no_sync_fn_in_async_fn.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/rules/no_sync_fn_in_async_fn.rs b/src/rules/no_sync_fn_in_async_fn.rs index 638b3f758..b4f978d0e 100644 --- a/src/rules/no_sync_fn_in_async_fn.rs +++ b/src/rules/no_sync_fn_in_async_fn.rs @@ -74,14 +74,10 @@ impl NoSyncFnInAsyncFnHandler { ctx: &mut Context, ) { // if we detect one of the blocking functions inside an async context, add lint - dbg!("a"); - dbg!(&self.blocking_fns); - dbg!(&node.text()); if_chain! { if self.blocking_fns.contains(&node.text().to_string()); if inside_async_fn(node); then { - dbg!("azea"); self.add_diagnostic(node.range(), ctx) } } @@ -170,7 +166,6 @@ impl Handler for NoSyncFnInAsyncFnHandler { if prop_symbol.strip_suffix("Sync").is_some(); if let Some(sync_fn) = inside_sync_fn(member_expr.as_node()); then { - dbg!(member_expr.text()); self.blocking_fns.push(sync_fn); } } @@ -196,21 +191,6 @@ impl Handler for NoSyncFnInAsyncFnHandler { } } - // // if we detect one of the blocking functions inside an async context, add lint - // if_chain! { - // if inside_async_fn(member_expr.as_node()); - // then { - // dbg!("{}",member_expr.text()); - // // ctx.add_diagnostic_with_hint( - // // member_expr.range(), - // // CODE, - // // MESSAGE, - // // format!("Consider changing this to an async equivalent: `await Deno.{}(..)`", - // // async_name), - // // ); - // } - // } - fn var_declarator(&mut self, v: &VarDeclarator, ctx: &mut Context) { if let Some(expr) = &v.init { if let Expr::Ident(ident) = expr { From 39cb842b1ad426bbd326ae5da46061e3b0ad31c3 Mon Sep 17 00:00:00 2001 From: Nbiba Bedis Date: Mon, 2 Oct 2023 03:31:25 +0100 Subject: [PATCH 5/6] no extra diff --- rust-toolchain.toml | 3 +++ src/rules/fresh_handler_export.rs | 4 +--- src/rules/fresh_server_event_handlers.rs | 4 +--- 3 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 rust-toolchain.toml diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 000000000..5299106e2 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.70.0" +components = ["clippy", "rustfmt"] diff --git a/src/rules/fresh_handler_export.rs b/src/rules/fresh_handler_export.rs index b4bd3c149..619d80055 100644 --- a/src/rules/fresh_handler_export.rs +++ b/src/rules/fresh_handler_export.rs @@ -60,9 +60,7 @@ impl Handler for Visitor { let id = match export_decl.decl { Decl::Var(var_decl) => { if let Some(first) = var_decl.decls.first() { - let Pat::Ident(name_ident) = first.name else { - return; - }; + let Pat::Ident(name_ident) = first.name else {return}; name_ident.id } else { return; diff --git a/src/rules/fresh_server_event_handlers.rs b/src/rules/fresh_server_event_handlers.rs index 6a9ff762f..73dc64367 100644 --- a/src/rules/fresh_server_event_handlers.rs +++ b/src/rules/fresh_server_event_handlers.rs @@ -91,9 +91,7 @@ impl Handler for Visitor { _ => return, }; - let JSXExpr::Expr(expr_value) = expr.expr else { - return; - }; + let JSXExpr::Expr(expr_value) = expr.expr else {return}; // If we pass a function expression or an arrow function expression // then we know for sure that we can't render that. From 7d9c0c22560a4f8bdf8d71d3ef9016e4071b989f Mon Sep 17 00:00:00 2001 From: Nbiba Bedis Date: Mon, 2 Oct 2023 03:41:33 +0100 Subject: [PATCH 6/6] cleanup --- src/rules/no_sync_fn_in_async_fn.rs | 104 +++++++++++++++------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/src/rules/no_sync_fn_in_async_fn.rs b/src/rules/no_sync_fn_in_async_fn.rs index b4f978d0e..8b0737ecf 100644 --- a/src/rules/no_sync_fn_in_async_fn.rs +++ b/src/rules/no_sync_fn_in_async_fn.rs @@ -74,28 +74,36 @@ impl NoSyncFnInAsyncFnHandler { ctx: &mut Context, ) { // if we detect one of the blocking functions inside an async context, add lint + let node_name = node.text().to_string(); if_chain! { - if self.blocking_fns.contains(&node.text().to_string()); + if self.blocking_fns.contains(&node_name); if inside_async_fn(node); then { - self.add_diagnostic(node.range(), ctx) + self.add_diagnostic(&node_name, node.range(), ctx) } } } - fn add_diagnostic(&mut self, range: SourceRange, ctx: &mut Context) { - ctx.add_diagnostic_with_hint(range, CODE, MESSAGE, format!("hello world")); + fn add_diagnostic( + &mut self, + node_name: &str, + range: SourceRange, + ctx: &mut Context, + ) { + ctx.add_diagnostic_with_hint( + range, + CODE, + MESSAGE, + format!("consier changing {node_name} to an async function"), + ); } fn handle_paren_callee(&mut self, p: &ParenExpr, ctx: &mut Context) { match p.expr { - // Nested paren callee ((eval))('var foo = 0;') Expr::Paren(paren) => self.handle_paren_callee(paren, ctx), - // Single argument callee: (eval)('var foo = 0;') Expr::Ident(ident) => { self.maybe_add_diagnostic(p.expr.as_node(), ctx); } - // Multiple arguments callee: (0, eval)('var foo = 0;') Expr::Seq(seq) => { for expr in &seq.exprs { if let Expr::Ident(ident) = expr { @@ -107,21 +115,6 @@ impl NoSyncFnInAsyncFnHandler { } } } -fn inside_async_fn(node: ast_view::Node) -> bool { - use deno_ast::view::Node::*; - match node { - FnDecl(decl) => decl.function.is_async(), - FnExpr(decl) => decl.function.is_async(), - ArrowExpr(decl) => decl.is_async(), - _ => { - let parent = match node.parent() { - Some(p) => p, - None => return false, - }; - inside_async_fn(parent) - } - } -} impl Handler for NoSyncFnInAsyncFnHandler { fn member_expr( @@ -129,26 +122,7 @@ impl Handler for NoSyncFnInAsyncFnHandler { member_expr: &ast_view::MemberExpr, ctx: &mut Context, ) { - fn inside_sync_fn(node: ast_view::Node) -> Option { - use deno_ast::view::Node::*; - match node { - FnDecl(decl) if !decl.function.is_async() => { - Some(decl.ident.text().into()) - } - FnExpr(decl) if !decl.function.is_async() => { - decl.ident.map(|id| id.text().into()) - } - _ => { - let parent = match node.parent() { - Some(p) => p, - None => return None, - }; - inside_sync_fn(parent) - } - } - } - - // Not check chained member expressions (e.g. `foo.bar.baz`) + // do not check chained member expressions (e.g. `foo.bar.baz`) if member_expr.parent().is::() { return; } @@ -210,22 +184,56 @@ impl Handler for NoSyncFnInAsyncFnHandler { } } +fn inside_async_fn(node: ast_view::Node) -> bool { + use deno_ast::view::Node::*; + match node { + FnDecl(decl) => decl.function.is_async(), + FnExpr(decl) => decl.function.is_async(), + ArrowExpr(decl) => decl.is_async(), + _ => { + let parent = match node.parent() { + Some(p) => p, + None => return false, + }; + inside_async_fn(parent) + } + } +} + +fn inside_sync_fn(node: ast_view::Node) -> Option { + use deno_ast::view::Node::*; + match node { + FnDecl(decl) if !decl.function.is_async() => Some(decl.ident.text().into()), + FnExpr(decl) if !decl.function.is_async() => { + decl.ident.map(|id| id.text().into()) + } + _ => { + let parent = match node.parent() { + Some(p) => p, + None => return None, + }; + inside_sync_fn(parent) + } + } +} + #[cfg(test)] mod tests { use super::*; #[test] - fn hello() { + fn no_sync_fn_in_async_fn_fails_nested() { + // both of these should panic + // TODO switch to assert_err assert_lint_ok! { NoSyncFnInAsyncFn, r#" - async function foo2() { foo() } - function foo() { + function foo() { Deno.readTextFileSync(""); - }"# + }"# } assert_lint_ok! { @@ -236,9 +244,7 @@ mod tests { }" async function foo2() { foo() - } - - # + }"# } }