Skip to content

Commit 39d17ef

Browse files
committed
feat: Generate static method using Self::assoc() syntax
This change improves the `generate_function` assist to support generating static methods/associated functions using the `Self::assoc()` syntax. Previously, one could generate a static method, but only when specifying the type name directly (like `Foo::assoc()`). After this change, `Self` is supported as well as the type name. Fixes rust-lang#13012
1 parent baa2ccc commit 39d17ef

File tree

1 file changed

+53
-11
lines changed

1 file changed

+53
-11
lines changed

crates/ide-assists/src/handlers/generate_function.rs

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
6161
}
6262

6363
let fn_name = &*name_ref.text();
64-
let target_module;
64+
let mut target_module = None;
6565
let mut adt_name = None;
6666

6767
let (target, file, insert_offset) = match path.qualifier() {
@@ -78,16 +78,11 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
7878
}
7979
}
8080

81-
let current_module = ctx.sema.scope(call.syntax())?.module();
82-
let module = adt.module(ctx.sema.db);
83-
target_module = if current_module == module { None } else { Some(module) };
84-
if current_module.krate() != module.krate() {
85-
return None;
86-
}
87-
let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
88-
let (target, insert_offset) = get_method_target(ctx, &module, &impl_)?;
89-
adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
90-
(target, file, insert_offset)
81+
static_method_target(ctx, &call, adt, &mut target_module, fn_name, &mut adt_name)?
82+
}
83+
Some(hir::PathResolution::SelfType(impl_)) => {
84+
let adt = impl_.self_ty(ctx.db()).as_adt()?;
85+
static_method_target(ctx, &call, adt, &mut target_module, fn_name, &mut adt_name)?
9186
}
9287
_ => {
9388
return None;
@@ -399,6 +394,26 @@ fn get_method_target(
399394
Some((target.clone(), get_insert_offset(&target)))
400395
}
401396

397+
fn static_method_target(
398+
ctx: &AssistContext<'_>,
399+
call: &CallExpr,
400+
adt: hir::Adt,
401+
target_module: &mut Option<Module>,
402+
fn_name: &str,
403+
adt_name: &mut Option<hir::Name>,
404+
) -> Option<(GeneratedFunctionTarget, FileId, TextSize)> {
405+
let current_module = ctx.sema.scope(call.syntax())?.module();
406+
let module = adt.module(ctx.sema.db);
407+
*target_module = if current_module == module { None } else { Some(module) };
408+
if current_module.krate() != module.krate() {
409+
return None;
410+
}
411+
let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
412+
let (target, insert_offset) = get_method_target(ctx, &module, &impl_)?;
413+
*adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
414+
Some((target, file, insert_offset))
415+
}
416+
402417
fn get_insert_offset(target: &GeneratedFunctionTarget) -> TextSize {
403418
match &target {
404419
GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
@@ -1633,6 +1648,33 @@ fn bar() ${0:-> _} {
16331648
)
16341649
}
16351650

1651+
#[test]
1652+
fn create_static_method_within_an_impl_with_self_syntax() {
1653+
check_assist(
1654+
generate_function,
1655+
r"
1656+
struct S;
1657+
impl S {
1658+
fn foo(&self) {
1659+
Self::bar$0();
1660+
}
1661+
}
1662+
",
1663+
r"
1664+
struct S;
1665+
impl S {
1666+
fn foo(&self) {
1667+
Self::bar();
1668+
}
1669+
1670+
fn bar() ${0:-> _} {
1671+
todo!()
1672+
}
1673+
}
1674+
",
1675+
)
1676+
}
1677+
16361678
#[test]
16371679
fn no_panic_on_invalid_global_path() {
16381680
check_assist(

0 commit comments

Comments
 (0)