From e2c233a42b204e7e7fa3d4fbabbb429a6a51fc91 Mon Sep 17 00:00:00 2001
From: mahdi-frms <mahdif1380@outlook.com>
Date: Sat, 21 Aug 2021 11:52:07 +0430
Subject: [PATCH 1/5] simplify

---
 .../src/handlers/generate_function.rs         | 24 +++++++++++++++----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index a0e682c4ce1..e7cec8ac5b3 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -1,4 +1,4 @@
-use hir::{HasSource, HirDisplay, Module, TypeInfo};
+use hir::{HasSource, HirDisplay, InFile, Module, TypeInfo};
 use ide_db::{base_db::FileId, helpers::SnippetCap};
 use rustc_hash::{FxHashMap, FxHashSet};
 use stdx::to_lower_snake_case;
@@ -109,7 +109,7 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let fn_name = call.name_ref()?;
     let adt = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references().as_adt()?;
 
-    let current_module = ctx.sema.scope(call.syntax()).module()?;
+    let current_module = current_module(call.syntax(), ctx)?;
     let target_module = adt.module(ctx.sema.db);
 
     if current_module.krate() != target_module.krate() {
@@ -152,6 +152,22 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     )
 }
 
+fn get_impl(
+    adt: InFile<&SyntaxNode>,
+    fn_name: &ast::NameRef,
+    ctx: &AssistContext,
+) -> Option<(Option<ast::Impl>, FileId)> {
+    let file = adt.file_id.original_file(ctx.sema.db);
+    let adt = adt.value;
+    let adt = ast::Adt::cast(adt.clone())?;
+    let r = find_struct_impl(ctx, &adt, fn_name.text().as_str())?;
+    Some((r, file))
+}
+
+fn current_module(current_node: &SyntaxNode, ctx: &AssistContext) -> Option<Module> {
+    ctx.sema.scope(current_node).module()
+}
+
 struct FunctionTemplate {
     insert_offset: TextSize,
     leading_ws: String,
@@ -218,7 +234,7 @@ impl FunctionBuilder {
             None => next_space_for_fn_after_call_site(FuncExpr::Func(call.clone()))?,
         };
         let needs_pub = target_module.is_some();
-        let target_module = target_module.or_else(|| ctx.sema.scope(target.syntax()).module())?;
+        let target_module = target_module.or_else(|| current_module(target.syntax(), ctx))?;
         let fn_name = fn_name(path)?;
         let (type_params, params) = fn_args(ctx, target_module, FuncExpr::Func(call.clone()))?;
 
@@ -250,8 +266,6 @@ impl FunctionBuilder {
         target_module: Module,
         current_module: Module,
     ) -> Option<Self> {
-        // let mut file = ctx.frange.file_id;
-        // let target_module = ctx.sema.scope(call.syntax()).module()?;
         let target = match impl_ {
             Some(impl_) => next_space_for_fn_in_impl(&impl_)?,
             None => {

From 87439b1d6a1f182a8bdff025b3eb89b2f6c7fe4b Mon Sep 17 00:00:00 2001
From: mahdi-frms <mahdif1380@outlook.com>
Date: Sat, 21 Aug 2021 13:29:15 +0430
Subject: [PATCH 2/5] func gen: seperate generation form position(1)

---
 .../src/handlers/generate_function.rs         | 82 ++++++++-----------
 1 file changed, 33 insertions(+), 49 deletions(-)

diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index e7cec8ac5b3..720b2390989 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -1,4 +1,4 @@
-use hir::{HasSource, HirDisplay, InFile, Module, TypeInfo};
+use hir::{HasSource, HirDisplay, Module, TypeInfo};
 use ide_db::{base_db::FileId, helpers::SnippetCap};
 use rustc_hash::{FxHashMap, FxHashSet};
 use stdx::to_lower_snake_case;
@@ -8,7 +8,7 @@ use syntax::{
         edit::{AstNodeEdit, IndentLevel},
         make, ArgListOwner, AstNode, ModuleItemOwner,
     },
-    SyntaxKind, SyntaxNode, TextSize,
+    SyntaxKind, SyntaxNode, TextRange, TextSize,
 };
 
 use crate::{
@@ -87,21 +87,7 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
 
     let function_builder = FunctionBuilder::from_call(ctx, &call, &path, target_module)?;
     let target = call.syntax().text_range();
-
-    acc.add(
-        AssistId("generate_function", AssistKind::Generate),
-        format!("Generate `{}` function", function_builder.fn_name),
-        target,
-        |builder| {
-            let function_template = function_builder.render();
-            builder.edit_file(function_template.file);
-            let new_fn = function_template.to_string(ctx.config.snippet_cap);
-            match ctx.config.snippet_cap {
-                Some(cap) => builder.insert_snippet(cap, function_template.insert_offset, new_fn),
-                None => builder.insert(function_template.insert_offset, new_fn),
-            }
-        },
-    )
+    add_func_to_accumulator(acc, ctx, target, function_builder, None)
 }
 
 fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
@@ -132,50 +118,46 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
         current_module,
     )?;
     let target = call.syntax().text_range();
+    let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
+    add_func_to_accumulator(acc, ctx, target, function_builder, adt_name)
+}
 
+fn add_func_to_accumulator(
+    acc: &mut Assists,
+    ctx: &AssistContext,
+    target: TextRange,
+    function_builder: FunctionBuilder,
+    adt_name: Option<hir::Name>,
+) -> Option<()> {
     acc.add(
         AssistId("generate_function", AssistKind::Generate),
         format!("Generate `{}` method", function_builder.fn_name),
         target,
         |builder| {
-            let function_template = function_builder.render();
-            builder.edit_file(function_template.file);
-            let mut new_fn = function_template.to_string(ctx.config.snippet_cap);
-            if impl_.is_none() {
-                new_fn = format!("\nimpl {} {{\n{}\n}}", adt.name(ctx.sema.db), new_fn,);
+            let (function_template, insert_offset, file) = function_builder.render();
+            let mut func = function_template.to_string(ctx.config.snippet_cap);
+            if let Some(name) = adt_name {
+                func = format!("\nimpl {} {{\n{}\n}}", name, func);
             }
+            builder.edit_file(file);
             match ctx.config.snippet_cap {
-                Some(cap) => builder.insert_snippet(cap, function_template.insert_offset, new_fn),
-                None => builder.insert(function_template.insert_offset, new_fn),
+                Some(cap) => builder.insert_snippet(cap, insert_offset, func),
+                None => builder.insert(insert_offset, func),
             }
         },
     )
 }
 
-fn get_impl(
-    adt: InFile<&SyntaxNode>,
-    fn_name: &ast::NameRef,
-    ctx: &AssistContext,
-) -> Option<(Option<ast::Impl>, FileId)> {
-    let file = adt.file_id.original_file(ctx.sema.db);
-    let adt = adt.value;
-    let adt = ast::Adt::cast(adt.clone())?;
-    let r = find_struct_impl(ctx, &adt, fn_name.text().as_str())?;
-    Some((r, file))
-}
-
 fn current_module(current_node: &SyntaxNode, ctx: &AssistContext) -> Option<Module> {
     ctx.sema.scope(current_node).module()
 }
 
 struct FunctionTemplate {
-    insert_offset: TextSize,
     leading_ws: String,
     fn_def: ast::Fn,
     ret_type: Option<ast::RetType>,
     should_focus_return_type: bool,
     trailing_ws: String,
-    file: FileId,
     tail_expr: ast::Expr,
 }
 
@@ -300,7 +282,7 @@ impl FunctionBuilder {
         })
     }
 
