diff options
Diffstat (limited to 'crates/assists/src/handlers/qualify_path.rs')
-rw-r--r-- | crates/assists/src/handlers/qualify_path.rs | 1212 |
1 files changed, 0 insertions, 1212 deletions
diff --git a/crates/assists/src/handlers/qualify_path.rs b/crates/assists/src/handlers/qualify_path.rs deleted file mode 100644 index a7d9fd4dc..000000000 --- a/crates/assists/src/handlers/qualify_path.rs +++ /dev/null | |||
@@ -1,1212 +0,0 @@ | |||
1 | use std::iter; | ||
2 | |||
3 | use hir::AsName; | ||
4 | use ide_db::helpers::{ | ||
5 | import_assets::{ImportAssets, ImportCandidate}, | ||
6 | mod_path_to_ast, | ||
7 | }; | ||
8 | use ide_db::RootDatabase; | ||
9 | use syntax::{ | ||
10 | ast, | ||
11 | ast::{make, ArgListOwner}, | ||
12 | AstNode, | ||
13 | }; | ||
14 | use test_utils::mark; | ||
15 | |||
16 | use crate::{ | ||
17 | assist_context::{AssistContext, Assists}, | ||
18 | AssistId, AssistKind, GroupLabel, | ||
19 | }; | ||
20 | |||
21 | // Assist: qualify_path | ||
22 | // | ||
23 | // If the name is unresolved, provides all possible qualified paths for it. | ||
24 | // | ||
25 | // ``` | ||
26 | // fn main() { | ||
27 | // let map = HashMap$0::new(); | ||
28 | // } | ||
29 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | ||
30 | // ``` | ||
31 | // -> | ||
32 | // ``` | ||
33 | // fn main() { | ||
34 | // let map = std::collections::HashMap::new(); | ||
35 | // } | ||
36 | // # pub mod std { pub mod collections { pub struct HashMap { } } } | ||
37 | // ``` | ||
38 | pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
39 | let import_assets = | ||
40 | if let Some(path_under_caret) = ctx.find_node_at_offset_with_descend::<ast::Path>() { | ||
41 | ImportAssets::for_regular_path(path_under_caret, &ctx.sema) | ||
42 | } else if let Some(method_under_caret) = | ||
43 | ctx.find_node_at_offset_with_descend::<ast::MethodCallExpr>() | ||
44 | { | ||
45 | ImportAssets::for_method_call(method_under_caret, &ctx.sema) | ||
46 | } else { | ||
47 | None | ||
48 | }?; | ||
49 | let proposed_imports = import_assets.search_for_relative_paths(&ctx.sema); | ||
50 | if proposed_imports.is_empty() { | ||
51 | return None; | ||
52 | } | ||
53 | |||
54 | let candidate = import_assets.import_candidate(); | ||
55 | let range = ctx.sema.original_range(import_assets.syntax_under_caret()).range; | ||
56 | |||
57 | let qualify_candidate = match candidate { | ||
58 | ImportCandidate::Path(candidate) => { | ||
59 | if candidate.qualifier.is_some() { | ||
60 | mark::hit!(qualify_path_qualifier_start); | ||
61 | let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; | ||
62 | let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?); | ||
63 | QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list()) | ||
64 | } else { | ||
65 | mark::hit!(qualify_path_unqualified_name); | ||
66 | let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; | ||
67 | let generics = path.segment()?.generic_arg_list(); | ||
68 | QualifyCandidate::UnqualifiedName(generics) | ||
69 | } | ||
70 | } | ||
71 | ImportCandidate::TraitAssocItem(_) => { | ||
72 | mark::hit!(qualify_path_trait_assoc_item); | ||
73 | let path = ast::Path::cast(import_assets.syntax_under_caret().clone())?; | ||
74 | let (qualifier, segment) = (path.qualifier()?, path.segment()?); | ||
75 | QualifyCandidate::TraitAssocItem(qualifier, segment) | ||
76 | } | ||
77 | ImportCandidate::TraitMethod(_) => { | ||
78 | mark::hit!(qualify_path_trait_method); | ||
79 | let mcall_expr = ast::MethodCallExpr::cast(import_assets.syntax_under_caret().clone())?; | ||
80 | QualifyCandidate::TraitMethod(ctx.sema.db, mcall_expr) | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | let group_label = group_label(candidate); | ||
85 | for (import, item) in proposed_imports { | ||
86 | acc.add_group( | ||
87 | &group_label, | ||
88 | AssistId("qualify_path", AssistKind::QuickFix), | ||
89 | label(candidate, &import), | ||
90 | range, | ||
91 | |builder| { | ||
92 | qualify_candidate.qualify( | ||
93 | |replace_with: String| builder.replace(range, replace_with), | ||
94 | import, | ||
95 | item, | ||
96 | ) | ||
97 | }, | ||
98 | ); | ||
99 | } | ||
100 | Some(()) | ||
101 | } | ||
102 | |||
103 | enum QualifyCandidate<'db> { | ||
104 | QualifierStart(ast::PathSegment, Option<ast::GenericArgList>), | ||
105 | UnqualifiedName(Option<ast::GenericArgList>), | ||
106 | TraitAssocItem(ast::Path, ast::PathSegment), | ||
107 | TraitMethod(&'db RootDatabase, ast::MethodCallExpr), | ||
108 | } | ||
109 | |||
110 | impl QualifyCandidate<'_> { | ||
111 | fn qualify(&self, mut replacer: impl FnMut(String), import: hir::ModPath, item: hir::ItemInNs) { | ||
112 | let import = mod_path_to_ast(&import); | ||
113 | match self { | ||
114 | QualifyCandidate::QualifierStart(segment, generics) => { | ||
115 | let generics = generics.as_ref().map_or_else(String::new, ToString::to_string); | ||
116 | replacer(format!("{}{}::{}", import, generics, segment)); | ||
117 | } | ||
118 | QualifyCandidate::UnqualifiedName(generics) => { | ||
119 | let generics = generics.as_ref().map_or_else(String::new, ToString::to_string); | ||
120 | replacer(format!("{}{}", import.to_string(), generics)); | ||
121 | } | ||
122 | QualifyCandidate::TraitAssocItem(qualifier, segment) => { | ||
123 | replacer(format!("<{} as {}>::{}", qualifier, import, segment)); | ||
124 | } | ||
125 | &QualifyCandidate::TraitMethod(db, ref mcall_expr) => { | ||
126 | Self::qualify_trait_method(db, mcall_expr, replacer, import, item); | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | |||
131 | fn qualify_trait_method( | ||
132 | db: &RootDatabase, | ||
133 | mcall_expr: &ast::MethodCallExpr, | ||
134 | mut replacer: impl FnMut(String), | ||
135 | import: ast::Path, | ||
136 | item: hir::ItemInNs, | ||
137 | ) -> Option<()> { | ||
138 | let receiver = mcall_expr.receiver()?; | ||
139 | let trait_method_name = mcall_expr.name_ref()?; | ||
140 | let generics = | ||
141 | mcall_expr.generic_arg_list().as_ref().map_or_else(String::new, ToString::to_string); | ||
142 | let arg_list = mcall_expr.arg_list().map(|arg_list| arg_list.args()); | ||
143 | let trait_ = item_as_trait(item)?; | ||
144 | let method = find_trait_method(db, trait_, &trait_method_name)?; | ||
145 | if let Some(self_access) = method.self_param(db).map(|sp| sp.access(db)) { | ||
146 | let receiver = match self_access { | ||
147 | hir::Access::Shared => make::expr_ref(receiver, false), | ||
148 | hir::Access::Exclusive => make::expr_ref(receiver, true), | ||
149 | hir::Access::Owned => receiver, | ||
150 | }; | ||
151 | replacer(format!( | ||
152 | "{}::{}{}{}", | ||
153 | import, | ||
154 | trait_method_name, | ||
155 | generics, | ||
156 | match arg_list { | ||
157 | Some(args) => make::arg_list(iter::once(receiver).chain(args)), | ||
158 | None => make::arg_list(iter::once(receiver)), | ||
159 | } | ||
160 | )); | ||
161 | } | ||
162 | Some(()) | ||
163 | } | ||
164 | } | ||
165 | |||
166 | fn find_trait_method( | ||
167 | db: &RootDatabase, | ||
168 | trait_: hir::Trait, | ||
169 | trait_method_name: &ast::NameRef, | ||
170 | ) -> Option<hir::Function> { | ||
171 | if let Some(hir::AssocItem::Function(method)) = | ||
172 | trait_.items(db).into_iter().find(|item: &hir::AssocItem| { | ||
173 | item.name(db).map(|name| name == trait_method_name.as_name()).unwrap_or(false) | ||
174 | }) | ||
175 | { | ||
176 | Some(method) | ||
177 | } else { | ||
178 | None | ||
179 | } | ||
180 | } | ||
181 | |||
182 | fn item_as_trait(item: hir::ItemInNs) -> Option<hir::Trait> { | ||
183 | if let hir::ModuleDef::Trait(trait_) = hir::ModuleDef::from(item.as_module_def_id()?) { | ||
184 | Some(trait_) | ||
185 | } else { | ||
186 | None | ||
187 | } | ||
188 | } | ||
189 | |||
190 | fn group_label(candidate: &ImportCandidate) -> GroupLabel { | ||
191 | let name = match candidate { | ||
192 | ImportCandidate::Path(it) => &it.name, | ||
193 | ImportCandidate::TraitAssocItem(it) | ImportCandidate::TraitMethod(it) => &it.name, | ||
194 | }; | ||
195 | GroupLabel(format!("Qualify {}", name)) | ||
196 | } | ||
197 | |||
198 | fn label(candidate: &ImportCandidate, import: &hir::ModPath) -> String { | ||
199 | match candidate { | ||
200 | ImportCandidate::Path(candidate) => { | ||
201 | if candidate.qualifier.is_some() { | ||
202 | format!("Qualify with `{}`", &import) | ||
203 | } else { | ||
204 | format!("Qualify as `{}`", &import) | ||
205 | } | ||
206 | } | ||
207 | ImportCandidate::TraitAssocItem(_) => format!("Qualify `{}`", &import), | ||
208 | ImportCandidate::TraitMethod(_) => format!("Qualify with cast as `{}`", &import), | ||
209 | } | ||
210 | } | ||
211 | |||
212 | #[cfg(test)] | ||
213 | mod tests { | ||
214 | use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target}; | ||
215 | |||
216 | use super::*; | ||
217 | |||
218 | #[test] | ||
219 | fn applicable_when_found_an_import_partial() { | ||
220 | mark::check!(qualify_path_unqualified_name); | ||
221 | check_assist( | ||
222 | qualify_path, | ||
223 | r" | ||
224 | mod std { | ||
225 | pub mod fmt { | ||
226 | pub struct Formatter; | ||
227 | } | ||
228 | } | ||
229 | |||
230 | use std::fmt; | ||
231 | |||
232 | $0Formatter | ||
233 | ", | ||
234 | r" | ||
235 | mod std { | ||
236 | pub mod fmt { | ||
237 | pub struct Formatter; | ||
238 | } | ||
239 | } | ||
240 | |||
241 | use std::fmt; | ||
242 | |||
243 | fmt::Formatter | ||
244 | ", | ||
245 | ); | ||
246 | } | ||
247 | |||
248 | #[test] | ||
249 | fn applicable_when_found_an_import() { | ||
250 | check_assist( | ||
251 | qualify_path, | ||
252 | r" | ||
253 | $0PubStruct | ||
254 | |||
255 | pub mod PubMod { | ||
256 | pub struct PubStruct; | ||
257 | } | ||
258 | ", | ||
259 | r" | ||
260 | PubMod::PubStruct | ||
261 | |||
262 | pub mod PubMod { | ||
263 | pub struct PubStruct; | ||
264 | } | ||
265 | ", | ||
266 | ); | ||
267 | } | ||
268 | |||
269 | #[test] | ||
270 | fn applicable_in_macros() { | ||
271 | check_assist( | ||
272 | qualify_path, | ||
273 | r" | ||
274 | macro_rules! foo { | ||
275 | ($i:ident) => { fn foo(a: $i) {} } | ||
276 | } | ||
277 | foo!(Pub$0Struct); | ||
278 | |||
279 | pub mod PubMod { | ||
280 | pub struct PubStruct; | ||
281 | } | ||
282 | ", | ||
283 | r" | ||
284 | macro_rules! foo { | ||
285 | ($i:ident) => { fn foo(a: $i) {} } | ||
286 | } | ||
287 | foo!(PubMod::PubStruct); | ||
288 | |||
289 | pub mod PubMod { | ||
290 | pub struct PubStruct; | ||
291 | } | ||
292 | ", | ||
293 | ); | ||
294 | } | ||
295 | |||
296 | #[test] | ||
297 | fn applicable_when_found_multiple_imports() { | ||
298 | check_assist( | ||
299 | qualify_path, | ||
300 | r" | ||
301 | PubSt$0ruct | ||
302 | |||
303 | pub mod PubMod1 { | ||
304 | pub struct PubStruct; | ||
305 | } | ||
306 | pub mod PubMod2 { | ||
307 | pub struct PubStruct; | ||
308 | } | ||
309 | pub mod PubMod3 { | ||
310 | pub struct PubStruct; | ||
311 | } | ||
312 | ", | ||
313 | r" | ||
314 | PubMod3::PubStruct | ||
315 | |||
316 | pub mod PubMod1 { | ||
317 | pub struct PubStruct; | ||
318 | } | ||
319 | pub mod PubMod2 { | ||
320 | pub struct PubStruct; | ||
321 | } | ||
322 | pub mod PubMod3 { | ||
323 | pub struct PubStruct; | ||
324 | } | ||
325 | ", | ||
326 | ); | ||
327 | } | ||
328 | |||
329 | #[test] | ||
330 | fn not_applicable_for_already_imported_types() { | ||
331 | check_assist_not_applicable( | ||
332 | qualify_path, | ||
333 | r" | ||
334 | use PubMod::PubStruct; | ||
335 | |||
336 | PubStruct$0 | ||
337 | |||
338 | pub mod PubMod { | ||
339 | pub struct PubStruct; | ||
340 | } | ||
341 | ", | ||
342 | ); | ||
343 | } | ||
344 | |||
345 | #[test] | ||
346 | fn not_applicable_for_types_with_private_paths() { | ||
347 | check_assist_not_applicable( | ||
348 | qualify_path, | ||
349 | r" | ||
350 | PrivateStruct$0 | ||
351 | |||
352 | pub mod PubMod { | ||
353 | struct PrivateStruct; | ||
354 | } | ||
355 | ", | ||
356 | ); | ||
357 | } | ||
358 | |||
359 | #[test] | ||
360 | fn not_applicable_when_no_imports_found() { | ||
361 | check_assist_not_applicable( | ||
362 | qualify_path, | ||
363 | " | ||
364 | PubStruct$0", | ||
365 | ); | ||
366 | } | ||
367 | |||
368 | #[test] | ||
369 | fn not_applicable_in_import_statements() { | ||
370 | check_assist_not_applicable( | ||
371 | qualify_path, | ||
372 | r" | ||
373 | use PubStruct$0; | ||
374 | |||
375 | pub mod PubMod { | ||
376 | pub struct PubStruct; | ||
377 | }", | ||
378 | ); | ||
379 | } | ||
380 | |||
381 | #[test] | ||
382 | fn qualify_function() { | ||
383 | check_assist( | ||
384 | qualify_path, | ||
385 | r" | ||
386 | test_function$0 | ||
387 | |||
388 | pub mod PubMod { | ||
389 | pub fn test_function() {}; | ||
390 | } | ||
391 | ", | ||
392 | r" | ||
393 | PubMod::test_function | ||
394 | |||
395 | pub mod PubMod { | ||
396 | pub fn test_function() {}; | ||
397 | } | ||
398 | ", | ||
399 | ); | ||
400 | } | ||
401 | |||
402 | #[test] | ||
403 | fn qualify_macro() { | ||
404 | check_assist( | ||
405 | qualify_path, | ||
406 | r" | ||
407 | //- /lib.rs crate:crate_with_macro | ||
408 | #[macro_export] | ||
409 | macro_rules! foo { | ||
410 | () => () | ||
411 | } | ||
412 | |||
413 | //- /main.rs crate:main deps:crate_with_macro | ||
414 | fn main() { | ||
415 | foo$0 | ||
416 | } | ||
417 | ", | ||
418 | r" | ||
419 | fn main() { | ||
420 | crate_with_macro::foo | ||
421 | } | ||
422 | ", | ||
423 | ); | ||
424 | } | ||
425 | |||
426 | #[test] | ||
427 | fn qualify_path_target() { | ||
428 | check_assist_target( | ||
429 | qualify_path, | ||
430 | r" | ||
431 | struct AssistInfo { | ||
432 | group_label: Option<$0GroupLabel>, | ||
433 | } | ||
434 | |||
435 | mod m { pub struct GroupLabel; } | ||
436 | ", | ||
437 | "GroupLabel", | ||
438 | ) | ||
439 | } | ||
440 | |||
441 | #[test] | ||
442 | fn not_applicable_when_path_start_is_imported() { | ||
443 | check_assist_not_applicable( | ||
444 | qualify_path, | ||
445 | r" | ||
446 | pub mod mod1 { | ||
447 | pub mod mod2 { | ||
448 | pub mod mod3 { | ||
449 | pub struct TestStruct; | ||
450 | } | ||
451 | } | ||
452 | } | ||
453 | |||
454 | use mod1::mod2; | ||
455 | fn main() { | ||
456 | mod2::mod3::TestStruct$0 | ||
457 | } | ||
458 | ", | ||
459 | ); | ||
460 | } | ||
461 | |||
462 | #[test] | ||
463 | fn not_applicable_for_imported_function() { | ||
464 | check_assist_not_applicable( | ||
465 | qualify_path, | ||
466 | r" | ||
467 | pub mod test_mod { | ||
468 | pub fn test_function() {} | ||
469 | } | ||
470 | |||
471 | use test_mod::test_function; | ||
472 | fn main() { | ||
473 | test_function$0 | ||
474 | } | ||
475 | ", | ||
476 | ); | ||
477 | } | ||
478 | |||
479 | #[test] | ||
480 | fn associated_struct_function() { | ||
481 | check_assist( | ||
482 | qualify_path, | ||
483 | r" | ||
484 | mod test_mod { | ||
485 | pub struct TestStruct {} | ||
486 | impl TestStruct { | ||
487 | pub fn test_function() {} | ||
488 | } | ||
489 | } | ||
490 | |||
491 | fn main() { | ||
492 | TestStruct::test_function$0 | ||
493 | } | ||
494 | ", | ||
495 | r" | ||
496 | mod test_mod { | ||
497 | pub struct TestStruct {} | ||
498 | impl TestStruct { | ||
499 | pub fn test_function() {} | ||
500 | } | ||
501 | } | ||
502 | |||
503 | fn main() { | ||
504 | test_mod::TestStruct::test_function | ||
505 | } | ||
506 | ", | ||
507 | ); | ||
508 | } | ||
509 | |||
510 | #[test] | ||
511 | fn associated_struct_const() { | ||
512 | mark::check!(qualify_path_qualifier_start); | ||
513 | check_assist( | ||
514 | qualify_path, | ||
515 | r" | ||
516 | mod test_mod { | ||
517 | pub struct TestStruct {} | ||
518 | impl TestStruct { | ||
519 | const TEST_CONST: u8 = 42; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | fn main() { | ||
524 | TestStruct::TEST_CONST$0 | ||
525 | } | ||
526 | ", | ||
527 | r" | ||
528 | mod test_mod { | ||
529 | pub struct TestStruct {} | ||
530 | impl TestStruct { | ||
531 | const TEST_CONST: u8 = 42; | ||
532 | } | ||
533 | } | ||
534 | |||
535 | fn main() { | ||
536 | test_mod::TestStruct::TEST_CONST | ||
537 | } | ||
538 | ", | ||
539 | ); | ||
540 | } | ||
541 | |||
542 | #[test] | ||
543 | fn associated_trait_function() { | ||
544 | check_assist( | ||
545 | qualify_path, | ||
546 | r" | ||
547 | mod test_mod { | ||
548 | pub trait TestTrait { | ||
549 | fn test_function(); | ||
550 | } | ||
551 | pub struct TestStruct {} | ||
552 | impl TestTrait for TestStruct { | ||
553 | fn test_function() {} | ||
554 | } | ||
555 | } | ||
556 | |||
557 | fn main() { | ||
558 | test_mod::TestStruct::test_function$0 | ||
559 | } | ||
560 | ", | ||
561 | r" | ||
562 | mod test_mod { | ||
563 | pub trait TestTrait { | ||
564 | fn test_function(); | ||
565 | } | ||
566 | pub struct TestStruct {} | ||
567 | impl TestTrait for TestStruct { | ||
568 | fn test_function() {} | ||
569 | } | ||
570 | } | ||
571 | |||
572 | fn main() { | ||
573 | <test_mod::TestStruct as test_mod::TestTrait>::test_function | ||
574 | } | ||
575 | ", | ||
576 | ); | ||
577 | } | ||
578 | |||
579 | #[test] | ||
580 | fn not_applicable_for_imported_trait_for_function() { | ||
581 | check_assist_not_applicable( | ||
582 | qualify_path, | ||
583 | r" | ||
584 | mod test_mod { | ||
585 | pub trait TestTrait { | ||
586 | fn test_function(); | ||
587 | } | ||
588 | pub trait TestTrait2 { | ||
589 | fn test_function(); | ||
590 | } | ||
591 | pub enum TestEnum { | ||
592 | One, | ||
593 | Two, | ||
594 | } | ||
595 | impl TestTrait2 for TestEnum { | ||
596 | fn test_function() {} | ||
597 | } | ||
598 | impl TestTrait for TestEnum { | ||
599 | fn test_function() {} | ||
600 | } | ||
601 | } | ||
602 | |||
603 | use test_mod::TestTrait2; | ||
604 | fn main() { | ||
605 | test_mod::TestEnum::test_function$0; | ||
606 | } | ||
607 | ", | ||
608 | ) | ||
609 | } | ||
610 | |||
611 | #[test] | ||
612 | fn associated_trait_const() { | ||
613 | mark::check!(qualify_path_trait_assoc_item); | ||
614 | check_assist( | ||
615 | qualify_path, | ||
616 | r" | ||
617 | mod test_mod { | ||
618 | pub trait TestTrait { | ||
619 | const TEST_CONST: u8; | ||
620 | } | ||
621 | pub struct TestStruct {} | ||
622 | impl TestTrait for TestStruct { | ||
623 | const TEST_CONST: u8 = 42; | ||
624 | } | ||
625 | } | ||
626 | |||
627 | fn main() { | ||
628 | test_mod::TestStruct::TEST_CONST$0 | ||
629 | } | ||
630 | ", | ||
631 | r" | ||
632 | mod test_mod { | ||
633 | pub trait TestTrait { | ||
634 | const TEST_CONST: u8; | ||
635 | } | ||
636 | pub struct TestStruct {} | ||
637 | impl TestTrait for TestStruct { | ||
638 | const TEST_CONST: u8 = 42; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | fn main() { | ||
643 | <test_mod::TestStruct as test_mod::TestTrait>::TEST_CONST | ||
644 | } | ||
645 | ", | ||
646 | ); | ||
647 | } | ||
648 | |||
649 | #[test] | ||
650 | fn not_applicable_for_imported_trait_for_const() { | ||
651 | check_assist_not_applicable( | ||
652 | qualify_path, | ||
653 | r" | ||
654 | mod test_mod { | ||
655 | pub trait TestTrait { | ||
656 | const TEST_CONST: u8; | ||
657 | } | ||
658 | pub trait TestTrait2 { | ||
659 | const TEST_CONST: f64; | ||
660 | } | ||
661 | pub enum TestEnum { | ||
662 | One, | ||
663 | Two, | ||
664 | } | ||
665 | impl TestTrait2 for TestEnum { | ||
666 | const TEST_CONST: f64 = 42.0; | ||
667 | } | ||
668 | impl TestTrait for TestEnum { | ||
669 | const TEST_CONST: u8 = 42; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | use test_mod::TestTrait2; | ||
674 | fn main() { | ||
675 | test_mod::TestEnum::TEST_CONST$0; | ||
676 | } | ||
677 | ", | ||
678 | ) | ||
679 | } | ||
680 | |||
681 | #[test] | ||
682 | fn trait_method() { | ||
683 | mark::check!(qualify_path_trait_method); | ||
684 | check_assist( | ||
685 | qualify_path, | ||
686 | r" | ||
687 | mod test_mod { | ||
688 | pub trait TestTrait { | ||
689 | fn test_method(&self); | ||
690 | } | ||
691 | pub struct TestStruct {} | ||
692 | impl TestTrait for TestStruct { | ||
693 | fn test_method(&self) {} | ||
694 | } | ||
695 | } | ||
696 | |||
697 | fn main() { | ||
698 | let test_struct = test_mod::TestStruct {}; | ||
699 | test_struct.test_meth$0od() | ||
700 | } | ||
701 | ", | ||
702 | r" | ||
703 | mod test_mod { | ||
704 | pub trait TestTrait { | ||
705 | fn test_method(&self); | ||
706 | } | ||
707 | pub struct TestStruct {} | ||
708 | impl TestTrait for TestStruct { | ||
709 | fn test_method(&self) {} | ||
710 | } | ||
711 | } | ||
712 | |||
713 | fn main() { | ||
714 | let test_struct = test_mod::TestStruct {}; | ||
715 | test_mod::TestTrait::test_method(&test_struct) | ||
716 | } | ||
717 | ", | ||
718 | ); | ||
719 | } | ||
720 | |||
721 | #[test] | ||
722 | fn trait_method_multi_params() { | ||
723 | check_assist( | ||
724 | qualify_path, | ||
725 | r" | ||
726 | mod test_mod { | ||
727 | pub trait TestTrait { | ||
728 | fn test_method(&self, test: i32); | ||
729 | } | ||
730 | pub struct TestStruct {} | ||
731 | impl TestTrait for TestStruct { | ||
732 | fn test_method(&self, test: i32) {} | ||
733 | } | ||
734 | } | ||
735 | |||
736 | fn main() { | ||
737 | let test_struct = test_mod::TestStruct {}; | ||
738 | test_struct.test_meth$0od(42) | ||
739 | } | ||
740 | ", | ||
741 | r" | ||
742 | mod test_mod { | ||
743 | pub trait TestTrait { | ||
744 | fn test_method(&self, test: i32); | ||
745 | } | ||
746 | pub struct TestStruct {} | ||
747 | impl TestTrait for TestStruct { | ||
748 | fn test_method(&self, test: i32) {} | ||
749 | } | ||
750 | } | ||
751 | |||
752 | fn main() { | ||
753 | let test_struct = test_mod::TestStruct {}; | ||
754 | test_mod::TestTrait::test_method(&test_struct, 42) | ||
755 | } | ||
756 | ", | ||
757 | ); | ||
758 | } | ||
759 | |||
760 | #[test] | ||
761 | fn trait_method_consume() { | ||
762 | check_assist( | ||
763 | qualify_path, | ||
764 | r" | ||
765 | mod test_mod { | ||
766 | pub trait TestTrait { | ||
767 | fn test_method(self); | ||
768 | } | ||
769 | pub struct TestStruct {} | ||
770 | impl TestTrait for TestStruct { | ||
771 | fn test_method(self) {} | ||
772 | } | ||
773 | } | ||
774 | |||
775 | fn main() { | ||
776 | let test_struct = test_mod::TestStruct {}; | ||
777 | test_struct.test_meth$0od() | ||
778 | } | ||
779 | ", | ||
780 | r" | ||
781 | mod test_mod { | ||
782 | pub trait TestTrait { | ||
783 | fn test_method(self); | ||
784 | } | ||
785 | pub struct TestStruct {} | ||
786 | impl TestTrait for TestStruct { | ||
787 | fn test_method(self) {} | ||
788 | } | ||
789 | } | ||
790 | |||
791 | fn main() { | ||
792 | let test_struct = test_mod::TestStruct {}; | ||
793 | test_mod::TestTrait::test_method(test_struct) | ||
794 | } | ||
795 | ", | ||
796 | ); | ||
797 | } | ||
798 | |||
799 | #[test] | ||
800 | fn trait_method_cross_crate() { | ||
801 | check_assist( | ||
802 | qualify_path, | ||
803 | r" | ||
804 | //- /main.rs crate:main deps:dep | ||
805 | fn main() { | ||
806 | let test_struct = dep::test_mod::TestStruct {}; | ||
807 | test_struct.test_meth$0od() | ||
808 | } | ||
809 | //- /dep.rs crate:dep | ||
810 | pub mod test_mod { | ||
811 | pub trait TestTrait { | ||
812 | fn test_method(&self); | ||
813 | } | ||
814 | pub struct TestStruct {} | ||
815 | impl TestTrait for TestStruct { | ||
816 | fn test_method(&self) {} | ||
817 | } | ||
818 | } | ||
819 | ", | ||
820 | r" | ||
821 | fn main() { | ||
822 | let test_struct = dep::test_mod::TestStruct {}; | ||
823 | dep::test_mod::TestTrait::test_method(&test_struct) | ||
824 | } | ||
825 | ", | ||
826 | ); | ||
827 | } | ||
828 | |||
829 | #[test] | ||
830 | fn assoc_fn_cross_crate() { | ||
831 | check_assist( | ||
832 | qualify_path, | ||
833 | r" | ||
834 | //- /main.rs crate:main deps:dep | ||
835 | fn main() { | ||
836 | dep::test_mod::TestStruct::test_func$0tion | ||
837 | } | ||
838 | //- /dep.rs crate:dep | ||
839 | pub mod test_mod { | ||
840 | pub trait TestTrait { | ||
841 | fn test_function(); | ||
842 | } | ||
843 | pub struct TestStruct {} | ||
844 | impl TestTrait for TestStruct { | ||
845 | fn test_function() {} | ||
846 | } | ||
847 | } | ||
848 | ", | ||
849 | r" | ||
850 | fn main() { | ||
851 | <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::test_function | ||
852 | } | ||
853 | ", | ||
854 | ); | ||
855 | } | ||
856 | |||
857 | #[test] | ||
858 | fn assoc_const_cross_crate() { | ||
859 | check_assist( | ||
860 | qualify_path, | ||
861 | r" | ||
862 | //- /main.rs crate:main deps:dep | ||
863 | fn main() { | ||
864 | dep::test_mod::TestStruct::CONST$0 | ||
865 | } | ||
866 | //- /dep.rs crate:dep | ||
867 | pub mod test_mod { | ||
868 | pub trait TestTrait { | ||
869 | const CONST: bool; | ||
870 | } | ||
871 | pub struct TestStruct {} | ||
872 | impl TestTrait for TestStruct { | ||
873 | const CONST: bool = true; | ||
874 | } | ||
875 | } | ||
876 | ", | ||
877 | r" | ||
878 | fn main() { | ||
879 | <dep::test_mod::TestStruct as dep::test_mod::TestTrait>::CONST | ||
880 | } | ||
881 | ", | ||
882 | ); | ||
883 | } | ||
884 | |||
885 | #[test] | ||
886 | fn assoc_fn_as_method_cross_crate() { | ||
887 | check_assist_not_applicable( | ||
888 | qualify_path, | ||
889 | r" | ||
890 | //- /main.rs crate:main deps:dep | ||
891 | fn main() { | ||
892 | let test_struct = dep::test_mod::TestStruct {}; | ||
893 | test_struct.test_func$0tion() | ||
894 | } | ||
895 | //- /dep.rs crate:dep | ||
896 | pub mod test_mod { | ||
897 | pub trait TestTrait { | ||
898 | fn test_function(); | ||
899 | } | ||
900 | pub struct TestStruct {} | ||
901 | impl TestTrait for TestStruct { | ||
902 | fn test_function() {} | ||
903 | } | ||
904 | } | ||
905 | ", | ||
906 | ); | ||
907 | } | ||
908 | |||
909 | #[test] | ||
910 | fn private_trait_cross_crate() { | ||
911 | check_assist_not_applicable( | ||
912 | qualify_path, | ||
913 | r" | ||
914 | //- /main.rs crate:main deps:dep | ||
915 | fn main() { | ||
916 | let test_struct = dep::test_mod::TestStruct {}; | ||
917 | test_struct.test_meth$0od() | ||
918 | } | ||
919 | //- /dep.rs crate:dep | ||
920 | pub mod test_mod { | ||
921 | trait TestTrait { | ||
922 | fn test_method(&self); | ||
923 | } | ||
924 | pub struct TestStruct {} | ||
925 | impl TestTrait for TestStruct { | ||
926 | fn test_method(&self) {} | ||
927 | } | ||
928 | } | ||
929 | ", | ||
930 | ); | ||
931 | } | ||
932 | |||
933 | #[test] | ||
934 | fn not_applicable_for_imported_trait_for_method() { | ||
935 | check_assist_not_applicable( | ||
936 | qualify_path, | ||
937 | r" | ||
938 | mod test_mod { | ||
939 | pub trait TestTrait { | ||
940 | fn test_method(&self); | ||
941 | } | ||
942 | pub trait TestTrait2 { | ||
943 | fn test_method(&self); | ||
944 | } | ||
945 | pub enum TestEnum { | ||
946 | One, | ||
947 | Two, | ||
948 | } | ||
949 | impl TestTrait2 for TestEnum { | ||
950 | fn test_method(&self) {} | ||
951 | } | ||
952 | impl TestTrait for TestEnum { | ||
953 | fn test_method(&self) {} | ||
954 | } | ||
955 | } | ||
956 | |||
957 | use test_mod::TestTrait2; | ||
958 | fn main() { | ||
959 | let one = test_mod::TestEnum::One; | ||
960 | one.test$0_method(); | ||
961 | } | ||
962 | ", | ||
963 | ) | ||
964 | } | ||
965 | |||
966 | #[test] | ||
967 | fn dep_import() { | ||
968 | check_assist( | ||
969 | qualify_path, | ||
970 | r" | ||
971 | //- /lib.rs crate:dep | ||
972 | pub struct Struct; | ||
973 | |||
974 | //- /main.rs crate:main deps:dep | ||
975 | fn main() { | ||
976 | Struct$0 | ||
977 | } | ||
978 | ", | ||
979 | r" | ||
980 | fn main() { | ||
981 | dep::Struct | ||
982 | } | ||
983 | ", | ||
984 | ); | ||
985 | } | ||
986 | |||
987 | #[test] | ||
988 | fn whole_segment() { | ||
989 | // Tests that only imports whose last segment matches the identifier get suggested. | ||
990 | check_assist( | ||
991 | qualify_path, | ||
992 | r" | ||
993 | //- /lib.rs crate:dep | ||
994 | pub mod fmt { | ||
995 | pub trait Display {} | ||
996 | } | ||
997 | |||
998 | pub fn panic_fmt() {} | ||
999 | |||
1000 | //- /main.rs crate:main deps:dep | ||
1001 | struct S; | ||
1002 | |||
1003 | impl f$0mt::Display for S {} | ||
1004 | ", | ||
1005 | r" | ||
1006 | struct S; | ||
1007 | |||
1008 | impl dep::fmt::Display for S {} | ||
1009 | ", | ||
1010 | ); | ||
1011 | } | ||
1012 | |||
1013 | #[test] | ||
1014 | fn macro_generated() { | ||
1015 | // Tests that macro-generated items are suggested from external crates. | ||
1016 | check_assist( | ||
1017 | qualify_path, | ||
1018 | r" | ||
1019 | //- /lib.rs crate:dep | ||
1020 | macro_rules! mac { | ||
1021 | () => { | ||
1022 | pub struct Cheese; | ||
1023 | }; | ||
1024 | } | ||
1025 | |||
1026 | mac!(); | ||
1027 | |||
1028 | //- /main.rs crate:main deps:dep | ||
1029 | fn main() { | ||
1030 | Cheese$0; | ||
1031 | } | ||
1032 | ", | ||
1033 | r" | ||
1034 | fn main() { | ||
1035 | dep::Cheese; | ||
1036 | } | ||
1037 | ", | ||
1038 | ); | ||
1039 | } | ||
1040 | |||
1041 | #[test] | ||
1042 | fn casing() { | ||
1043 | // Tests that differently cased names don't interfere and we only suggest the matching one. | ||
1044 | check_assist( | ||
1045 | qualify_path, | ||
1046 | r" | ||
1047 | //- /lib.rs crate:dep | ||
1048 | pub struct FMT; | ||
1049 | pub struct fmt; | ||
1050 | |||
1051 | //- /main.rs crate:main deps:dep | ||
1052 | fn main() { | ||
1053 | FMT$0; | ||
1054 | } | ||
1055 | ", | ||
1056 | r" | ||
1057 | fn main() { | ||
1058 | dep::FMT; | ||
1059 | } | ||
1060 | ", | ||
1061 | ); | ||
1062 | } | ||
1063 | |||
1064 | #[test] | ||
1065 | fn keep_generic_annotations() { | ||
1066 | check_assist( | ||
1067 | qualify_path, | ||
1068 | r" | ||
1069 | //- /lib.rs crate:dep | ||
1070 | pub mod generic { pub struct Thing<'a, T>(&'a T); } | ||
1071 | |||
1072 | //- /main.rs crate:main deps:dep | ||
1073 | fn foo() -> Thin$0g<'static, ()> {} | ||
1074 | |||
1075 | fn main() {} | ||
1076 | ", | ||
1077 | r" | ||
1078 | fn foo() -> dep::generic::Thing<'static, ()> {} | ||
1079 | |||
1080 | fn main() {} | ||
1081 | ", | ||
1082 | ); | ||
1083 | } | ||
1084 | |||
1085 | #[test] | ||
1086 | fn keep_generic_annotations_leading_colon() { | ||
1087 | check_assist( | ||
1088 | qualify_path, | ||
1089 | r" | ||
1090 | //- /lib.rs crate:dep | ||
1091 | pub mod generic { pub struct Thing<'a, T>(&'a T); } | ||
1092 | |||
1093 | //- /main.rs crate:main deps:dep | ||
1094 | fn foo() -> Thin$0g::<'static, ()> {} | ||
1095 | |||
1096 | fn main() {} | ||
1097 | ", | ||
1098 | r" | ||
1099 | fn foo() -> dep::generic::Thing::<'static, ()> {} | ||
1100 | |||
1101 | fn main() {} | ||
1102 | ", | ||
1103 | ); | ||
1104 | } | ||
1105 | |||
1106 | #[test] | ||
1107 | fn associated_struct_const_generic() { | ||
1108 | check_assist( | ||
1109 | qualify_path, | ||
1110 | r" | ||
1111 | mod test_mod { | ||
1112 | pub struct TestStruct<T> {} | ||
1113 | impl<T> TestStruct<T> { | ||
1114 | const TEST_CONST: u8 = 42; | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | fn main() { | ||
1119 | TestStruct::<()>::TEST_CONST$0 | ||
1120 | } | ||
1121 | ", | ||
1122 | r" | ||
1123 | mod test_mod { | ||
1124 | pub struct TestStruct<T> {} | ||
1125 | impl<T> TestStruct<T> { | ||
1126 | const TEST_CONST: u8 = 42; | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | fn main() { | ||
1131 | test_mod::TestStruct::<()>::TEST_CONST | ||
1132 | } | ||
1133 | ", | ||
1134 | ); | ||
1135 | } | ||
1136 | |||
1137 | #[test] | ||
1138 | fn associated_trait_const_generic() { | ||
1139 | check_assist( | ||
1140 | qualify_path, | ||
1141 | r" | ||
1142 | mod test_mod { | ||
1143 | pub trait TestTrait { | ||
1144 | const TEST_CONST: u8; | ||
1145 | } | ||
1146 | pub struct TestStruct<T> {} | ||
1147 | impl<T> TestTrait for TestStruct<T> { | ||
1148 | const TEST_CONST: u8 = 42; | ||
1149 | } | ||
1150 | } | ||
1151 | |||
1152 | fn main() { | ||
1153 | test_mod::TestStruct::<()>::TEST_CONST$0 | ||
1154 | } | ||
1155 | ", | ||
1156 | r" | ||
1157 | mod test_mod { | ||
1158 | pub trait TestTrait { | ||
1159 | const TEST_CONST: u8; | ||
1160 | } | ||
1161 | pub struct TestStruct<T> {} | ||
1162 | impl<T> TestTrait for TestStruct<T> { | ||
1163 | const TEST_CONST: u8 = 42; | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | fn main() { | ||
1168 | <test_mod::TestStruct::<()> as test_mod::TestTrait>::TEST_CONST | ||
1169 | } | ||
1170 | ", | ||
1171 | ); | ||
1172 | } | ||
1173 | |||
1174 | #[test] | ||
1175 | fn trait_method_generic() { | ||
1176 | check_assist( | ||
1177 | qualify_path, | ||
1178 | r" | ||
1179 | mod test_mod { | ||
1180 | pub trait TestTrait { | ||
1181 | fn test_method<T>(&self); | ||
1182 | } | ||
1183 | pub struct TestStruct {} | ||
1184 | impl TestTrait for TestStruct { | ||
1185 | fn test_method<T>(&self) {} | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | fn main() { | ||
1190 | let test_struct = test_mod::TestStruct {}; | ||
1191 | test_struct.test_meth$0od::<()>() | ||
1192 | } | ||
1193 | ", | ||
1194 | r" | ||
1195 | mod test_mod { | ||
1196 | pub trait TestTrait { | ||
1197 | fn test_method<T>(&self); | ||
1198 | } | ||
1199 | pub struct TestStruct {} | ||
1200 | impl TestTrait for TestStruct { | ||
1201 | fn test_method<T>(&self) {} | ||
1202 | } | ||
1203 | } | ||
1204 | |||
1205 | fn main() { | ||
1206 | let test_struct = test_mod::TestStruct {}; | ||
1207 | test_mod::TestTrait::test_method::<()>(&test_struct) | ||
1208 | } | ||
1209 | ", | ||
1210 | ); | ||
1211 | } | ||
1212 | } | ||