From 59d295d29609b1d48150f7dcf97abaf1e4bb4521 Mon Sep 17 00:00:00 2001 From: A4-Tacks Date: Sun, 2 Aug 2026 01:25:33 +0800 Subject: [PATCH] fix: complete let in macro when expand at macro stmts Example --- ```rust macro_rules! m { ($($t:tt)*) => { $($t)* } } fn quux(x: i32) { m!(l$0); } ``` **Differences** ```diff ... kw if let +kw impl +kw impl for +kw let +kw letm kw loop ... ``` --- crates/ide-completion/src/context/analysis.rs | 8 ++- crates/ide-completion/src/tests/expression.rs | 64 +++++++++++++++++-- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 7280fd1ad575..6f71aedebad6 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -2028,7 +2028,13 @@ fn is_in_block(node: &SyntaxNode) -> bool { return true; }; node.parent() - .map(|node| ast::ExprStmt::can_cast(node.kind()) || ast::StmtList::can_cast(node.kind())) + .map(|node| { + ast::ExprStmt::can_cast(node.kind()) + || ast::StmtList::can_cast(node.kind()) + // Because `is_in_block` is only called in the context of an expression, + // there is no need to consider expanding it into a type or pattern + || ast::MacroStmts::can_cast(node.kind()) + }) .unwrap_or(false) } diff --git a/crates/ide-completion/src/tests/expression.rs b/crates/ide-completion/src/tests/expression.rs index 0e558cf6a2b5..39748355c011 100644 --- a/crates/ide-completion/src/tests/expression.rs +++ b/crates/ide-completion/src/tests/expression.rs @@ -807,7 +807,7 @@ fn foo() { fn in_macro_expr_frag() { check( r#" -macro_rules! m { ($e:expr) => { $e } } +macro_rules! m { ($e:expr) => { let _ = $e; } } fn quux(x: i32) { m!($0); } @@ -835,7 +835,7 @@ fn quux(x: i32) { ); check( r" -macro_rules! m { ($e:expr) => { $e } } +macro_rules! m { ($e:expr) => { let _ = $e; } } fn quux(x: i32) { m!(x$0); } @@ -859,11 +859,12 @@ fn quux(x: i32) { kw unsafe kw while kw while let + ex x "#]], ); check( r#" -macro_rules! m { ($e:expr) => { $e } } +macro_rules! m { ($e:expr) => { let _ = $e; } } fn quux(x: i32) { let y = 92; m!(x$0 @@ -893,6 +894,56 @@ fn quux(x: i32) { ); } +#[test] +fn in_identity_macro() { + check( + r#" +macro_rules! m { ($($t:tt)*) => { $($t)* } } +fn quux(x: i32) { + m!(l$0); +} +"#, + expect![[r#" + fn quux(…) fn(i32) + lc x i32 + ma m!(…) macro_rules! m + bt u32 u32 + kw async + kw const + kw crate:: + kw enum + kw extern + kw false + kw fn + kw for + kw if + kw if let + kw impl + kw impl for + kw let + kw letm + kw loop + kw match + kw mod + kw return + kw self:: + kw static + kw struct + kw trait + kw true + kw type + kw union + kw unsafe + kw use + kw while + kw while let + sn macro_rules + sn pd + sn ppd + "#]], + ); +} + #[test] fn enum_qualified() { check_with_base_items( @@ -4094,20 +4145,23 @@ fn main() { ma bar macro_rules! bar ma foo macro_rules! foo bt u32 u32 - kw const kw crate:: kw false kw for kw if kw if let + kw let + kw letm kw loop kw match kw return kw self:: kw true - kw unsafe kw while kw while let + sn macro_rules + sn pd + sn ppd "#]], ); }