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