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
48 .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?;
50 let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call);
53 AssistId("qualify_method_call", AssistKind::RefactorInline),
54 format!("Qualify `{}` method call", ident.text()),
57 qualify_candidate.qualify(
58 |replace_with: String| builder.replace(range, replace_with),
67 fn item_for_path_search(db: &dyn HirDatabase, item: ItemInNs) -> Option<ItemInNs> {
69 ItemInNs::Types(_) | ItemInNs::Values(_) => match item_as_assoc(db, item) {
70 Some(assoc_item) => match assoc_item.container(db) {
71 AssocItemContainer::Trait(trait_) => ItemInNs::from(ModuleDef::from(trait_)),
72 AssocItemContainer::Impl(impl_) => match impl_.trait_(db) {
73 None => ItemInNs::from(ModuleDef::from(impl_.self_ty(db).as_adt()?)),
74 Some(trait_) => ItemInNs::from(ModuleDef::from(trait_)),
79 ItemInNs::Macros(_) => item,
83 fn item_as_assoc(db: &dyn HirDatabase, item: ItemInNs) -> Option<AssocItem> {
84 item.as_module_def().and_then(|module_def| module_def.as_assoc_item(db))
90 use crate::tests::{check_assist, check_assist_not_applicable};
122 fn struct_method_multi_params() {
128 fn foo(&self, p1: i32, p2: u32) {}
139 fn foo(&self, p1: i32, p2: u32) {}
144 Foo::foo(&foo, 9, 9u)
151 fn struct_method_consume() {
157 fn foo(self, p1: i32, p2: u32) {}
168 fn foo(self, p1: i32, p2: u32) {}
180 fn struct_method_exclusive() {
186 fn foo(&mut self, p1: i32, p2: u32) {}
197 fn foo(&mut self, p1: i32, p2: u32) {}
202 Foo::foo(&mut foo, 9, 9u)
209 fn struct_method_cross_crate() {
213 //- /main.rs crate:main deps:dep
215 let foo = dep::test_mod::Foo {};
218 //- /dep.rs crate:dep
222 pub fn foo(&mut self, p1: i32, p2: u32) {}
228 let foo = dep::test_mod::Foo {};
229 dep::test_mod::Foo::foo(&mut foo, 9, 9u)
236 fn struct_method_generic() {
270 pub trait TestTrait {
271 fn test_method(&self);
273 pub struct TestStruct {}
274 impl TestTrait for TestStruct {
275 fn test_method(&self) {}
282 let test_struct = test_mod::TestStruct {};
283 test_struct.test_meth$0od()
288 pub trait TestTrait {
289 fn test_method(&self);
291 pub struct TestStruct {}
292 impl TestTrait for TestStruct {
293 fn test_method(&self) {}
300 let test_struct = test_mod::TestStruct {};
301 TestTrait::test_method(&test_struct)
308 fn trait_method_multi_params() {
313 pub trait TestTrait {
314 fn test_method(&self, p1: i32, p2: u32);
316 pub struct TestStruct {}
317 impl TestTrait for TestStruct {
318 fn test_method(&self, p1: i32, p2: u32) {}
325 let test_struct = test_mod::TestStruct {};
326 test_struct.test_meth$0od(12, 32u)
331 pub trait TestTrait {
332 fn test_method(&self, p1: i32, p2: u32);
334 pub struct TestStruct {}
335 impl TestTrait for TestStruct {
336 fn test_method(&self, p1: i32, p2: u32) {}
343 let test_struct = test_mod::TestStruct {};
344 TestTrait::test_method(&test_struct, 12, 32u)
351 fn trait_method_consume() {
356 pub trait TestTrait {
357 fn test_method(self, p1: i32, p2: u32);
359 pub struct TestStruct {}
360 impl TestTrait for TestStruct {
361 fn test_method(self, p1: i32, p2: u32) {}
368 let test_struct = test_mod::TestStruct {};
369 test_struct.test_meth$0od(12, 32u)
374 pub trait TestTrait {
375 fn test_method(self, p1: i32, p2: u32);
377 pub struct TestStruct {}
378 impl TestTrait for TestStruct {
379 fn test_method(self, p1: i32, p2: u32) {}
386 let test_struct = test_mod::TestStruct {};
387 TestTrait::test_method(test_struct, 12, 32u)
394 fn trait_method_exclusive() {
399 pub trait TestTrait {
400 fn test_method(&mut self, p1: i32, p2: u32);
402 pub struct TestStruct {}
403 impl TestTrait for TestStruct {
404 fn test_method(&mut self, p1: i32, p2: u32);
411 let test_struct = test_mod::TestStruct {};
412 test_struct.test_meth$0od(12, 32u)
417 pub trait TestTrait {
418 fn test_method(&mut self, p1: i32, p2: u32);
420 pub struct TestStruct {}
421 impl TestTrait for TestStruct {
422 fn test_method(&mut self, p1: i32, p2: u32);
429 let test_struct = test_mod::TestStruct {};
430 TestTrait::test_method(&mut test_struct, 12, 32u)
437 fn trait_method_cross_crate() {
441 //- /main.rs crate:main deps:dep
443 let foo = dep::test_mod::Foo {};
446 //- /dep.rs crate:dep
450 pub fn foo(&mut self, p1: i32, p2: u32) {}
456 let foo = dep::test_mod::Foo {};
457 dep::test_mod::Foo::foo(&mut foo, 9, 9u)
464 fn trait_method_generic() {
469 pub trait TestTrait {
470 fn test_method<T>(&self);
472 pub struct TestStruct {}
473 impl TestTrait for TestStruct {
474 fn test_method<T>(&self) {}
481 let test_struct = TestStruct {};
482 test_struct.test_meth$0od::<()>()
487 pub trait TestTrait {
488 fn test_method<T>(&self);
490 pub struct TestStruct {}
491 impl TestTrait for TestStruct {
492 fn test_method<T>(&self) {}
499 let test_struct = TestStruct {};
500 TestTrait::test_method::<()>(&test_struct)
507 fn struct_method_over_stuct_instance() {
508 check_assist_not_applicable(
525 fn trait_method_over_stuct_instance() {
526 check_assist_not_applicable(
530 pub trait TestTrait {
531 fn test_method(&self);
533 pub struct TestStruct {}
534 impl TestTrait for TestStruct {
535 fn test_method(&self) {}
542 let test_struct = test_mod::TestStruct {};
543 tes$0t_struct.test_method()