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