]> git.lizzy.rs Git - rust.git/blob - crates/ide-assists/src/handlers/qualify_method_call.rs
fix some test due to resolve to where trait m impl
[rust.git] / crates / ide-assists / src / handlers / qualify_method_call.rs
1 use hir::{ItemInNs, ModuleDef};
2 use ide_db::{
3     assists::{AssistId, AssistKind},
4     imports::import_assets::item_for_path_search,
5 };
6 use syntax::{ast, AstNode};
7
8 use crate::{
9     assist_context::{AssistContext, Assists},
10     handlers::qualify_path::QualifyCandidate,
11 };
12
13 // Assist: qualify_method_call
14 //
15 // Replaces the method call with a qualified function call.
16 //
17 // ```
18 // struct Foo;
19 // impl Foo {
20 //     fn foo(&self) {}
21 // }
22 // fn main() {
23 //     let foo = Foo;
24 //     foo.fo$0o();
25 // }
26 // ```
27 // ->
28 // ```
29 // struct Foo;
30 // impl Foo {
31 //     fn foo(&self) {}
32 // }
33 // fn main() {
34 //     let foo = Foo;
35 //     Foo::foo(&foo);
36 // }
37 // ```
38 pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
39     let name: ast::NameRef = ctx.find_node_at_offset()?;
40     let call = name.syntax().parent().and_then(ast::MethodCallExpr::cast)?;
41
42     let ident = name.ident_token()?;
43
44     let range = call.syntax().text_range();
45     let resolved_call = ctx.sema.resolve_method_call(&call)?;
46
47     let current_module = ctx.sema.scope(call.syntax())?.module();
48     let target_module_def = ModuleDef::from(resolved_call);
49     let item_in_ns = ItemInNs::from(target_module_def);
50     let receiver_path = current_module
51         .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?;
52
53     let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call);
54
55     acc.add(
56         AssistId("qualify_method_call", AssistKind::RefactorInline),
57         format!("Qualify `{}` method call", ident.text()),
58         range,
59         |builder| {
60             qualify_candidate.qualify(
61                 |replace_with: String| builder.replace(range, replace_with),
62                 &receiver_path,
63                 item_in_ns,
64             )
65         },
66     );
67     Some(())
68 }
69
70 #[cfg(test)]
71 mod tests {
72     use super::*;
73     use crate::tests::{check_assist, check_assist_not_applicable};
74
75     #[test]
76     fn struct_method() {
77         check_assist(
78             qualify_method_call,
79             r#"
80 struct Foo;
81 impl Foo {
82     fn foo(&self) {}
83 }
84
85 fn main() {
86     let foo = Foo {};
87     foo.fo$0o()
88 }
89 "#,
90             r#"
91 struct Foo;
92 impl Foo {
93     fn foo(&self) {}
94 }
95
96 fn main() {
97     let foo = Foo {};
98     Foo::foo(&foo)
99 }
100 "#,
101         );
102     }
103
104     #[test]
105     fn struct_method_multi_params() {
106         check_assist(
107             qualify_method_call,
108             r#"
109 struct Foo;
110 impl Foo {
111     fn foo(&self, p1: i32, p2: u32) {}
112 }
113
114 fn main() {
115     let foo = Foo {};
116     foo.fo$0o(9, 9u)
117 }
118 "#,
119             r#"
120 struct Foo;
121 impl Foo {
122     fn foo(&self, p1: i32, p2: u32) {}
123 }
124
125 fn main() {
126     let foo = Foo {};
127     Foo::foo(&foo, 9, 9u)
128 }
129 "#,
130         );
131     }
132
133     #[test]
134     fn struct_method_consume() {
135         check_assist(
136             qualify_method_call,
137             r#"
138 struct Foo;
139 impl Foo {
140     fn foo(self, p1: i32, p2: u32) {}
141 }
142
143 fn main() {
144     let foo = Foo {};
145     foo.fo$0o(9, 9u)
146 }
147 "#,
148             r#"
149 struct Foo;
150 impl Foo {
151     fn foo(self, p1: i32, p2: u32) {}
152 }
153
154 fn main() {
155     let foo = Foo {};
156     Foo::foo(foo, 9, 9u)
157 }
158 "#,
159         );
160     }
161
162     #[test]
163     fn struct_method_exclusive() {
164         check_assist(
165             qualify_method_call,
166             r#"
167 struct Foo;
168 impl Foo {
169     fn foo(&mut self, p1: i32, p2: u32) {}
170 }
171
172 fn main() {
173     let foo = Foo {};
174     foo.fo$0o(9, 9u)
175 }
176 "#,
177             r#"
178 struct Foo;
179 impl Foo {
180     fn foo(&mut self, p1: i32, p2: u32) {}
181 }
182
183 fn main() {
184     let foo = Foo {};
185     Foo::foo(&mut foo, 9, 9u)
186 }
187 "#,
188         );
189     }
190
191     #[test]
192     fn struct_method_cross_crate() {
193         check_assist(
194             qualify_method_call,
195             r#"
196 //- /main.rs crate:main deps:dep
197 fn main() {
198     let foo = dep::test_mod::Foo {};
199     foo.fo$0o(9, 9u)
200 }
201 //- /dep.rs crate:dep
202 pub mod test_mod {
203     pub struct Foo;
204     impl Foo {
205         pub fn foo(&mut self, p1: i32, p2: u32) {}
206     }
207 }
208 "#,
209             r#"
210 fn main() {
211     let foo = dep::test_mod::Foo {};
212     dep::test_mod::Foo::foo(&mut foo, 9, 9u)
213 }
214 "#,
215         );
216     }
217
218     #[test]
219     fn struct_method_generic() {
220         check_assist(
221             qualify_method_call,
222             r#"
223 struct Foo;
224 impl Foo {
225     fn foo<T>(&self) {}
226 }
227
228 fn main() {
229     let foo = Foo {};
230     foo.fo$0o::<()>()
231 }
232 "#,
233             r#"
234 struct Foo;
235 impl Foo {
236     fn foo<T>(&self) {}
237 }
238
239 fn main() {
240     let foo = Foo {};
241     Foo::foo::<()>(&foo)
242 }
243 "#,
244         );
245     }
246
247     #[test]
248     fn trait_method() {
249         check_assist(
250             qualify_method_call,
251             r#"
252 mod test_mod {
253     pub trait TestTrait {
254         fn test_method(&self);
255     }
256     pub struct TestStruct {}
257     impl TestTrait for TestStruct {
258         fn test_method(&self) {}
259     }
260 }
261
262 use test_mod::*;
263
264 fn main() {
265     let test_struct = test_mod::TestStruct {};
266     test_struct.test_meth$0od()
267 }
268 "#,
269             r#"
270 mod test_mod {
271     pub trait TestTrait {
272         fn test_method(&self);
273     }
274     pub struct TestStruct {}
275     impl TestTrait for TestStruct {
276         fn test_method(&self) {}
277     }
278 }
279
280 use test_mod::*;
281
282 fn main() {
283     let test_struct = test_mod::TestStruct {};
284     TestStruct::test_method(&test_struct)
285 }
286 "#,
287         );
288     }
289
290     #[test]
291     fn trait_method_multi_params() {
292         check_assist(
293             qualify_method_call,
294             r#"
295 mod test_mod {
296     pub trait TestTrait {
297         fn test_method(&self, p1: i32, p2: u32);
298     }
299     pub struct TestStruct {}
300     impl TestTrait for TestStruct {
301         fn test_method(&self, p1: i32, p2: u32) {}
302     }
303 }
304
305 use test_mod::*;
306
307 fn main() {
308     let test_struct = test_mod::TestStruct {};
309     test_struct.test_meth$0od(12, 32u)
310 }
311 "#,
312             r#"
313 mod test_mod {
314     pub trait TestTrait {
315         fn test_method(&self, p1: i32, p2: u32);
316     }
317     pub struct TestStruct {}
318     impl TestTrait for TestStruct {
319         fn test_method(&self, p1: i32, p2: u32) {}
320     }
321 }
322
323 use test_mod::*;
324
325 fn main() {
326     let test_struct = test_mod::TestStruct {};
327     TestStruct::test_method(&test_struct, 12, 32u)
328 }
329 "#,
330         );
331     }
332
333     #[test]
334     fn trait_method_consume() {
335         check_assist(
336             qualify_method_call,
337             r#"
338 mod test_mod {
339     pub trait TestTrait {
340         fn test_method(self, p1: i32, p2: u32);
341     }
342     pub struct TestStruct {}
343     impl TestTrait for TestStruct {
344         fn test_method(self, p1: i32, p2: u32) {}
345     }
346 }
347
348 use test_mod::*;
349
350 fn main() {
351     let test_struct = test_mod::TestStruct {};
352     test_struct.test_meth$0od(12, 32u)
353 }
354 "#,
355             r#"
356 mod test_mod {
357     pub trait TestTrait {
358         fn test_method(self, p1: i32, p2: u32);
359     }
360     pub struct TestStruct {}
361     impl TestTrait for TestStruct {
362         fn test_method(self, p1: i32, p2: u32) {}
363     }
364 }
365
366 use test_mod::*;
367
368 fn main() {
369     let test_struct = test_mod::TestStruct {};
370     TestStruct::test_method(test_struct, 12, 32u)
371 }
372 "#,
373         );
374     }
375
376     #[test]
377     fn trait_method_exclusive() {
378         check_assist(
379             qualify_method_call,
380             r#"
381 mod test_mod {
382     pub trait TestTrait {
383         fn test_method(&mut self, p1: i32, p2: u32);
384     }
385     pub struct TestStruct {}
386     impl TestTrait for TestStruct {
387         fn test_method(&mut self, p1: i32, p2: u32);
388     }
389 }
390
391 use test_mod::*;
392
393 fn main() {
394     let test_struct = test_mod::TestStruct {};
395     test_struct.test_meth$0od(12, 32u)
396 }
397 "#,
398             r#"
399 mod test_mod {
400     pub trait TestTrait {
401         fn test_method(&mut self, p1: i32, p2: u32);
402     }
403     pub struct TestStruct {}
404     impl TestTrait for TestStruct {
405         fn test_method(&mut self, p1: i32, p2: u32);
406     }
407 }
408
409 use test_mod::*;
410
411 fn main() {
412     let test_struct = test_mod::TestStruct {};
413     TestStruct::test_method(&mut test_struct, 12, 32u)
414 }
415 "#,
416         );
417     }
418
419     #[test]
420     fn trait_method_cross_crate() {
421         check_assist(
422             qualify_method_call,
423             r#"
424 //- /main.rs crate:main deps:dep
425 fn main() {
426     let foo = dep::test_mod::Foo {};
427     foo.fo$0o(9, 9u)
428 }
429 //- /dep.rs crate:dep
430 pub mod test_mod {
431     pub struct Foo;
432     impl Foo {
433         pub fn foo(&mut self, p1: i32, p2: u32) {}
434     }
435 }
436 "#,
437             r#"
438 fn main() {
439     let foo = dep::test_mod::Foo {};
440     dep::test_mod::Foo::foo(&mut foo, 9, 9u)
441 }
442 "#,
443         );
444     }
445
446     #[test]
447     fn trait_method_generic() {
448         check_assist(
449             qualify_method_call,
450             r#"
451 mod test_mod {
452     pub trait TestTrait {
453         fn test_method<T>(&self);
454     }
455     pub struct TestStruct {}
456     impl TestTrait for TestStruct {
457         fn test_method<T>(&self) {}
458     }
459 }
460
461 use test_mod::*;
462
463 fn main() {
464     let test_struct = TestStruct {};
465     test_struct.test_meth$0od::<()>()
466 }
467 "#,
468             r#"
469 mod test_mod {
470     pub trait TestTrait {
471         fn test_method<T>(&self);
472     }
473     pub struct TestStruct {}
474     impl TestTrait for TestStruct {
475         fn test_method<T>(&self) {}
476     }
477 }
478
479 use test_mod::*;
480
481 fn main() {
482     let test_struct = TestStruct {};
483     TestStruct::test_method::<()>(&test_struct)
484 }
485 "#,
486         );
487     }
488
489     #[test]
490     fn struct_method_over_stuct_instance() {
491         check_assist_not_applicable(
492             qualify_method_call,
493             r#"
494 struct Foo;
495 impl Foo {
496     fn foo(&self) {}
497 }
498
499 fn main() {
500     let foo = Foo {};
501     f$0oo.foo()
502 }
503 "#,
504         );
505     }
506
507     #[test]
508     fn trait_method_over_stuct_instance() {
509         check_assist_not_applicable(
510             qualify_method_call,
511             r#"
512 mod test_mod {
513     pub trait TestTrait {
514         fn test_method(&self);
515     }
516     pub struct TestStruct {}
517     impl TestTrait for TestStruct {
518         fn test_method(&self) {}
519     }
520 }
521
522 use test_mod::*;
523
524 fn main() {
525     let test_struct = test_mod::TestStruct {};
526     tes$0t_struct.test_method()
527 }
528 "#,
529         );
530     }
531 }