]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/flyimport.rs
Do not show flyimports in trait or impl declarations
[rust.git] / crates / ide_completion / src / completions / flyimport.rs
1 //! Feature: completion with imports-on-the-fly
2 //!
3 //! When completing names in the current scope, proposes additional imports from other modules or crates,
4 //! if they can be qualified in the scope and their name contains all symbols from the completion input.
5 //!
6 //! To be considered applicable, the name must contain all input symbols in the given order, not necessarily adjacent.
7 //! If any input symbol is not lowercased, the name must contain all symbols in exact case; otherwise the contaning is checked case-insensitively.
8 //!
9 //! ```
10 //! fn main() {
11 //!     pda$0
12 //! }
13 //! # pub mod std { pub mod marker { pub struct PhantomData { } } }
14 //! ```
15 //! ->
16 //! ```
17 //! use std::marker::PhantomData;
18 //!
19 //! fn main() {
20 //!     PhantomData
21 //! }
22 //! # pub mod std { pub mod marker { pub struct PhantomData { } } }
23 //! ```
24 //!
25 //! Also completes associated items, that require trait imports.
26 //! If any unresolved and/or partially-qualified path predeces the input, it will be taken into account.
27 //! Currently, only the imports with their import path ending with the whole qialifier will be proposed
28 //! (no fuzzy matching for qualifier).
29 //!
30 //! ```
31 //! mod foo {
32 //!     pub mod bar {
33 //!         pub struct Item;
34 //!
35 //!         impl Item {
36 //!             pub const TEST_ASSOC: usize = 3;
37 //!         }
38 //!     }
39 //! }
40 //!
41 //! fn main() {
42 //!     bar::Item::TEST_A$0
43 //! }
44 //! ```
45 //! ->
46 //! ```
47 //! use foo::bar;
48 //!
49 //! mod foo {
50 //!     pub mod bar {
51 //!         pub struct Item;
52 //!
53 //!         impl Item {
54 //!             pub const TEST_ASSOC: usize = 3;
55 //!         }
56 //!     }
57 //! }
58 //!
59 //! fn main() {
60 //!     bar::Item::TEST_ASSOC
61 //! }
62 //! ```
63 //!
64 //! NOTE: currently, if an assoc item comes from a trait that's not currently imported and it also has an unresolved and/or partially-qualified path,
65 //! no imports will be proposed.
66 //!
67 //! .Fuzzy search details
68 //!
69 //! To avoid an excessive amount of the results returned, completion input is checked for inclusion in the names only
70 //! (i.e. in `HashMap` in the `std::collections::HashMap` path).
71 //! For the same reasons, avoids searching for any path imports for inputs with their length less that 2 symbols
72 //! (but shows all associated items for any input length).
73 //!
74 //! .Import configuration
75 //!
76 //! It is possible to configure how use-trees are merged with the `importMergeBehavior` setting.
77 //! Mimics the corresponding behavior of the `Auto Import` feature.
78 //!
79 //! .LSP and performance implications
80 //!
81 //! The feature is enabled only if the LSP client supports LSP protocol version 3.16+ and reports the `additionalTextEdits`
82 //! (case sensitive) resolve client capability in its client capabilities.
83 //! This way the server is able to defer the costly computations, doing them for a selected completion item only.
84 //! For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones,
85 //! which might be slow ergo the feature is automatically disabled.
86 //!
87 //! .Feature toggle
88 //!
89 //! The feature can be forcefully turned off in the settings with the `rust-analyzer.completion.enableAutoimportCompletions` flag.
90 //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding
91 //! capability enabled.
92
93 use hir::ModPath;
94 use ide_db::helpers::{
95     import_assets::{ImportAssets, ImportCandidate},
96     insert_use::ImportScope,
97 };
98 use itertools::Itertools;
99 use syntax::{AstNode, SyntaxNode, T};
100
101 use crate::{
102     context::CompletionContext,
103     render::{render_resolution_with_import, RenderContext},
104     ImportEdit,
105 };
106
107 use super::Completions;
108
109 pub(crate) fn import_on_the_fly(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
110     if !ctx.config.enable_imports_on_the_fly {
111         return None;
112     }
113     if ctx.use_item_syntax.is_some()
114         || ctx.attribute_under_caret.is_some()
115         || ctx.mod_declaration_under_caret.is_some()
116         || ctx.record_lit_syntax.is_some()
117         || ctx.has_trait_parent
118         || ctx.has_impl_parent
119     {
120         return None;
121     }
122     let potential_import_name = {
123         let token_kind = ctx.token.kind();
124         if matches!(token_kind, T![.] | T![::]) {
125             String::new()
126         } else {
127             ctx.token.to_string()
128         }
129     };
130
131     let _p = profile::span("import_on_the_fly").detail(|| potential_import_name.to_string());
132
133     let user_input_lowercased = potential_import_name.to_lowercase();
134     let import_assets = import_assets(ctx, potential_import_name)?;
135     let import_scope = ImportScope::find_insert_use_container(
136         position_for_import(ctx, Some(import_assets.import_candidate()))?,
137         &ctx.sema,
138     )?;
139
140     acc.add_all(
141         import_assets
142             .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
143             .into_iter()
144             .sorted_by_key(|located_import| {
145                 compute_fuzzy_completion_order_key(
146                     &located_import.import_path,
147                     &user_input_lowercased,
148                 )
149             })
150             .filter_map(|import| {
151                 render_resolution_with_import(
152                     RenderContext::new(ctx),
153                     ImportEdit { import, scope: import_scope.clone() },
154                 )
155             }),
156     );
157     Some(())
158 }
159
160 pub(crate) fn position_for_import<'a>(
161     ctx: &'a CompletionContext,
162     import_candidate: Option<&ImportCandidate>,
163 ) -> Option<&'a SyntaxNode> {
164     Some(match import_candidate {
165         Some(ImportCandidate::Path(_)) => ctx.name_ref_syntax.as_ref()?.syntax(),
166         Some(ImportCandidate::TraitAssocItem(_)) => ctx.path_qual.as_ref()?.syntax(),
167         Some(ImportCandidate::TraitMethod(_)) => ctx.dot_receiver.as_ref()?.syntax(),
168         None => ctx
169             .name_ref_syntax
170             .as_ref()
171             .map(|name_ref| name_ref.syntax())
172             .or_else(|| ctx.path_qual.as_ref().map(|path| path.syntax()))
173             .or_else(|| ctx.dot_receiver.as_ref().map(|expr| expr.syntax()))?,
174     })
175 }
176
177 fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
178     let current_module = ctx.scope.module()?;
179     if let Some(dot_receiver) = &ctx.dot_receiver {
180         ImportAssets::for_fuzzy_method_call(
181             current_module,
182             ctx.sema.type_of_expr(dot_receiver)?,
183             fuzzy_name,
184             dot_receiver.syntax().clone(),
185         )
186     } else {
187         let fuzzy_name_length = fuzzy_name.len();
188         let approximate_node = match current_module.definition_source(ctx.db).value {
189             hir::ModuleSource::SourceFile(s) => s.syntax().clone(),
190             hir::ModuleSource::Module(m) => m.syntax().clone(),
191             hir::ModuleSource::BlockExpr(b) => b.syntax().clone(),
192         };
193         let assets_for_path = ImportAssets::for_fuzzy_path(
194             current_module,
195             ctx.path_qual.clone(),
196             fuzzy_name,
197             &ctx.sema,
198             approximate_node,
199         )?;
200
201         if matches!(assets_for_path.import_candidate(), ImportCandidate::Path(_))
202             && fuzzy_name_length < 2
203         {
204             cov_mark::hit!(ignore_short_input_for_path);
205             None
206         } else {
207             Some(assets_for_path)
208         }
209     }
210 }
211
212 fn compute_fuzzy_completion_order_key(
213     proposed_mod_path: &ModPath,
214     user_input_lowercased: &str,
215 ) -> usize {
216     cov_mark::hit!(certain_fuzzy_order_test);
217     let import_name = match proposed_mod_path.segments().last() {
218         Some(name) => name.to_string().to_lowercase(),
219         None => return usize::MAX,
220     };
221     match import_name.match_indices(user_input_lowercased).next() {
222         Some((first_matching_index, _)) => first_matching_index,
223         None => usize::MAX,
224     }
225 }
226
227 #[cfg(test)]
228 mod tests {
229     use expect_test::{expect, Expect};
230
231     use crate::{
232         item::CompletionKind,
233         test_utils::{check_edit, check_edit_with_config, completion_list, TEST_CONFIG},
234     };
235
236     fn check(ra_fixture: &str, expect: Expect) {
237         let actual = completion_list(ra_fixture, CompletionKind::Magic);
238         expect.assert_eq(&actual);
239     }
240
241     #[test]
242     fn function_fuzzy_completion() {
243         check_edit(
244             "stdin",
245             r#"
246 //- /lib.rs crate:dep
247 pub mod io {
248     pub fn stdin() {}
249 };
250
251 //- /main.rs crate:main deps:dep
252 fn main() {
253     stdi$0
254 }
255 "#,
256             r#"
257 use dep::io::stdin;
258
259 fn main() {
260     stdin()$0
261 }
262 "#,
263         );
264     }
265
266     #[test]
267     fn macro_fuzzy_completion() {
268         check_edit(
269             "macro_with_curlies!",
270             r#"
271 //- /lib.rs crate:dep
272 /// Please call me as macro_with_curlies! {}
273 #[macro_export]
274 macro_rules! macro_with_curlies {
275     () => {}
276 }
277
278 //- /main.rs crate:main deps:dep
279 fn main() {
280     curli$0
281 }
282 "#,
283             r#"
284 use dep::macro_with_curlies;
285
286 fn main() {
287     macro_with_curlies! {$0}
288 }
289 "#,
290         );
291     }
292
293     #[test]
294     fn struct_fuzzy_completion() {
295         check_edit(
296             "ThirdStruct",
297             r#"
298 //- /lib.rs crate:dep
299 pub struct FirstStruct;
300 pub mod some_module {
301     pub struct SecondStruct;
302     pub struct ThirdStruct;
303 }
304
305 //- /main.rs crate:main deps:dep
306 use dep::{FirstStruct, some_module::SecondStruct};
307
308 fn main() {
309     this$0
310 }
311 "#,
312             r#"
313 use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};
314
315 fn main() {
316     ThirdStruct
317 }
318 "#,
319         );
320     }
321
322     #[test]
323     fn short_paths_are_ignored() {
324         cov_mark::check!(ignore_short_input_for_path);
325
326         check(
327             r#"
328 //- /lib.rs crate:dep
329 pub struct FirstStruct;
330 pub mod some_module {
331     pub struct SecondStruct;
332     pub struct ThirdStruct;
333 }
334
335 //- /main.rs crate:main deps:dep
336 use dep::{FirstStruct, some_module::SecondStruct};
337
338 fn main() {
339     t$0
340 }
341 "#,
342             expect![[r#""#]],
343         );
344     }
345
346     #[test]
347     fn fuzzy_completions_come_in_specific_order() {
348         cov_mark::check!(certain_fuzzy_order_test);
349         check(
350             r#"
351 //- /lib.rs crate:dep
352 pub struct FirstStruct;
353 pub mod some_module {
354     // already imported, omitted
355     pub struct SecondStruct;
356     // does not contain all letters from the query, omitted
357     pub struct UnrelatedOne;
358     // contains all letters from the query, but not in sequence, displayed last
359     pub struct ThiiiiiirdStruct;
360     // contains all letters from the query, but not in the beginning, displayed second
361     pub struct AfterThirdStruct;
362     // contains all letters from the query in the begginning, displayed first
363     pub struct ThirdStruct;
364 }
365
366 //- /main.rs crate:main deps:dep
367 use dep::{FirstStruct, some_module::SecondStruct};
368
369 fn main() {
370     hir$0
371 }
372 "#,
373             expect![[r#"
374                 st dep::some_module::ThirdStruct
375                 st dep::some_module::AfterThirdStruct
376                 st dep::some_module::ThiiiiiirdStruct
377             "#]],
378         );
379     }
380
381     #[test]
382     fn trait_function_fuzzy_completion() {
383         let fixture = r#"
384         //- /lib.rs crate:dep
385         pub mod test_mod {
386             pub trait TestTrait {
387                 const SPECIAL_CONST: u8;
388                 type HumbleType;
389                 fn weird_function();
390                 fn random_method(&self);
391             }
392             pub struct TestStruct {}
393             impl TestTrait for TestStruct {
394                 const SPECIAL_CONST: u8 = 42;
395                 type HumbleType = ();
396                 fn weird_function() {}
397                 fn random_method(&self) {}
398             }
399         }
400
401         //- /main.rs crate:main deps:dep
402         fn main() {
403             dep::test_mod::TestStruct::wei$0
404         }
405         "#;
406
407         check(
408             fixture,
409             expect![[r#"
410                 fn weird_function() (dep::test_mod::TestTrait) fn()
411             "#]],
412         );
413
414         check_edit(
415             "weird_function",
416             fixture,
417             r#"
418 use dep::test_mod::TestTrait;
419
420 fn main() {
421     dep::test_mod::TestStruct::weird_function()$0
422 }
423 "#,
424         );
425     }
426
427     #[test]
428     fn trait_const_fuzzy_completion() {
429         let fixture = r#"
430         //- /lib.rs crate:dep
431         pub mod test_mod {
432             pub trait TestTrait {
433                 const SPECIAL_CONST: u8;
434                 type HumbleType;
435                 fn weird_function();
436                 fn random_method(&self);
437             }
438             pub struct TestStruct {}
439             impl TestTrait for TestStruct {
440                 const SPECIAL_CONST: u8 = 42;
441                 type HumbleType = ();
442                 fn weird_function() {}
443                 fn random_method(&self) {}
444             }
445         }
446
447         //- /main.rs crate:main deps:dep
448         fn main() {
449             dep::test_mod::TestStruct::spe$0
450         }
451         "#;
452
453         check(
454             fixture,
455             expect![[r#"
456             ct SPECIAL_CONST (dep::test_mod::TestTrait)
457         "#]],
458         );
459
460         check_edit(
461             "SPECIAL_CONST",
462             fixture,
463             r#"
464 use dep::test_mod::TestTrait;
465
466 fn main() {
467     dep::test_mod::TestStruct::SPECIAL_CONST
468 }
469 "#,
470         );
471     }
472
473     #[test]
474     fn trait_method_fuzzy_completion() {
475         let fixture = r#"
476         //- /lib.rs crate:dep
477         pub mod test_mod {
478             pub trait TestTrait {
479                 const SPECIAL_CONST: u8;
480                 type HumbleType;
481                 fn weird_function();
482                 fn random_method(&self);
483             }
484             pub struct TestStruct {}
485             impl TestTrait for TestStruct {
486                 const SPECIAL_CONST: u8 = 42;
487                 type HumbleType = ();
488                 fn weird_function() {}
489                 fn random_method(&self) {}
490             }
491         }
492
493         //- /main.rs crate:main deps:dep
494         fn main() {
495             let test_struct = dep::test_mod::TestStruct {};
496             test_struct.ran$0
497         }
498         "#;
499
500         check(
501             fixture,
502             expect![[r#"
503                 me random_method() (dep::test_mod::TestTrait) fn(&self)
504             "#]],
505         );
506
507         check_edit(
508             "random_method",
509             fixture,
510             r#"
511 use dep::test_mod::TestTrait;
512
513 fn main() {
514     let test_struct = dep::test_mod::TestStruct {};
515     test_struct.random_method()$0
516 }
517 "#,
518         );
519     }
520
521     #[test]
522     fn no_trait_type_fuzzy_completion() {
523         check(
524             r#"
525 //- /lib.rs crate:dep
526 pub mod test_mod {
527     pub trait TestTrait {
528         const SPECIAL_CONST: u8;
529         type HumbleType;
530         fn weird_function();
531         fn random_method(&self);
532     }
533     pub struct TestStruct {}
534     impl TestTrait for TestStruct {
535         const SPECIAL_CONST: u8 = 42;
536         type HumbleType = ();
537         fn weird_function() {}
538         fn random_method(&self) {}
539     }
540 }
541
542 //- /main.rs crate:main deps:dep
543 fn main() {
544     dep::test_mod::TestStruct::hum$0
545 }
546 "#,
547             expect![[r#""#]],
548         );
549     }
550
551     #[test]
552     fn does_not_propose_names_in_scope() {
553         check(
554             r#"
555 //- /lib.rs crate:dep
556 pub mod test_mod {
557     pub trait TestTrait {
558         const SPECIAL_CONST: u8;
559         type HumbleType;
560         fn weird_function();
561         fn random_method(&self);
562     }
563     pub struct TestStruct {}
564     impl TestTrait for TestStruct {
565         const SPECIAL_CONST: u8 = 42;
566         type HumbleType = ();
567         fn weird_function() {}
568         fn random_method(&self) {}
569     }
570 }
571
572 //- /main.rs crate:main deps:dep
573 use dep::test_mod::TestStruct;
574 fn main() {
575     TestSt$0
576 }
577 "#,
578             expect![[r#""#]],
579         );
580     }
581
582     #[test]
583     fn does_not_propose_traits_in_scope() {
584         check(
585             r#"
586 //- /lib.rs crate:dep
587 pub mod test_mod {
588     pub trait TestTrait {
589         const SPECIAL_CONST: u8;
590         type HumbleType;
591         fn weird_function();
592         fn random_method(&self);
593     }
594     pub struct TestStruct {}
595     impl TestTrait for TestStruct {
596         const SPECIAL_CONST: u8 = 42;
597         type HumbleType = ();
598         fn weird_function() {}
599         fn random_method(&self) {}
600     }
601 }
602
603 //- /main.rs crate:main deps:dep
604 use dep::test_mod::{TestStruct, TestTrait};
605 fn main() {
606     dep::test_mod::TestStruct::hum$0
607 }
608 "#,
609             expect![[r#""#]],
610         );
611     }
612
613     #[test]
614     fn blanket_trait_impl_import() {
615         check_edit(
616             "another_function",
617             r#"
618 //- /lib.rs crate:dep
619 pub mod test_mod {
620     pub struct TestStruct {}
621     pub trait TestTrait {
622         fn another_function();
623     }
624     impl<T> TestTrait for T {
625         fn another_function() {}
626     }
627 }
628
629 //- /main.rs crate:main deps:dep
630 fn main() {
631     dep::test_mod::TestStruct::ano$0
632 }
633 "#,
634             r#"
635 use dep::test_mod::TestTrait;
636
637 fn main() {
638     dep::test_mod::TestStruct::another_function()$0
639 }
640 "#,
641         );
642     }
643
644     #[test]
645     fn zero_input_deprecated_assoc_item_completion() {
646         check(
647             r#"
648 //- /lib.rs crate:dep
649 pub mod test_mod {
650     #[deprecated]
651     pub trait TestTrait {
652         const SPECIAL_CONST: u8;
653         type HumbleType;
654         fn weird_function();
655         fn random_method(&self);
656     }
657     pub struct TestStruct {}
658     impl TestTrait for TestStruct {
659         const SPECIAL_CONST: u8 = 42;
660         type HumbleType = ();
661         fn weird_function() {}
662         fn random_method(&self) {}
663     }
664 }
665
666 //- /main.rs crate:main deps:dep
667 fn main() {
668     let test_struct = dep::test_mod::TestStruct {};
669     test_struct.$0
670 }
671         "#,
672             expect![[r#"
673                 me random_method() (dep::test_mod::TestTrait) fn(&self) DEPRECATED
674             "#]],
675         );
676
677         check(
678             r#"
679 //- /lib.rs crate:dep
680 pub mod test_mod {
681     #[deprecated]
682     pub trait TestTrait {
683         const SPECIAL_CONST: u8;
684         type HumbleType;
685         fn weird_function();
686         fn random_method(&self);
687     }
688     pub struct TestStruct {}
689     impl TestTrait for TestStruct {
690         const SPECIAL_CONST: u8 = 42;
691         type HumbleType = ();
692         fn weird_function() {}
693         fn random_method(&self) {}
694     }
695 }
696
697 //- /main.rs crate:main deps:dep
698 fn main() {
699     dep::test_mod::TestStruct::$0
700 }
701 "#,
702             expect![[r#"
703                 ct SPECIAL_CONST (dep::test_mod::TestTrait) DEPRECATED
704                 fn weird_function() (dep::test_mod::TestTrait) fn() DEPRECATED
705             "#]],
706         );
707     }
708
709     #[test]
710     fn no_completions_in_use_statements() {
711         check(
712             r#"
713 //- /lib.rs crate:dep
714 pub mod io {
715     pub fn stdin() {}
716 };
717
718 //- /main.rs crate:main deps:dep
719 use stdi$0
720
721 fn main() {}
722 "#,
723             expect![[]],
724         );
725     }
726
727     #[test]
728     fn prefix_config_usage() {
729         let fixture = r#"
730 mod foo {
731     pub mod bar {
732         pub struct Item;
733     }
734 }
735
736 use crate::foo::bar;
737
738 fn main() {
739     Ite$0
740 }"#;
741         let mut config = TEST_CONFIG;
742
743         config.insert_use.prefix_kind = hir::PrefixKind::ByCrate;
744         check_edit_with_config(
745             config.clone(),
746             "Item",
747             fixture,
748             r#"
749 mod foo {
750     pub mod bar {
751         pub struct Item;
752     }
753 }
754
755 use crate::foo::bar::{self, Item};
756
757 fn main() {
758     Item
759 }"#,
760         );
761
762         config.insert_use.prefix_kind = hir::PrefixKind::BySelf;
763         check_edit_with_config(
764             config.clone(),
765             "Item",
766             fixture,
767             r#"
768 mod foo {
769     pub mod bar {
770         pub struct Item;
771     }
772 }
773
774 use crate::foo::bar;
775
776 use self::foo::bar::Item;
777
778 fn main() {
779     Item
780 }"#,
781         );
782
783         config.insert_use.prefix_kind = hir::PrefixKind::Plain;
784         check_edit_with_config(
785             config,
786             "Item",
787             fixture,
788             r#"
789 mod foo {
790     pub mod bar {
791         pub struct Item;
792     }
793 }
794
795 use foo::bar::Item;
796
797 use crate::foo::bar;
798
799 fn main() {
800     Item
801 }"#,
802         );
803     }
804
805     #[test]
806     fn unresolved_qualifier() {
807         let fixture = r#"
808 mod foo {
809     pub mod bar {
810         pub mod baz {
811             pub struct Item;
812         }
813     }
814 }
815
816 fn main() {
817     bar::baz::Ite$0
818 }"#;
819
820         check(
821             fixture,
822             expect![[r#"
823         st foo::bar::baz::Item
824         "#]],
825         );
826
827         check_edit(
828             "Item",
829             fixture,
830             r#"
831         use foo::bar;
832
833         mod foo {
834             pub mod bar {
835                 pub mod baz {
836                     pub struct Item;
837                 }
838             }
839         }
840
841         fn main() {
842             bar::baz::Item
843         }"#,
844         );
845     }
846
847     #[test]
848     fn unresolved_assoc_item_container() {
849         let fixture = r#"
850 mod foo {
851     pub struct Item;
852
853     impl Item {
854         pub const TEST_ASSOC: usize = 3;
855     }
856 }
857
858 fn main() {
859     Item::TEST_A$0
860 }"#;
861
862         check(
863             fixture,
864             expect![[r#"
865         ct TEST_ASSOC (foo::Item)
866         "#]],
867         );
868
869         check_edit(
870             "TEST_ASSOC",
871             fixture,
872             r#"
873 use foo::Item;
874
875 mod foo {
876     pub struct Item;
877
878     impl Item {
879         pub const TEST_ASSOC: usize = 3;
880     }
881 }
882
883 fn main() {
884     Item::TEST_ASSOC
885 }"#,
886         );
887     }
888
889     #[test]
890     fn unresolved_assoc_item_container_with_path() {
891         let fixture = r#"
892 mod foo {
893     pub mod bar {
894         pub struct Item;
895
896         impl Item {
897             pub const TEST_ASSOC: usize = 3;
898         }
899     }
900 }
901
902 fn main() {
903     bar::Item::TEST_A$0
904 }"#;
905
906         check(
907             fixture,
908             expect![[r#"
909         ct TEST_ASSOC (foo::bar::Item)
910     "#]],
911         );
912
913         check_edit(
914             "TEST_ASSOC",
915             fixture,
916             r#"
917 use foo::bar;
918
919 mod foo {
920     pub mod bar {
921         pub struct Item;
922
923         impl Item {
924             pub const TEST_ASSOC: usize = 3;
925         }
926     }
927 }
928
929 fn main() {
930     bar::Item::TEST_ASSOC
931 }"#,
932         );
933     }
934
935     #[test]
936     fn fuzzy_unresolved_path() {
937         check(
938             r#"
939 mod foo {
940     pub mod bar {
941         pub struct Item;
942
943         impl Item {
944             pub const TEST_ASSOC: usize = 3;
945         }
946     }
947 }
948
949 fn main() {
950     bar::ASS$0
951 }"#,
952             expect![[]],
953         )
954     }
955
956     #[test]
957     fn unqualified_assoc_items_are_omitted() {
958         check(
959             r#"
960 mod something {
961     pub trait BaseTrait {
962         fn test_function() -> i32;
963     }
964
965     pub struct Item1;
966     pub struct Item2;
967
968     impl BaseTrait for Item1 {
969         fn test_function() -> i32 {
970             1
971         }
972     }
973
974     impl BaseTrait for Item2 {
975         fn test_function() -> i32 {
976             2
977         }
978     }
979 }
980
981 fn main() {
982     test_f$0
983 }"#,
984             expect![[]],
985         )
986     }
987
988     #[test]
989     fn case_matters() {
990         check(
991             r#"
992 mod foo {
993     pub const TEST_CONST: usize = 3;
994     pub fn test_function() -> i32 {
995         4
996     }
997 }
998
999 fn main() {
1000     TE$0
1001 }"#,
1002             expect![[r#"
1003         ct foo::TEST_CONST
1004     "#]],
1005         );
1006
1007         check(
1008             r#"
1009 mod foo {
1010     pub const TEST_CONST: usize = 3;
1011     pub fn test_function() -> i32 {
1012         4
1013     }
1014 }
1015
1016 fn main() {
1017     te$0
1018 }"#,
1019             expect![[r#"
1020         ct foo::TEST_CONST
1021         fn test_function() (foo::test_function) fn() -> i32
1022     "#]],
1023         );
1024
1025         check(
1026             r#"
1027 mod foo {
1028     pub const TEST_CONST: usize = 3;
1029     pub fn test_function() -> i32 {
1030         4
1031     }
1032 }
1033
1034 fn main() {
1035     Te$0
1036 }"#,
1037             expect![[]],
1038         );
1039     }
1040
1041     #[test]
1042     fn no_fuzzy_during_fields_of_record_lit_syntax() {
1043         check(
1044             r#"
1045 mod m {
1046     pub fn some_fn() -> i32 {
1047         42
1048     }
1049 }
1050 struct Foo {
1051     some_field: i32,
1052 }
1053 fn main() {
1054     let _ = Foo { so$0 };
1055 }
1056 "#,
1057             expect![[]],
1058         );
1059     }
1060
1061     #[test]
1062     fn fuzzy_after_fields_of_record_lit_syntax() {
1063         check(
1064             r#"
1065 mod m {
1066     pub fn some_fn() -> i32 {
1067         42
1068     }
1069 }
1070 struct Foo {
1071     some_field: i32,
1072 }
1073 fn main() {
1074     let _ = Foo { some_field: so$0 };
1075 }
1076 "#,
1077             expect![[r#"
1078                 fn some_fn() (m::some_fn) fn() -> i32
1079             "#]],
1080         );
1081     }
1082
1083     #[test]
1084     fn no_flyimports_in_traits_and_impl_declarations() {
1085         check(
1086             r#"
1087 mod m {
1088     pub fn some_fn() -> i32 {
1089         42
1090     }
1091 }
1092 trait Foo {
1093     som$0
1094 }
1095 "#,
1096             expect![[r#""#]],
1097         );
1098
1099         check(
1100             r#"
1101 mod m {
1102     pub fn some_fn() -> i32 {
1103         42
1104     }
1105 }
1106 struct Foo;
1107 impl Foo {
1108     som$0
1109 }
1110 "#,
1111             expect![[r#""#]],
1112         );
1113
1114         check(
1115             r#"
1116 mod m {
1117     pub fn some_fn() -> i32 {
1118         42
1119     }
1120 }
1121 struct Foo;
1122 trait Bar {}
1123 impl Bar for Foo {
1124     som$0
1125 }
1126 "#,
1127             expect![[r#""#]],
1128         );
1129     }
1130 }