-    fn render(self) -> FunctionTemplate {
+    fn render(self) -> (FunctionTemplate, TextSize, FileId) {
         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 };
@@ -333,17 +315,19 @@ impl FunctionBuilder {
             }
         };
 
-        FunctionTemplate {
+        (
+            FunctionTemplate {
+                leading_ws,
+                ret_type: fn_def.ret_type(),
+                // PANIC: we guarantee we always create a function body with a tail expr
+                tail_expr: fn_def.body().unwrap().tail_expr().unwrap(),
+                should_focus_return_type: self.should_focus_return_type,
+                fn_def,
+                trailing_ws,
+            },
             insert_offset,
-            leading_ws,
-            ret_type: fn_def.ret_type(),
-            // PANIC: we guarantee we always create a function body with a tail expr
-            tail_expr: fn_def.body().unwrap().tail_expr().unwrap(),
-            should_focus_return_type: self.should_focus_return_type,
-            fn_def,
-            trailing_ws,
-            file: self.file,
-        }
+            self.file,
+        )
     }
 }
 

From 1ac9400100d276dd169e56ce6df1ebbd8a75f961 Mon Sep 17 00:00:00 2001
From: mahdi-frms <mahdif1380@outlook.com>
Date: Sat, 21 Aug 2021 17:31:37 +0430
Subject: [PATCH 3/5] func gen: seperate generation form position(2)

