]> git.proxmox.com Git - rustc.git/blobdiff - src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / ide-assists / src / handlers / generate_function.rs
index e26c76da1891649c0a035706e5eb278aa325b99e..c229127e48ffca348a66a7d56a54b75e8cb34c0a 100644 (file)
@@ -1,4 +1,4 @@
-use hir::{HasSource, HirDisplay, Module, Semantics, TypeInfo};
+use hir::{Adt, HasSource, HirDisplay, Module, Semantics, TypeInfo};
 use ide_db::{
     base_db::FileId,
     defs::{Definition, NameRefClass},
@@ -145,7 +145,8 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
         return None;
     }
     let (impl_, file) = get_adt_source(ctx, &adt, fn_name.text().as_str())?;
-    let (target, insert_offset) = get_method_target(ctx, &target_module, &impl_)?;
+    let (target, insert_offset) = get_method_target(ctx, &impl_, &adt)?;
+
     let function_builder =
         FunctionBuilder::from_method_call(ctx, &call, &fn_name, target_module, target)?;
     let text_range = call.syntax().text_range();
@@ -174,10 +175,11 @@ fn add_func_to_accumulator(
     label: String,
 ) -> Option<()> {
     acc.add(AssistId("generate_function", AssistKind::Generate), label, text_range, |builder| {
-        let function_template = function_builder.render();
+        let indent = IndentLevel::from_node(function_builder.target.syntax());
+        let function_template = function_builder.render(adt_name.is_some());
         let mut func = function_template.to_string(ctx.config.snippet_cap);
         if let Some(name) = adt_name {
-            func = format!("\nimpl {} {{\n{}\n}}", name, func);
+            func = format!("\n{indent}impl {name} {{\n{func}\n{indent}}}");
         }
         builder.edit_file(file);
         match ctx.config.snippet_cap {
@@ -196,7 +198,7 @@ fn get_adt_source(
     let file = ctx.sema.parse(range.file_id);
     let adt_source =
         ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;
-    find_struct_impl(ctx, &adt_source, fn_name).map(|impl_| (impl_, range.file_id))
+    find_struct_impl(ctx, &adt_source, &[fn_name.to_string()]).map(|impl_| (impl_, range.file_id))
 }
 
 struct FunctionTemplate {
@@ -210,23 +212,26 @@ struct FunctionTemplate {
 
 impl FunctionTemplate {
     fn to_string(&self, cap: Option<SnippetCap>) -> String {
+        let Self { leading_ws, fn_def, ret_type, should_focus_return_type, trailing_ws, tail_expr } =
+            self;
+
         let f = match cap {
             Some(cap) => {
-                let cursor = if self.should_focus_return_type {
+                let cursor = if *should_focus_return_type {
                     // Focus the return type if there is one
-                    match self.ret_type {
-                        Some(ref ret_type) => ret_type.syntax(),
-                        None => self.tail_expr.syntax(),
+                    match ret_type {
+                        Some(ret_type) => ret_type.syntax(),
+                        None => tail_expr.syntax(),
                     }
                 } else {
-                    self.tail_expr.syntax()
+                    tail_expr.syntax()
                 };
-                render_snippet(cap, self.fn_def.syntax(), Cursor::Replace(cursor))
+                render_snippet(cap, fn_def.syntax(), Cursor::Replace(cursor))
             }
-            None => self.fn_def.to_string(),
+            None => fn_def.to_string(),
         };
 
-        format!("{}{}{}", self.leading_ws, f, self.trailing_ws)
+        format!("{leading_ws}{f}{trailing_ws}")
     }
 }
 
@@ -307,7 +312,7 @@ impl FunctionBuilder {
         })
     }
 
-    fn render(self) -> FunctionTemplate {
+    fn render(self, is_method: bool) -> FunctionTemplate {
         let placeholder_expr = make::ext::expr_todo();
         let fn_body = make::block_expr(vec![], Some(placeholder_expr));
         let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
@@ -325,16 +330,23 @@ impl FunctionBuilder {
 
         match self.target {
             GeneratedFunctionTarget::BehindItem(it) => {
-                let indent = IndentLevel::from_node(&it);
-                leading_ws = format!("\n\n{}", indent);
+                let mut indent = IndentLevel::from_node(&it);
+                if is_method {
+                    indent = indent + 1;
+                    leading_ws = format!("{indent}");
+                } else {
+                    leading_ws = format!("\n\n{indent}");
+                }
+
                 fn_def = fn_def.indent(indent);
                 trailing_ws = String::new();
             }
             GeneratedFunctionTarget::InEmptyItemList(it) => {
                 let indent = IndentLevel::from_node(&it);
-                leading_ws = format!("\n{}", indent + 1);
-                fn_def = fn_def.indent(indent + 1);
-                trailing_ws = format!("\n{}", indent);
+                let leading_indent = indent + 1;
+                leading_ws = format!("\n{leading_indent}");
+                fn_def = fn_def.indent(leading_indent);
+                trailing_ws = format!("\n{indent}");
             }
         };
 
@@ -411,14 +423,13 @@ fn get_fn_target(
 
 fn get_method_target(
     ctx: &AssistContext<'_>,
-    target_module: &Module,
     impl_: &Option<ast::Impl>,
+    adt: &Adt,
 ) -> Option<(GeneratedFunctionTarget, TextSize)> {
     let target = match impl_ {
         Some(impl_) => next_space_for_fn_in_impl(impl_)?,
         None => {
-            next_space_for_fn_in_module(ctx.sema.db, &target_module.definition_source(ctx.sema.db))?
-                .1
+            GeneratedFunctionTarget::BehindItem(adt.source(ctx.sema.db)?.syntax().value.clone())
         }
     };
     Some((target.clone(), get_insert_offset(&target)))
@@ -437,7 +448,7 @@ fn assoc_fn_target_info(
         return None;
     }
     let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
-    let (target, insert_offset) = get_method_target(ctx, &module, &impl_)?;
+    let (target, insert_offset) = get_method_target(ctx, &impl_, &adt)?;
     let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
     Some(TargetInfo::new(target_module, adt_name, target, file, insert_offset))
 }
@@ -1468,14 +1479,12 @@ fn foo() {S.bar$0();}
 ",
             r"
 struct S;
-fn foo() {S.bar();}
 impl S {
-
-
-fn bar(&self) ${0:-> _} {
-    todo!()
-}
+    fn bar(&self) ${0:-> _} {
+        todo!()
+    }
 }
+fn foo() {S.bar();}
 ",
         )
     }
@@ -1516,14 +1525,12 @@ fn foo() {s::S.bar$0();}
             r"
 mod s {
     pub struct S;
-impl S {
-
-
-    pub(crate) fn bar(&self) ${0:-> _} {
-        todo!()
+    impl S {
+        pub(crate) fn bar(&self) ${0:-> _} {
+            todo!()
+        }
     }
 }
-}
 fn foo() {s::S.bar();}
 ",
         )
@@ -1544,18 +1551,16 @@ mod s {
 ",
             r"
 struct S;
+impl S {
+    fn bar(&self) ${0:-> _} {
+        todo!()
+    }
+}
 mod s {
     fn foo() {
         super::S.bar();
     }
 }
-impl S {
-
-
-fn bar(&self) ${0:-> _} {
-    todo!()
-}
-}
 
 ",
         )
@@ -1571,14 +1576,12 @@ fn foo() {$0S.bar();}
 ",
             r"
 struct S;
-fn foo() {S.bar();}
 impl S {
-
-
-fn bar(&self) ${0:-> _} {
-    todo!()
-}
+    fn bar(&self) ${0:-> _} {
+        todo!()
+    }
 }
+fn foo() {S.bar();}
 ",
         )
     }
@@ -1593,14 +1596,12 @@ fn foo() {S::bar$0();}
 ",
             r"
 struct S;
-fn foo() {S::bar();}
 impl S {
-
-
-fn bar() ${0:-> _} {
-    todo!()
-}
+    fn bar() ${0:-> _} {
+        todo!()
+    }
 }
+fn foo() {S::bar();}
 ",
         )
     }
@@ -1641,14 +1642,12 @@ fn foo() {s::S::bar$0();}
             r"
 mod s {
     pub struct S;
-impl S {
-
-
-    pub(crate) fn bar() ${0:-> _} {
-        todo!()
+    impl S {
+        pub(crate) fn bar() ${0:-> _} {
+            todo!()
+        }
     }
 }
-}
 fn foo() {s::S::bar();}
 ",
         )
@@ -1664,14 +1663,12 @@ fn foo() {$0S::bar();}
 ",
             r"
 struct S;
-fn foo() {S::bar();}
 impl S {
-
-
-fn bar() ${0:-> _} {
-    todo!()
-}
+    fn bar() ${0:-> _} {
+        todo!()
+    }
 }
+fn foo() {S::bar();}
 ",
         )
     }
@@ -1841,15 +1838,13 @@ fn main() {
 ",
             r"
 enum Foo {}
-fn main() {
-    Foo::new();
-}
 impl Foo {
-
-
-fn new() ${0:-> _} {
-    todo!()
+    fn new() ${0:-> _} {
+        todo!()
+    }
 }
+fn main() {
+    Foo::new();
 }
 ",
         )