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.rs103
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!()}
+ }
+}
+",
+ )
+ }
}