1 use hir::{db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, ItemInNs, ModuleDef};
2 use ide_db::assists::{AssistId, AssistKind};
3 use syntax::{ast, AstNode};
6 assist_context::{AssistContext, Assists},
7 handlers::qualify_path::QualifyCandidate,
10 // Assist: qualify_method_call
12 // Replaces the method call with a qualified function call.
35 pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
36 let name: ast::NameRef = ctx.find_node_at_offset()?;
37 let call = name.syntax().parent().and_then(ast::MethodCallExpr::cast)?;
39 let ident = name.ident_token()?;
41 let range = call.syntax().text_range();
42 let resolved_call = ctx.sema.resolve_method_call(&call)?;
44 let current_module = ctx.sema.scope(call.syntax())?.module();
45 let target_module_def = ModuleDef::from(resolved_call);
46 let item_in_ns = ItemInNs::from(target_module_def);
47 let receiver_path = current_module.find_use_path(
49 item_for_path_search(ctx.sema.db, item_in_ns)?,
50 ctx.config.prefer_no_std,
53 let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call);
56 AssistId("qualify_method_call", AssistKind::RefactorInline),
57 format!("Qualify `{}` method call", ident.text()),
60 qualify_candidate.qualify(
61 |replace_with: String| builder.replace(range, replace_with),
70 fn item_for_path_search(db: &dyn HirDatabase, item: ItemInNs) -> Option<ItemInNs> {
72 ItemInNs::Types(_) | ItemInNs::Values(_) => match item_as_assoc(db, item) {
73 Some(assoc_item) => match assoc_item.container(db) {
74 AssocItemContainer::Trait(trait_) => ItemInNs::from(ModuleDef::from(trait_)),
75 AssocItemContainer::Impl(impl_) => match impl_.trait_(db) {
76 None => ItemInNs::from(ModuleDef::from(impl_.self_ty(db).as_adt()?)),
77 Some(trait_) => ItemInNs::from(ModuleDef::from(trait_)),
82 ItemInNs::Macros(_) => item,
86 fn item_as_assoc(db: &dyn HirDatabase, item: ItemInNs) -> Option<AssocItem> {
87 item.as_module_def().and_then(|module_def| module_def.as_assoc_item(db))
93 use crate::tests::{check_assist, check_assist_not_applicable};
125 fn struct_method_multi_params() {
131 fn foo(&self, p1: i32, p2: u32) {}
142 fn foo(&self, p1: i32, p2: u32) {}
147 Foo::foo(&foo, 9, 9u)
154 fn struct_method_consume() {
160 fn foo(self, p1: i32, p2: u32) {}
171 fn foo(self, p1: i32, p2: u32) {}
183 fn struct_method_exclusive() {
189 fn foo(&mut self, p1: i32, p2: u32) {}
200 fn foo(&mut self, p1: i32, p2: u32) {}
205 Foo::foo(&mut foo, 9, 9u)
212 fn struct_method_cross_crate() {
216 //- /main.rs crate:main deps:dep
218 let foo = dep::test_mod::Foo {};
221 //- /dep.rs crate:dep
225 pub fn foo(&mut self, p1: i32, p2: u32) {}
231 let foo = dep::test_mod::Foo {};
232 dep::test_mod::Foo::foo(&mut foo, 9, 9u)
239 fn struct_method_generic() {
273 pub trait TestTrait {
274 fn test_method(&self);
276 pub struct TestStruct {}
277 impl TestTrait for TestStruct {
278 fn test_method(&self) {}
285 let test_struct = test_mod::TestStruct {};
286 test_struct.test_meth$0od()
291 pub trait TestTrait {
292 fn test_method(&self);
294 pub struct TestStruct {}
295 impl TestTrait for TestStruct {
296 fn test_method(&self) {}
303 let test_struct = test_mod::TestStruct {};
304 TestTrait::test_method(&test_struct)
311 fn trait_method_multi_params() {
316 pub trait TestTrait {
317 fn test_method(&self, p1: i32, p2: u32);
319 pub struct TestStruct {}
320 impl TestTrait for TestStruct {
321 fn test_method(&self, p1: i32, p2: u32) {}
328 let test_struct = test_mod::TestStruct {};
329 test_struct.test_meth$0od(12, 32u)
334 pub trait TestTrait {
335 fn test_method(&self, p1: i32, p2: u32);
337 pub struct TestStruct {}
338 impl TestTrait for TestStruct {
339 fn test_method(&self, p1: i32, p2: u32) {}
346 let test_struct = test_mod::TestStruct {};
347 TestTrait::test_method(&test_struct, 12, 32u)
354 fn trait_method_consume() {
359 pub trait TestTrait {
360 fn test_method(self, p1: i32, p2: u32);
362 pub struct TestStruct {}
363 impl TestTrait for TestStruct {
364 fn test_method(self, p1: i32, p2: u32) {}
371 let test_struct = test_mod::TestStruct {};
372 test_struct.test_meth$0od(12, 32u)
377 pub trait TestTrait {
378 fn test_method(self, p1: i32, p2: u32);
380 pub struct TestStruct {}
381 impl TestTrait for TestStruct {
382 fn test_method(self, p1: i32, p2: u32) {}
389 let test_struct = test_mod::TestStruct {};
390 TestTrait::test_method(test_struct, 12, 32u)
397 fn trait_method_exclusive() {
402 pub trait TestTrait {
403 fn test_method(&mut self, p1: i32, p2: u32);
405 pub struct TestStruct {}
406 impl TestTrait for TestStruct {
407 fn test_method(&mut self, p1: i32, p2: u32);
414 let test_struct = test_mod::TestStruct {};
415 test_struct.test_meth$0od(12, 32u)
420 pub trait TestTrait {
421 fn test_method(&mut self, p1: i32, p2: u32);
423 pub struct TestStruct {}
424 impl TestTrait for TestStruct {
425 fn test_method(&mut self, p1: i32, p2: u32);
432 let test_struct = test_mod::TestStruct {};
433 TestTrait::test_method(&mut test_struct, 12, 32u)
440 fn trait_method_cross_crate() {
444 //- /main.rs crate:main deps:dep
446 let foo = dep::test_mod::Foo {};
449 //- /dep.rs crate:dep
453 pub fn foo(&mut self, p1: i32, p2: u32) {}
459 let foo = dep::test_mod::Foo {};
460 dep::test_mod::Foo::foo(&mut foo, 9, 9u)
467 fn trait_method_generic() {
472 pub trait TestTrait {
473 fn test_method<T>(&self);
475 pub struct TestStruct {}
476 impl TestTrait for TestStruct {
477 fn test_method<T>(&self) {}
484 let test_struct = TestStruct {};
485 test_struct.test_meth$0od::<()>()
490 pub trait TestTrait {
491 fn test_method<T>(&self);
493 pub struct TestStruct {}
494 impl TestTrait for TestStruct {
495 fn test_method<T>(&self) {}
502 let test_struct = TestStruct {};
503 TestTrait::test_method::<()>(&test_struct)
510 fn struct_method_over_stuct_instance() {
511 check_assist_not_applicable(
528 fn trait_method_over_stuct_instance() {
529 check_assist_not_applicable(
533 pub trait TestTrait {
534 fn test_method(&self);
536 pub struct TestStruct {}
537 impl TestTrait for TestStruct {
538 fn test_method(&self) {}
545 let test_struct = test_mod::TestStruct {};
546 tes$0t_struct.test_method()