]> git.lizzy.rs Git - rust.git/blob - crates/ide_completion/src/completions/flyimport.rs
simplify
[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() || ctx.is_path_disallowed() {
114         return None;
115     }
116     let potential_import_name = {
117         let token_kind = ctx.token.kind();
118         if matches!(token_kind, T![.] | T![::]) {
119             String::new()
120         } else {
121             ctx.token.to_string()
122         }
123     };
124
125     let _p = profile::span("import_on_the_fly").detail(|| potential_import_name.to_string());
126
127     let user_input_lowercased = potential_import_name.to_lowercase();
128     let import_assets = import_assets(ctx, potential_import_name)?;
129     let import_scope = ImportScope::find_insert_use_container_with_macros(
130         position_for_import(ctx, Some(import_assets.import_candidate()))?,
131         &ctx.sema,
132     )?;
133
134     acc.add_all(
135         import_assets
136             .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
137             .into_iter()
138             .sorted_by_key(|located_import| {
139                 compute_fuzzy_completion_order_key(
140                     &located_import.import_path,
141                     &user_input_lowercased,
142                 )
143             })
144             .filter_map(|import| {
145                 render_resolution_with_import(
146                     RenderContext::new(ctx),
147                     ImportEdit { import, scope: import_scope.clone() },
148                 )
149             }),
150     );
151     Some(())
152 }
153
154 pub(crate) fn position_for_import<'a>(
155     ctx: &'a CompletionContext,
156     import_candidate: Option<&ImportCandidate>,
157 ) -> Option<&'a SyntaxNode> {
158     Some(match import_candidate {
159         Some(ImportCandidate::Path(_)) => ctx.name_ref_syntax.as_ref()?.syntax(),
160         Some(ImportCandidate::TraitAssocItem(_)) => ctx.path_qual.as_ref()?.syntax(),
161         Some(ImportCandidate::TraitMethod(_)) => ctx.dot_receiver.as_ref()?.syntax(),
162         None => ctx
163             .name_ref_syntax
164             .as_ref()
165             .map(|name_ref| name_ref.syntax())
166             .or_else(|| ctx.path_qual.as_ref().map(|path| path.syntax()))
167             .or_else(|| ctx.dot_receiver.as_ref().map(|expr| expr.syntax()))?,
168     })
169 }
170
171 fn import_assets(ctx: &CompletionContext, fuzzy_name: String) -> Option<ImportAssets> {
172     let current_module = ctx.scope.module()?;
173     if let Some(dot_receiver) = &ctx.dot_receiver {
174         ImportAssets::for_fuzzy_method_call(
175             current_module,
176             ctx.sema.type_of_expr(dot_receiver)?,
177             fuzzy_name,
178             dot_receiver.syntax().clone(),
179         )
180     } else {
181         let fuzzy_name_length = fuzzy_name.len();
182         let approximate_node = match current_module.definition_source(ctx.db).value {
183             hir::ModuleSource::SourceFile(s) => s.syntax().clone(),
184             hir::ModuleSource::Module(m) => m.syntax().clone(),
185             hir::ModuleSource::BlockExpr(b) => b.syntax().clone(),
186         };
187         let assets_for_path = ImportAssets::for_fuzzy_path(
188             current_module,
189             ctx.path_qual.clone(),
190             fuzzy_name,
191             &ctx.sema,
192             approximate_node,
193         )?;
194
195         if matches!(assets_for_path.import_candidate(), ImportCandidate::Path(_))
196             && fuzzy_name_length < 2
197         {
198             cov_mark::hit!(ignore_short_input_for_path);
199             None
200         } else {
201             Some(assets_for_path)
202         }
203     }
204 }
205
206 fn compute_fuzzy_completion_order_key(
207     proposed_mod_path: &ModPath,
208     user_input_lowercased: &str,
209 ) -> usize {
210     cov_mark::hit!(certain_fuzzy_order_test);
211     let import_name = match proposed_mod_path.segments().last() {
212         Some(name) => name.to_string().to_lowercase(),
213         None => return usize::MAX,
214     };
215     match import_name.match_indices(user_input_lowercased).next() {
216         Some((first_matching_index, _)) => first_matching_index,
217         None => usize::MAX,
218     }
219 }
220
221 #[cfg(test)]
222 mod tests {
223     use expect_test::{expect, Expect};
224
225     use crate::{
226         item::CompletionKind,
227         test_utils::{check_edit, check_edit_with_config, completion_list, TEST_CONFIG},
228     };
229
230     fn check(ra_fixture: &str, expect: Expect) {
231         let actual = completion_list(ra_fixture, CompletionKind::Magic);
232         expect.assert_eq(&actual);
233     }
234
235     #[test]
236     fn function_fuzzy_completion() {
237         check_edit(
238             "stdin",
239             r#"
240 //- /lib.rs crate:dep
241 pub mod io {
242     pub fn stdin() {}
243 };
244
245 //- /main.rs crate:main deps:dep
246 fn main() {
247     stdi$0
248 }
249 "#,
250             r#"
251 use dep::io::stdin;
252
253 fn main() {
254     stdin()$0
255 }
256 "#,
257         );
258     }
259
260     #[test]
261     fn macro_fuzzy_completion() {
262         check_edit(
263             "macro_with_curlies!",
264             r#"
265 //- /lib.rs crate:dep
266 /// Please call me as macro_with_curlies! {}
267 #[macro_export]
268 macro_rules! macro_with_curlies {
269     () => {}
270 }
271
272 //- /main.rs crate:main deps:dep
273 fn main() {
274     curli$0
275 }
276 "#,
277             r#"
278 use dep::macro_with_curlies;
279
280 fn main() {
281     macro_with_curlies! {$0}
282 }
283 "#,
284         );
285     }
286
287     #[test]
288     fn struct_fuzzy_completion() {
289         check_edit(
290             "ThirdStruct",
291             r#"
292 //- /lib.rs crate:dep
293 pub struct FirstStruct;
294 pub mod some_module {
295     pub struct SecondStruct;
296     pub struct ThirdStruct;
297 }
298
299 //- /main.rs crate:main deps:dep
300 use dep::{FirstStruct, some_module::SecondStruct};
301
302 fn main() {
303     this$0
304 }
305 "#,
306             r#"
307 use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};
308
309 fn main() {
310     ThirdStruct
311 }
312 "#,
313         );
314     }
315
316     #[test]
317     fn short_paths_are_ignored() {
318         cov_mark::check!(ignore_short_input_for_path);
319
320         check(
321             r#"
322 //- /lib.rs crate:dep
323 pub struct FirstStruct;
324 pub mod some_module {
325     pub struct SecondStruct;
326     pub struct ThirdStruct;
327 }
328
329 //- /main.rs crate:main deps:dep
330 use dep::{FirstStruct, some_module::SecondStruct};
331
332 fn main() {
333     t$0
334 }
335 "#,
336             expect![[r#""#]],
337         );
338     }
339
340     #[test]
341     fn fuzzy_completions_come_in_specific_order() {
342         cov_mark::check!(certain_fuzzy_order_test);
343         check(
344             r#"
345 //- /lib.rs crate:dep
346 pub struct FirstStruct;
347 pub mod some_module {
348     // already imported, omitted
349     pub struct SecondStruct;
350     // does not contain all letters from the query, omitted
351     pub struct UnrelatedOne;
352     // contains all letters from the query, but not in sequence, displayed last
353     pub struct ThiiiiiirdStruct;
354     // contains all letters from the query, but not in the beginning, displayed second
355     pub struct AfterThirdStruct;
356     // contains all letters from the query in the begginning, displayed first
357     pub struct ThirdStruct;
358 }
359
360 //- /main.rs crate:main deps:dep
361 use dep::{FirstStruct, some_module::SecondStruct};
362
363 fn main() {
364     hir$0
365 }
366 "#,
367             expect![[r#"
368                 st dep::some_module::ThirdStruct
369                 st dep::some_module::AfterThirdStruct
370                 st dep::some_module::ThiiiiiirdStruct
371             "#]],
372         );
373     }
374
375     #[test]
376     fn trait_function_fuzzy_completion() {
377         let fixture = r#"
378         //- /lib.rs crate:dep
379         pub mod test_mod {
380             pub trait TestTrait {
381                 const SPECIAL_CONST: u8;
382                 type HumbleType;
383                 fn weird_function();
384                 fn random_method(&self);
385             }
386             pub struct TestStruct {}
387             impl TestTrait for TestStruct {
388                 const SPECIAL_CONST: u8 = 42;
389                 type HumbleType = ();
390                 fn weird_function() {}
391                 fn random_method(&self) {}
392             }
393         }
394
395         //- /main.rs crate:main deps:dep
396         fn main() {
397             dep::test_mod::TestStruct::wei$0
398         }
399         "#;
400
401         check(
402             fixture,
403             expect![[r#"
404                 fn weird_function() (dep::test_mod::TestTrait) fn()
405             "#]],
406         );
407
408         check_edit(
409             "weird_function",
410             fixture,
411             r#"
412 use dep::test_mod::TestTrait;
413
414 fn main() {
415     dep::test_mod::TestStruct::weird_function()$0
416 }
417 "#,
418         );
419     }
420
421     #[test]
422     fn trait_const_fuzzy_completion() {
423         let fixture = r#"
424         //- /lib.rs crate:dep
425         pub mod test_mod {
426             pub trait TestTrait {
427                 const SPECIAL_CONST: u8;
428                 type HumbleType;
429                 fn weird_function();
430                 fn random_method(&self);
431             }
432             pub struct TestStruct {}
433             impl TestTrait for TestStruct {
434                 const SPECIAL_CONST: u8 = 42;
435                 type HumbleType = ();
436                 fn weird_function() {}
437                 fn random_method(&self) {}
438             }
439         }
440
441         //- /main.rs crate:main deps:dep
442         fn main() {
443             dep::test_mod::TestStruct::spe$0
444         }
445         "#;
446
447         check(
448             fixture,
449             expect![[r#"
450             ct SPECIAL_CONST (dep::test_mod::TestTrait)
451         "#]],
452         );
453
454         check_edit(
455             "SPECIAL_CONST",
456             fixture,
457             r#"
458 use dep::test_mod::TestTrait;
459
460 fn main() {
461     dep::test_mod::TestStruct::SPECIAL_CONST
462 }
463 "#,
464         );
465     }
466
467     #[test]
468     fn trait_method_fuzzy_completion() {
469         let fixture = r#"
470         //- /lib.rs crate:dep
471         pub mod test_mod {
472             pub trait TestTrait {
473                 const SPECIAL_CONST: u8;
474                 type HumbleType;
475                 fn weird_function();
476                 fn random_method(&self);
477             }
478             pub struct TestStruct {}
479             impl TestTrait for TestStruct {
480                 const SPECIAL_CONST: u8 = 42;
481                 type HumbleType = ();
482                 fn weird_function() {}
483                 fn random_method(&self) {}
484             }
485         }
486
487         //- /main.rs crate:main deps:dep
488         fn main() {
489             let test_struct = dep::test_mod::TestStruct {};
490             test_struct.ran$0
491         }
492         "#;
493
494         check(
495             fixture,
496             expect![[r#"
497                 me random_method() (dep::test_mod::TestTrait) fn(&self)
498             "#]],
499         );
500
501         check_edit(
502             "random_method",
503             fixture,
504             r#"
505 use dep::test_mod::TestTrait;
506
507 fn main() {
508     let test_struct = dep::test_mod::TestStruct {};
509     test_struct.random_method()$0
510 }
511 "#,
512         );
513     }
514
515     #[test]
516     fn no_trait_type_fuzzy_completion() {
517         check(
518             r#"
519 //- /lib.rs crate:dep
520 pub mod test_mod {
521     pub trait TestTrait {
522         const SPECIAL_CONST: u8;
523         type HumbleType;
524         fn weird_function();
525         fn random_method(&self);
526     }
527     pub struct TestStruct {}
528     impl TestTrait for TestStruct {
529         const SPECIAL_CONST: u8 = 42;
530         type HumbleType = ();
531         fn weird_function() {}
532         fn random_method(&self) {}
533     }
534 }
535
536 //- /main.rs crate:main deps:dep
537 fn main() {
538     dep::test_mod::TestStruct::hum$0
539 }
540 "#,
541             expect![[r#""#]],
542         );
543     }
544
545     #[test]
546     fn does_not_propose_names_in_scope() {
547         check(
548             r#"
549 //- /lib.rs crate:dep
550 pub mod test_mod {
551     pub trait TestTrait {
552         const SPECIAL_CONST: u8;
553         type HumbleType;
554         fn weird_function();
555         fn random_method(&self);
556     }
557     pub struct TestStruct {}
558     impl TestTrait for TestStruct {
559         const SPECIAL_CONST: u8 = 42;
560         type HumbleType = ();
561         fn weird_function() {}
562         fn random_method(&self) {}
563     }
564 }
565
566 //- /main.rs crate:main deps:dep
567 use dep::test_mod::TestStruct;
568 fn main() {
569     TestSt$0
570 }
571 "#,
572             expect![[r#""#]],
573         );
574     }
575
576     #[test]
577     fn does_not_propose_traits_in_scope() {
578         check(
579             r#"
580 //- /lib.rs crate:dep
581 pub mod test_mod {
582     pub trait TestTrait {
583         const SPECIAL_CONST: u8;
584         type HumbleType;
585         fn weird_function();
586         fn random_method(&self);
587     }
588     pub struct TestStruct {}
589     impl TestTrait for TestStruct {
590         const SPECIAL_CONST: u8 = 42;
591         type HumbleType = ();
592         fn weird_function() {}
593         fn random_method(&self) {}
594     }
595 }
596
597 //- /main.rs crate:main deps:dep
598 use dep::test_mod::{TestStruct, TestTrait};
599 fn main() {
600     dep::test_mod::TestStruct::hum$0
601 }
602 "#,
603             expect![[r#""#]],
604         );
605     }
606
607     #[test]
608     fn blanket_trait_impl_import() {
609         check_edit(
610             "another_function",
611             r#"
612 //- /lib.rs crate:dep
613 pub mod test_mod {
614     pub struct TestStruct {}
615     pub trait TestTrait {
616         fn another_function();
617     }
618     impl<T> TestTrait for T {
619         fn another_function() {}
620     }
621 }
622
623 //- /main.rs crate:main deps:dep
624 fn main() {
625     dep::test_mod::TestStruct::ano$0
626 }
627 "#,
628             r#"
629 use dep::test_mod::TestTrait;
630
631 fn main() {
632     dep::test_mod::TestStruct::another_function()$0
633 }
634 "#,
635         );
636     }
637
638     #[test]
639     fn zero_input_deprecated_assoc_item_completion() {
640         check(
641             r#"
642 //- /lib.rs crate:dep
643 pub mod test_mod {
644     #[deprecated]
645     pub trait TestTrait {
646         const SPECIAL_CONST: u8;
647         type HumbleType;
648         fn weird_function();
649         fn random_method(&self);
650     }
651     pub struct TestStruct {}
652     impl TestTrait for TestStruct {
653         const SPECIAL_CONST: u8 = 42;
654         type HumbleType = ();
655         fn weird_function() {}
656         fn random_method(&self) {}
657     }
658 }
659
660 //- /main.rs crate:main deps:dep
661 fn main() {
662     let test_struct = dep::test_mod::TestStruct {};
663     test_struct.$0
664 }
665         "#,
666             expect![[r#"
667                 me random_method() (dep::test_mod::TestTrait) fn(&self) DEPRECATED
668             "#]],
669         );
670
671         check(
672             r#"
673 //- /lib.rs crate:dep
674 pub mod test_mod {
675     #[deprecated]
676     pub trait TestTrait {
677         const SPECIAL_CONST: u8;
678         type HumbleType;
679         fn weird_function();
680         fn random_method(&self);
681     }
682     pub struct TestStruct {}
683     impl TestTrait for TestStruct {
684         const SPECIAL_CONST: u8 = 42;
685         type HumbleType = ();
686         fn weird_function() {}
687         fn random_method(&self) {}
688     }
689 }
690
691 //- /main.rs crate:main deps:dep
692 fn main() {
693     dep::test_mod::TestStruct::$0
694 }
695 "#,
696             expect![[r#"
697                 ct SPECIAL_CONST (dep::test_mod::TestTrait) DEPRECATED
698                 fn weird_function() (dep::test_mod::TestTrait) fn() DEPRECATED
699             "#]],
700         );
701     }
702
703     #[test]
704     fn no_completions_in_use_statements() {
705         check(
706             r#"
707 //- /lib.rs crate:dep
708 pub mod io {
709     pub fn stdin() {}
710 };
711
712 //- /main.rs crate:main deps:dep
713 use stdi$0
714
715 fn main() {}
716 "#,
717             expect![[]],
718         );
719     }
720
721     #[test]
722     fn prefix_config_usage() {
723         let fixture = r#"
724 mod foo {
725     pub mod bar {
726         pub struct Item;
727     }
728 }
729
730 use crate::foo::bar;
731
732 fn main() {
733     Ite$0
734 }"#;
735         let mut config = TEST_CONFIG;
736
737         config.insert_use.prefix_kind = hir::PrefixKind::ByCrate;
738         check_edit_with_config(
739             config.clone(),
740             "Item",
741             fixture,
742             r#"
743 mod foo {
744     pub mod bar {
745         pub struct Item;
746     }
747 }
748
749 use crate::foo::bar::{self, Item};
750
751 fn main() {
752     Item
753 }"#,
754         );
755
756         config.insert_use.prefix_kind = hir::PrefixKind::BySelf;
757         check_edit_with_config(
758             config.clone(),
759             "Item",
760             fixture,
761             r#"
762 mod foo {
763     pub mod bar {
764         pub struct Item;
765     }
766 }
767
768 use crate::foo::bar;
769
770 use self::foo::bar::Item;
771
772 fn main() {
773     Item
774 }"#,
775         );
776
777         config.insert_use.prefix_kind = hir::PrefixKind::Plain;
778         check_edit_with_config(
779             config,
780             "Item",
781             fixture,
782             r#"
783 mod foo {
784     pub mod bar {
785         pub struct Item;
786     }
787 }
788
789 use foo::bar::Item;
790
791 use crate::foo::bar;
792
793 fn main() {
794     Item
795 }"#,
796         );
797     }
798
799     #[test]
800     fn unresolved_qualifier() {
801         let fixture = r#"
802 mod foo {
803     pub mod bar {
804         pub mod baz {
805             pub struct Item;
806         }
807     }
808 }
809
810 fn main() {
811     bar::baz::Ite$0
812 }"#;
813
814         check(
815             fixture,
816             expect![[r#"
817         st foo::bar::baz::Item
818         "#]],
819         );
820
821         check_edit(
822             "Item",
823             fixture,
824             r#"
825         use foo::bar;
826
827         mod foo {
828             pub mod bar {
829                 pub mod baz {
830                     pub struct Item;
831                 }
832             }
833         }
834
835         fn main() {
836             bar::baz::Item
837         }"#,
838         );
839     }
840
841     #[test]
842     fn unresolved_assoc_item_container() {
843         let fixture = r#"
844 mod foo {
845     pub struct Item;
846
847     impl Item {
848         pub const TEST_ASSOC: usize = 3;
849     }
850 }
851
852 fn main() {
853     Item::TEST_A$0
854 }"#;
855
856         check(
857             fixture,
858             expect![[r#"
859         ct TEST_ASSOC (foo::Item)
860         "#]],
861         );
862
863         check_edit(
864             "TEST_ASSOC",
865             fixture,
866             r#"
867 use foo::Item;
868
869 mod foo {
870     pub struct Item;
871
872     impl Item {
873         pub const TEST_ASSOC: usize = 3;
874     }
875 }
876
877 fn main() {
878     Item::TEST_ASSOC
879 }"#,
880         );
881     }
882
883     #[test]
884     fn unresolved_assoc_item_container_with_path() {
885         let fixture = r#"
886 mod foo {
887     pub mod bar {
888         pub struct Item;
889
890         impl Item {
891             pub const TEST_ASSOC: usize = 3;
892         }
893     }
894 }
895
896 fn main() {
897     bar::Item::TEST_A$0
898 }"#;
899
900         check(
901             fixture,
902             expect![[r#"
903         ct TEST_ASSOC (foo::bar::Item)
904     "#]],
905         );
906
907         check_edit(
908             "TEST_ASSOC",
909             fixture,
910             r#"
911 use foo::bar;
912
913 mod foo {
914     pub mod bar {
915         pub struct Item;
916
917         impl Item {
918             pub const TEST_ASSOC: usize = 3;
919         }
920     }
921 }
922
923 fn main() {
924     bar::Item::TEST_ASSOC
925 }"#,
926         );
927     }
928
929     #[test]
930     fn fuzzy_unresolved_path() {
931         check(
932             r#"
933 mod foo {
934     pub mod bar {
935         pub struct Item;
936
937         impl Item {
938             pub const TEST_ASSOC: usize = 3;
939         }
940     }
941 }
942
943 fn main() {
944     bar::ASS$0
945 }"#,
946             expect![[]],
947         )
948     }
949
950     #[test]
951     fn unqualified_assoc_items_are_omitted() {
952         check(
953             r#"
954 mod something {
955     pub trait BaseTrait {
956         fn test_function() -> i32;
957     }
958
959     pub struct Item1;
960     pub struct Item2;
961
962     impl BaseTrait for Item1 {
963         fn test_function() -> i32 {
964             1
965         }
966     }
967
968     impl BaseTrait for Item2 {
969         fn test_function() -> i32 {
970             2
971         }
972     }
973 }
974
975 fn main() {
976     test_f$0
977 }"#,
978             expect![[]],
979         )
980     }
981
982     #[test]
983     fn case_matters() {
984         check(
985             r#"
986 mod foo {
987     pub const TEST_CONST: usize = 3;
988     pub fn test_function() -> i32 {
989         4
990     }
991 }
992
993 fn main() {
994     TE$0
995 }"#,
996             expect![[r#"
997         ct foo::TEST_CONST
998     "#]],
999         );
1000
1001         check(
1002             r#"
1003 mod foo {
1004     pub const TEST_CONST: usize = 3;
1005     pub fn test_function() -> i32 {
1006         4
1007     }
1008 }
1009
1010 fn main() {
1011     te$0
1012 }"#,
1013             expect![[r#"
1014         ct foo::TEST_CONST
1015         fn test_function() (foo::test_function) fn() -> i32
1016     "#]],
1017         );
1018
1019         check(
1020             r#"
1021 mod foo {
1022     pub const TEST_CONST: usize = 3;
1023     pub fn test_function() -> i32 {
1024         4
1025     }
1026 }
1027
1028 fn main() {
1029     Te$0
1030 }"#,
1031             expect![[]],
1032         );
1033     }
1034
1035     #[test]
1036     fn no_fuzzy_during_fields_of_record_lit_syntax() {
1037         check(
1038             r#"
1039 mod m {
1040     pub fn some_fn() -> i32 {
1041         42
1042     }
1043 }
1044 struct Foo {
1045     some_field: i32,
1046 }
1047 fn main() {
1048     let _ = Foo { so$0 };
1049 }
1050 "#,
1051             expect![[]],
1052         );
1053     }
1054
1055     #[test]
1056     fn fuzzy_after_fields_of_record_lit_syntax() {
1057         check(
1058             r#"
1059 mod m {
1060     pub fn some_fn() -> i32 {
1061         42
1062     }
1063 }
1064 struct Foo {
1065     some_field: i32,
1066 }
1067 fn main() {
1068     let _ = Foo { some_field: so$0 };
1069 }
1070 "#,
1071             expect![[r#"
1072                 fn some_fn() (m::some_fn) fn() -> i32
1073             "#]],
1074         );
1075     }
1076
1077     #[test]
1078     fn no_flyimports_in_traits_and_impl_declarations() {
1079         check(
1080             r#"
1081 mod m {
1082     pub fn some_fn() -> i32 {
1083         42
1084     }
1085 }
1086 trait Foo {
1087     som$0
1088 }
1089 "#,
1090             expect![[r#""#]],
1091         );
1092
1093         check(
1094             r#"
1095 mod m {
1096     pub fn some_fn() -> i32 {
1097         42
1098     }
1099 }
1100 struct Foo;
1101 impl Foo {
1102     som$0
1103 }
1104 "#,
1105             expect![[r#""#]],
1106         );
1107
1108         check(
1109             r#"
1110 mod m {
1111     pub fn some_fn() -> i32 {
1112         42
1113     }
1114 }
1115 struct Foo;
1116 trait Bar {}
1117 impl Bar for Foo {
1118     som$0
1119 }
1120 "#,
1121             expect![[r#""#]],
1122         );
1123     }
1124
1125     #[test]
1126     fn no_inherent_candidates_proposed() {
1127         check(
1128             r#"
1129 mod baz {
1130     pub trait DefDatabase {
1131         fn method1(&self);
1132     }
1133     pub trait HirDatabase: DefDatabase {
1134         fn method2(&self);
1135     }
1136 }
1137
1138 mod bar {
1139     fn test(db: &dyn crate::baz::HirDatabase) {
1140         db.metho$0
1141     }
1142 }
1143             "#,
1144             expect![[r#""#]],
1145         );
1146     }
1147 }