diff options
| author | bors <bors@rust-lang.org> | 2022-07-26 16:14:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-07-26 16:14:51 +0000 |
| commit | c2eebd7a50faa2578376a80ceba91bdc75d748e2 (patch) | |
| tree | cf9ee9f5302ec3cbbd455143aafb0dda30d59a8b | |
| parent | 7a30f62ecf5642174dbc52de122fc0b21e1c15e1 (diff) | |
| parent | add33b65dda4b59b46b5192f3a88a83b771af844 (diff) | |
| download | rust-c2eebd7a50faa2578376a80ceba91bdc75d748e2.tar.gz rust-c2eebd7a50faa2578376a80ceba91bdc75d748e2.zip | |
Auto merge of #12877 - zachs18:inline-def-in-macro, r=zachs18
fix: Insert spaces when inlining a function defined in a macro.
(partially) fixes #12860.
This PR (only) addresses the whitespace issue when inlining functions defined in macros.
Additionally, the indentation/spacing is not ideal, but works, e.g.
```rs
macro_rules! define_function {
() => { fn test_function_macro() {
if let Some(3) = 3i32.checked_add(0) {
println!("3 + 0 == 3");
}
} };
}
define_function!();
fn main() {
test_function_macro();
}
// previously became
// ...
fn main() {
ifletSome(3)=3i32.checked_add(0){println!("3 + 0 == 3");};
}
// now becomes
// ...
fn main() {
if let Some(3) = 3i32.checked_add(0){
println!("3 + 0 == 3");
};
}
```
The `self` -> `this` problem[^this] is (probably?) a separate problem that I am also looking into.
[^this]: As mentioned in [my comment on the above issue](https://github.com/rust-lang/rust-analyzer/issues/12860#issuecomment-1193231766), inlining a method defined in a macro does not properly replace `self` with the new local `this`.
| -rw-r--r-- | crates/ide-assists/src/handlers/inline_call.rs | 48 |
1 files changed, 46 insertions, 2 deletions
diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs index 658a1aadf53..80d3b925593 100644 --- a/crates/ide-assists/src/handlers/inline_call.rs +++ b/crates/ide-assists/src/handlers/inline_call.rs @@ -7,7 +7,7 @@ use ide_db::{ imports::insert_use::remove_path_if_in_use_stmt, path_transform::PathTransform, search::{FileReference, SearchScope}, - syntax_helpers::node_ext::expr_as_name_ref, + syntax_helpers::{insert_whitespace_into_node::insert_ws_into, node_ext::expr_as_name_ref}, RootDatabase, }; use itertools::{izip, Itertools}; @@ -301,7 +301,16 @@ fn inline( params: &[(ast::Pat, Option<ast::Type>, hir::Param)], CallInfo { node, arguments, generic_arg_list }: &CallInfo, ) -> ast::Expr { - let body = fn_body.clone_for_update(); + let body = if sema.hir_file_for(fn_body.syntax()).is_macro() { + cov_mark::hit!(inline_call_defined_in_macro); + if let Some(body) = ast::BlockExpr::cast(insert_ws_into(fn_body.syntax().clone())) { + body + } else { + fn_body.clone_for_update() + } + } else { + fn_body.clone_for_update() + }; let usages_for_locals = |local| { Definition::Local(local) .usages(sema) @@ -1147,4 +1156,39 @@ fn bar() -> u32 { "#, ) } + + #[test] + fn inline_call_defined_in_macro() { + cov_mark::check!(inline_call_defined_in_macro); + check_assist( + inline_call, + r#" +macro_rules! define_foo { + () => { fn foo() -> u32 { + let x = 0; + x + } }; +} +define_foo!(); +fn bar() -> u32 { + foo$0() +} +"#, + r#" +macro_rules! define_foo { + () => { fn foo() -> u32 { + let x = 0; + x + } }; +} +define_foo!(); +fn bar() -> u32 { + { + let x = 0; + x + } +} +"#, + ) + } } |
