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