Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/generate_function.rs')
| -rw-r--r-- | crates/ide-assists/src/handlers/generate_function.rs | 103 |
1 files changed, 77 insertions, 26 deletions
diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs index bd66c02b41..fbf6241e43 100644 --- a/crates/ide-assists/src/handlers/generate_function.rs +++ b/crates/ide-assists/src/handlers/generate_function.rs @@ -4,7 +4,6 @@ use hir::{ }; use ide_db::{ FileId, FxHashMap, FxHashSet, RootDatabase, SnippetCap, - assists::ExprFillDefaultMode, defs::{Definition, NameRefClass}, famous_defs::FamousDefs, helpers::is_editable_crate, @@ -24,7 +23,7 @@ use syntax::{ use crate::{ AssistContext, AssistId, Assists, - utils::{convert_reference_type, find_struct_impl}, + utils::{convert_reference_type, expr_fill_default, find_struct_impl}, }; // Assist: generate_function @@ -147,7 +146,16 @@ 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 enclosing_impl = ctx.find_node_at_offset::<ast::Impl>(); + let cursor_impl = enclosing_impl.filter(|impl_| { + ctx.sema.to_def(impl_).map_or(false, |def| def.self_ty(ctx.sema.db).as_adt() == Some(adt)) + }); + + let (impl_, file) = if let Some(impl_) = cursor_impl { + (Some(impl_), ctx.vfs_file_id()) + } else { + get_adt_source(ctx, &adt, fn_name.text().as_str())? + }; let target = get_method_target(ctx, &impl_, &adt)?; let function_builder = FunctionBuilder::from_method_call( @@ -277,11 +285,7 @@ impl FunctionBuilder { target_module, &mut necessary_generic_params, ); - let placeholder_expr = match ctx.config.expr_fill_default { - ExprFillDefaultMode::Todo => make::ext::expr_todo(), - ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), - ExprFillDefaultMode::Default => make::ext::expr_todo(), - }; + let placeholder_expr = expr_fill_default(ctx.config); fn_body = make::block_expr(vec![], Some(placeholder_expr)); }; @@ -336,11 +340,7 @@ impl FunctionBuilder { let (generic_param_list, where_clause) = fn_generic_params(ctx, necessary_generic_params, &target)?; - let placeholder_expr = match ctx.config.expr_fill_default { - ExprFillDefaultMode::Todo => make::ext::expr_todo(), - ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), - ExprFillDefaultMode::Default => make::ext::expr_todo(), - }; + let placeholder_expr = expr_fill_default(ctx.config); let fn_body = make::block_expr(vec![], Some(placeholder_expr)); Some(Self { @@ -456,11 +456,7 @@ fn make_fn_body_as_new_function( let adt_info = adt_info.as_ref()?; let path_self = make::ext::ident_path("Self"); - let placeholder_expr = match ctx.config.expr_fill_default { - ExprFillDefaultMode::Todo => make::ext::expr_todo(), - ExprFillDefaultMode::Underscore => make::ext::expr_underscore(), - ExprFillDefaultMode::Default => make::ext::expr_todo(), - }; + let placeholder_expr = expr_fill_default(ctx.config); let tail_expr = if let Some(strukt) = adt_info.adt.as_struct() { match strukt.kind(ctx.db()) { StructKind::Record => { @@ -1147,14 +1143,7 @@ fn fn_arg_type( if ty.is_reference() || ty.is_mutable_reference() { let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate()); convert_reference_type(ty.strip_references(), ctx.db(), famous_defs) - .map(|conversion| { - conversion - .convert_type( - ctx.db(), - target_module.krate(ctx.db()).to_display_target(ctx.db()), - ) - .to_string() - }) + .map(|conversion| conversion.convert_type(ctx.db(), target_module).to_string()) .or_else(|| ty.display_source_code(ctx.db(), target_module.into(), true).ok()) } else { ty.display_source_code(ctx.db(), target_module.into(), true).ok() @@ -3191,4 +3180,66 @@ fn main() { "#, ); } + + #[test] + fn regression_21288() { + check_assist( + generate_function, + r#" +//- minicore: copy +fn foo() { + $0bar(&|x| true) +} + "#, + r#" +fn foo() { + bar(&|x| true) +} + +fn bar(arg: impl Fn(_) -> bool) { + ${0:todo!()} +} + "#, + ); + } + #[test] + fn generate_method_uses_current_impl_block() { + check_assist( + generate_function, + r" +struct Foo; + +impl Foo { + fn new() -> Self { + Foo + } +} + +impl Foo { + fn method1(&self) { + self.method2$0(42) + } +} +", + r" +struct Foo; + +impl Foo { + fn new() -> Self { + Foo + } +} + +impl Foo { + fn method1(&self) { + self.method2(42) + } + + fn method2(&self, arg: i32) { + ${0:todo!()} + } +} +", + ) + } } |