---
 .../src/handlers/generate_function.rs         | 107 +++++++++++-------
 1 file changed, 63 insertions(+), 44 deletions(-)

diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index 720b2390989..8e446549ba2 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -85,9 +85,10 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
         None => None,
     };
 
-    let function_builder = FunctionBuilder::from_call(ctx, &call, &path, target_module)?;
+    let (function_builder, inserting_offset, file) =
+        FunctionBuilder::from_call(ctx, &call, &path, target_module)?;
     let target = call.syntax().text_range();
-    add_func_to_accumulator(acc, ctx, target, function_builder, None)
+    add_func_to_accumulator(acc, ctx, target, function_builder, inserting_offset, file, None)
 }
 
 fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
@@ -108,7 +109,7 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
         ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;
     let impl_ = find_struct_impl(ctx, &adt_source, fn_name.text().as_str())?;
 
-    let function_builder = FunctionBuilder::from_method_call(
+    let (function_builder, inserting_offset, file) = FunctionBuilder::from_method_call(
         ctx,
         &call,
         &fn_name,
@@ -119,7 +120,7 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     )?;
     let target = call.syntax().text_range();
     let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
-    add_func_to_accumulator(acc, ctx, target, function_builder, adt_name)
+    add_func_to_accumulator(acc, ctx, target, function_builder, inserting_offset, file, adt_name)
 }
 
 fn add_func_to_accumulator(
@@ -127,6 +128,8 @@ fn add_func_to_accumulator(
     ctx: &AssistContext,
     target: TextRange,
     function_builder: FunctionBuilder,
+    insert_offset: TextSize,
+    file: FileId,
     adt_name: Option<hir::Name>,
 ) -> Option<()> {
     acc.add(
@@ -134,7 +137,7 @@ fn add_func_to_accumulator(
         format!("Generate `{}` method", function_builder.fn_name),
         target,
         |builder| {
-            let (function_template, insert_offset, file) = function_builder.render();
+            let function_template = function_builder.render();
             let mut func = function_template.to_string(ctx.config.snippet_cap);
             if let Some(name) = adt_name {
                 func = format!("\nimpl {} {{\n{}\n}}", name, func);
@@ -204,7 +207,7 @@ impl FunctionBuilder {
         call: &ast::CallExpr,
         path: &ast::Path,
         target_module: Option<hir::Module>,
-    ) -> Option<Self> {
+    ) -> Option<(Self, TextSize, FileId)> {
         let mut file = ctx.frange.file_id;
         let target = match &target_module {
             Some(target_module) => {
@@ -226,17 +229,28 @@ impl FunctionBuilder {
         let (ret_type, should_focus_return_type) =
             make_return_type(ctx, &ast::Expr::CallExpr(call.clone()), target_module);
 
-        Some(Self {
-            target,
-            fn_name,
-            type_params,
-            params,
-            ret_type,
-            should_focus_return_type,
+        let insert_offset = match &target {
+            GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
+            GeneratedFunctionTarget::InEmptyItemList(it) => {
+                it.text_range().start() + TextSize::of('{')
+            }
+        };
+
+        Some((
+            Self {
+                target,
+                fn_name,
+                type_params,
+                params,
+                ret_type,
+                should_focus_return_type,
+                file,
+                needs_pub,
+                is_async,
+            },
+            insert_offset,
             file,
-            needs_pub,
-            is_async,
-        })
+        ))
     }
 
     fn from_method_call(
@@ -247,7 +261,7 @@ impl FunctionBuilder {
         file: FileId,
         target_module: Module,
         current_module: Module,
-    ) -> Option<Self> {
+    ) -> Option<(Self, TextSize, FileId)> {
         let target = match impl_ {
             Some(impl_) => next_space_for_fn_in_impl(&impl_)?,
             None => {
@@ -269,20 +283,31 @@ impl FunctionBuilder {
         let (ret_type, should_focus_return_type) =
             make_return_type(ctx, &ast::Expr::MethodCallExpr(call.clone()), target_module);
 
-        Some(Self {
-            target,
-            fn_name,
-            type_params,
-            params,
-            ret_type,
-            should_focus_return_type,
+        let insert_offset = match &target {
+            GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
+            GeneratedFunctionTarget::InEmptyItemList(it) => {
+                it.text_range().start() + TextSize::of('{')
+            }
+        };
+
+        Some((
+            Self {
+                target,
+                fn_name,
+                type_params,
+                params,
+                ret_type,
+                should_focus_return_type,
+                file,
+                needs_pub,
+                is_async,
+            },
+            insert_offset,
             file,
-            needs_pub,
-            is_async,
-        })
+        ))
     }
 
-    fn render(self) -> (FunctionTemplate, TextSize, FileId) {
+    fn render(self) -> 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 };
@@ -298,36 +323,30 @@ impl FunctionBuilder {
         let leading_ws;
         let trailing_ws;
 
-        let insert_offset = match self.target {
+        match self.target {
             GeneratedFunctionTarget::BehindItem(it) => {
                 let indent = IndentLevel::from_node(&it);
                 leading_ws = format!("\n\n{}", indent);
                 fn_def = fn_def.indent(indent);
                 trailing_ws = String::new();
-                it.text_range().end()
             }
             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);
-                it.text_range().start() + TextSize::of('{')
             }
         };
 
-        (
-            FunctionTemplate {
-                leading_ws,
-                ret_type: fn_def.ret_type(),
-                // PANIC: we guarantee we always create a function body with a tail expr
-                tail_expr: fn_def.body().unwrap().tail_expr().unwrap(),
-                should_focus_return_type: self.should_focus_return_type,
-                fn_def,
-                trailing_ws,
-            },
-            insert_offset,
-            self.file,
-        )
+        FunctionTemplate {
+            leading_ws,
+            ret_type: fn_def.ret_type(),
+            // PANIC: we guarantee we always create a function body with a tail expr
+            tail_expr: fn_def.body().unwrap().tail_expr().unwrap(),
+            should_focus_return_type: self.should_focus_return_type,
+            fn_def,
+            trailing_ws,
+        }
     }
 }
 

From 50923ad741e3734e06a0d48845b334ba5b8565cb Mon Sep 17 00:00:00 2001
From: mahdi-frms <mahdif1380@outlook.com>
Date: Sat, 21 Aug 2021 18:58:29 +0430
Subject: [PATCH 4/5] func gen: seperate generation form position(3)

---
 .../src/handlers/generate_function.rs         | 175 +++++++++---------
 1 file changed, 86 insertions(+), 89 deletions(-)

diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index 8e446549ba2..384d0c0ba9e 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -6,7 +6,7 @@ use syntax::{
     ast::{
         self,
         edit::{AstNodeEdit, IndentLevel},
-        make, ArgListOwner, AstNode, ModuleItemOwner,
+        make, ArgListOwner, AstNode, CallExpr, ModuleItemOwner,
     },
     SyntaxKind, SyntaxNode, TextRange, TextSize,
 };
@@ -85,10 +85,10 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
         None => None,
     };
 
-    let (function_builder, inserting_offset, file) =
-        FunctionBuilder::from_call(ctx, &call, &path, target_module)?;
+    let (target, file, insert_offset) = get_fn_target(ctx, &target_module, call.clone())?;
+    let function_builder = FunctionBuilder::from_call(ctx, &call, &path, target_module, target)?;
     let target = call.syntax().text_range();
-    add_func_to_accumulator(acc, ctx, target, function_builder, inserting_offset, file, None)
+    add_func_to_accumulator(acc, ctx, target, function_builder, insert_offset, file, None)
 }
 
 fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
@@ -109,24 +109,26 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
         ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;
     let impl_ = find_struct_impl(ctx, &adt_source, fn_name.text().as_str())?;
 
-    let (function_builder, inserting_offset, file) = FunctionBuilder::from_method_call(
-        ctx,
-        &call,
-        &fn_name,
-        &impl_,
-        range.file_id,
-        target_module,
-        current_module,
-    )?;
-    let target = call.syntax().text_range();
+    let (target, insert_offset) = get_method_target(ctx, &target_module, &impl_)?;
+    let function_builder =
+        FunctionBuilder::from_method_call(ctx, &call, &fn_name, target_module, target)?;
+    let text_range = call.syntax().text_range();
     let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
-    add_func_to_accumulator(acc, ctx, target, function_builder, inserting_offset, file, adt_name)
+    add_func_to_accumulator(
+        acc,
+        ctx,
+        text_range,
+        function_builder,
+        insert_offset,
+        range.file_id,
+        adt_name,
+    )
 }
 
 fn add_func_to_accumulator(
     acc: &mut Assists,
     ctx: &AssistContext,
-    target: TextRange,
+    text_range: TextRange,
     function_builder: FunctionBuilder,
     insert_offset: TextSize,
     file: FileId,
@@ -135,7 +137,7 @@ fn add_func_to_accumulator(
     acc.add(
         AssistId("generate_function", AssistKind::Generate),
         format!("Generate `{}` method", function_builder.fn_name),
-        target,
+        text_range,
         |builder| {
             let function_template = function_builder.render();
             let mut func = function_template.to_string(ctx.config.snippet_cap);
@@ -194,7 +196,6 @@ struct FunctionBuilder {
     params: ast::ParamList,
     ret_type: Option<ast::RetType>,
     should_focus_return_type: bool,
-    file: FileId,
     needs_pub: bool,
     is_async: bool,
 }
@@ -207,17 +208,8 @@ impl FunctionBuilder {
         call: &ast::CallExpr,
         path: &ast::Path,
         target_module: Option<hir::Module>,
-    ) -> Option<(Self, TextSize, FileId)> {
-        let mut file = ctx.frange.file_id;
-        let target = match &target_module {
-            Some(target_module) => {
-                let module_source = target_module.definition_source(ctx.db());
-                let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, &module_source)?;
-                file = in_file;
-                target
-            }
-            None => next_space_for_fn_after_call_site(FuncExpr::Func(call.clone()))?,
-        };
+        target: GeneratedFunctionTarget,
+    ) -> Option<Self> {
         let needs_pub = target_module.is_some();
         let target_module = target_module.or_else(|| current_module(target.syntax(), ctx))?;
         let fn_name = fn_name(path)?;
@@ -229,51 +221,27 @@ impl FunctionBuilder {
         let (ret_type, should_focus_return_type) =
             make_return_type(ctx, &ast::Expr::CallExpr(call.clone()), target_module);
 
-        let insert_offset = match &target {
-            GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
-            GeneratedFunctionTarget::InEmptyItemList(it) => {
-                it.text_range().start() + TextSize::of('{')
-            }
-        };
-
-        Some((
-            Self {
-                target,
-                fn_name,
-                type_params,
-                params,
-                ret_type,
-                should_focus_return_type,
-                file,
-                needs_pub,
-                is_async,
-            },
-            insert_offset,
-            file,
-        ))
+        Some(Self {
+            target,
+            fn_name,
+            type_params,
+            params,
+            ret_type,
+            should_focus_return_type,
+            needs_pub,
+            is_async,
+        })
     }
 
     fn from_method_call(
         ctx: &AssistContext,
         call: &ast::MethodCallExpr,
         name: &ast::NameRef,
-        impl_: &Option<ast::Impl>,
-        file: FileId,
         target_module: Module,
-        current_module: Module,
-    ) -> Option<(Self, TextSize, FileId)> {
-        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
-            }
-        };
-        let needs_pub = !module_is_descendant(&current_module, &target_module, ctx);
-
+        target: GeneratedFunctionTarget,
+    ) -> Option<Self> {
+        let needs_pub =
+            !module_is_descendant(&current_module(call.syntax(), ctx)?, &target_module, ctx);
         let fn_name = make::name(&name.text());
         let (type_params, params) = fn_args(ctx, target_module, FuncExpr::Method(call.clone()))?;
 
@@ -283,28 +251,16 @@ impl FunctionBuilder {
         let (ret_type, should_focus_return_type) =
             make_return_type(ctx, &ast::Expr::MethodCallExpr(call.clone()), target_module);
 
-        let insert_offset = match &target {
-            GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
-            GeneratedFunctionTarget::InEmptyItemList(it) => {
-                it.text_range().start() + TextSize::of('{')
-            }
-        };
-
-        Some((
-            Self {
-                target,
-                fn_name,
-                type_params,
-                params,
-                ret_type,
-                should_focus_return_type,
-                file,
-                needs_pub,
-                is_async,
-            },
-            insert_offset,
-            file,
-        ))
+        Some(Self {
+            target,
+            fn_name,
+            type_params,
+            params,
+            ret_type,
+            should_focus_return_type,
+            needs_pub,
+            is_async,
+        })
     }
 
     fn render(self) -> FunctionTemplate {
@@ -382,6 +338,47 @@ fn make_return_type(
     (ret_type, should_focus_return_type)
 }
 
+fn get_fn_target(
+    ctx: &AssistContext,
+    target_module: &Option<Module>,
+    call: CallExpr,
+) -> Option<(GeneratedFunctionTarget, FileId, TextSize)> {
+    let mut file = ctx.frange.file_id;
+    let target = match target_module {
+        Some(target_module) => {
+            let module_source = target_module.definition_source(ctx.db());
+            let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, &module_source)?;
+            file = in_file;
+            target
+        }
+        None => next_space_for_fn_after_call_site(FuncExpr::Func(call.clone()))?,
+    };
+    Some((target.clone(), file, get_insert_offset(&target)))
+}
+
+fn get_method_target(
+    ctx: &AssistContext,
+    target_module: &Module,
+    impl_: &Option<ast::Impl>,
+) -> 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
+        }
+    };
+    Some((target.clone(), get_insert_offset(&target)))
+}
+
+fn get_insert_offset(target: &GeneratedFunctionTarget) -> TextSize {
+    match &target {
+        GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
+        GeneratedFunctionTarget::InEmptyItemList(it) => it.text_range().start() + TextSize::of('{'),
+    }
+}
+
+#[derive(Clone)]
 enum GeneratedFunctionTarget {
     BehindItem(SyntaxNode),
     InEmptyItemList(SyntaxNode),

From c1edbfbacce28f26e1bb5a93acc6fe5385da28c7 Mon Sep 17 00:00:00 2001
From: mahdi-frms <mahdif1380@outlook.com>
Date: Sun, 22 Aug 2021 12:31:16 +0430
Subject: [PATCH 5/5] better assist label

---
 .../src/handlers/generate_function.rs         | 35 +++++++++----------
 1 file changed, 17 insertions(+), 18 deletions(-)

diff --git a/crates/ide_assists/src/handlers/generate_function.rs b/crates/ide_assists/src/handlers/generate_function.rs
index 384d0c0ba9e..6e5d78b1ea5 100644
--- a/crates/ide_assists/src/handlers/generate_function.rs
+++ b/crates/ide_assists/src/handlers/generate_function.rs
@@ -88,7 +88,8 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let (target, file, insert_offset) = get_fn_target(ctx, &target_module, call.clone())?;
     let function_builder = FunctionBuilder::from_call(ctx, &call, &path, target_module, target)?;
     let target = call.syntax().text_range();
-    add_func_to_accumulator(acc, ctx, target, function_builder, insert_offset, file, None)
+    let label = format!("Generate {} function", function_builder.fn_name.clone());
+    add_func_to_accumulator(acc, ctx, target, function_builder, insert_offset, file, None, label)
 }
 
 fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
@@ -114,6 +115,7 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
         FunctionBuilder::from_method_call(ctx, &call, &fn_name, target_module, target)?;
     let text_range = call.syntax().text_range();
     let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
+    let label = format!("Generate {} method", function_builder.fn_name.clone());
     add_func_to_accumulator(
         acc,
         ctx,
@@ -122,6 +124,7 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
         insert_offset,
         range.file_id,
         adt_name,
+        label,
     )
 }
 
@@ -133,24 +136,20 @@ fn add_func_to_accumulator(
     insert_offset: TextSize,
     file: FileId,
     adt_name: Option<hir::Name>,
+    label: String,
 ) -> Option<()> {
-    acc.add(
-        AssistId("generate_function", AssistKind::Generate),
-        format!("Generate `{}` method", function_builder.fn_name),
-        text_range,
-        |builder| {
-            let function_template = function_builder.render();
-            let mut func = function_template.to_string(ctx.config.snippet_cap);
-            if let Some(name) = adt_name {
-                func = format!("\nimpl {} {{\n{}\n}}", name, func);
-            }
-            builder.edit_file(file);
-            match ctx.config.snippet_cap {
-                Some(cap) => builder.insert_snippet(cap, insert_offset, func),
-                None => builder.insert(insert_offset, func),
-            }
-        },
-    )
+    acc.add(AssistId("generate_function", AssistKind::Generate), label, text_range, |builder| {
+        let function_template = function_builder.render();
+        let mut func = function_template.to_string(ctx.config.snippet_cap);
+        if let Some(name) = adt_name {
+            func = format!("\nimpl {} {{\n{}\n}}", name, func);
+        }
+        builder.edit_file(file);
+        match ctx.config.snippet_cap {
+            Some(cap) => builder.insert_snippet(cap, insert_offset, func),
+            None => builder.insert(insert_offset, func),
+        }
+    })
 }
 
 fn current_module(current_node: &SyntaxNode, ctx: &AssistContext) -> Option<Module> {