1 //! Completion of names from the current scope, e.g. locals and imported items.
4 use hir::{Adt, ModuleDef, ScopeDef, Type};
5 use ide_db::helpers::insert_use::ImportScope;
6 use ide_db::imports_locator;
11 render::{render_resolution_with_import, RenderContext},
12 CompletionContext, Completions, ImportEdit,
15 pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) {
16 if !(ctx.is_trivial_path || ctx.is_pat_binding_or_const) {
19 if ctx.record_lit_syntax.is_some()
20 || ctx.record_pat_syntax.is_some()
21 || ctx.attribute_under_caret.is_some()
22 || ctx.mod_declaration_under_caret.is_some()
27 if let Some(ty) = &ctx.expected_type {
28 complete_enum_variants(acc, ctx, ty);
31 if ctx.is_pat_binding_or_const {
35 ctx.scope.process_all_names(&mut |name, res| {
36 if ctx.use_item_syntax.is_some() {
37 if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) {
38 if name_ref.syntax().text() == name.to_string().as_str() {
39 mark::hit!(self_fulfilling_completion);
44 acc.add_resolution(ctx, name.to_string(), &res)
47 if ctx.config.enable_autoimport_completions && ctx.config.resolve_additional_edits_lazily() {
48 fuzzy_completion(acc, ctx).unwrap_or_default()
52 fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) {
53 if let Some(Adt::Enum(enum_data)) = ty.as_adt() {
54 let variants = enum_data.variants(ctx.db);
56 let module = if let Some(module) = ctx.scope.module() {
57 // Compute path from the completion site if available.
60 // Otherwise fall back to the enum's definition site.
61 enum_data.module(ctx.db)
64 for variant in variants {
65 if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) {
66 // Variants with trivial paths are already added by the existing completion logic,
67 // so we should avoid adding these twice
68 if path.segments.len() > 1 {
69 acc.add_qualified_enum_variant(ctx, variant, path);
76 // Feature: Fuzzy Completion and Autoimports
78 // When completing names in the current scope, proposes additional imports from other modules or crates,
79 // if they can be qualified in the scope and their name contains all symbols from the completion input
80 // (case-insensitive, in any order or places).
86 // # pub mod std { pub mod marker { pub struct PhantomData { } } }
90 // use std::marker::PhantomData;
95 // # pub mod std { pub mod marker { pub struct PhantomData { } } }
98 // .Fuzzy search details
100 // To avoid an excessive amount of the results returned, completion input is checked for inclusion in the identifiers only
101 // (i.e. in `HashMap` in the `std::collections::HashMap` path), also not in the module indentifiers.
102 // It also avoids searching for any imports for inputs with their length less that 3 symbols.
106 // It is possible to configure how use-trees are merged with the `importMergeBehaviour` setting.
107 // Mimics the corresponding behaviour of the `Auto Import` feature.
109 // .LSP and performance implications
111 // The feature is enabled only if the LSP client supports LSP protocol version 3.16+ and reports the `additionalTextEdits`
112 // (case sensitive) resolve client capability in its client capabilities.
113 // This way the server is able to defer the costly computations, doing them for a selected completion item only.
114 // For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones,
115 // which might be slow ergo the feature is automatically disabled.
119 // The feature can be forcefully turned off in the settings with the `rust-analyzer.completion.enableAutoimportCompletions` flag.
120 // Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding
121 // capability enabled.
122 fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
123 let _p = profile::span("fuzzy_completion");
124 let potential_import_name = ctx.token.to_string();
126 if potential_import_name.len() < 3 {
130 let current_module = ctx.scope.module()?;
131 let anchor = ctx.name_ref_syntax.as_ref()?;
132 let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;
134 let possible_imports =
135 imports_locator::find_similar_imports(&ctx.sema, ctx.krate?, &potential_import_name, true)
136 .filter_map(|import_candidate| {
137 Some(match import_candidate {
138 Either::Left(module_def) => (
139 current_module.find_use_path(ctx.db, module_def)?,
140 ScopeDef::ModuleDef(module_def),
142 Either::Right(macro_def) => (
143 current_module.find_use_path(ctx.db, macro_def)?,
144 ScopeDef::MacroDef(macro_def),
148 .filter(|(mod_path, _)| mod_path.len() > 1)
149 .filter_map(|(import_path, definition)| {
150 render_resolution_with_import(
151 RenderContext::new(ctx),
153 import_path: import_path.clone(),
154 import_scope: import_scope.clone(),
155 merge_behaviour: ctx.config.merge,
161 acc.add_all(possible_imports);
167 use expect_test::{expect, Expect};
168 use test_utils::mark;
171 test_utils::{check_edit, check_edit_with_config, completion_list},
172 CompletionConfig, CompletionKind,
175 fn check(ra_fixture: &str, expect: Expect) {
176 let actual = completion_list(ra_fixture, CompletionKind::Reference);
177 expect.assert_eq(&actual)
181 fn self_fulfilling_completion() {
182 mark::check!(self_fulfilling_completion);
186 use std::collections;
195 fn bind_pat_and_path_ignore_at() {
199 fn quux(x: Option<Enum>) {
202 Some(en<|> @ Enum::A) => (),
211 fn bind_pat_and_path_ignore_ref() {
215 fn quux(x: Option<Enum>) {
218 Some(ref en<|>) => (),
227 fn bind_pat_and_path() {
231 fn quux(x: Option<Enum>) {
245 fn completes_bindings_from_let() {
255 fn quux(…) fn quux(x: i32)
263 fn completes_bindings_from_if_let() {
267 if let Some(x) = foo() {
270 if let Some(a) = bar() {
285 fn completes_bindings_from_for() {
289 for x in &[1, 2, 3] { <|> }
300 fn completes_if_prefix_is_keyword() {
301 mark::check!(completes_if_prefix_is_keyword);
320 fn completes_generic_params() {
322 r#"fn quux<T>() { <|> }"#,
325 fn quux() fn quux<T>()
331 fn completes_generic_params_in_struct() {
333 r#"struct S<T> { x: <|>}"#,
343 fn completes_self_in_enum() {
345 r#"enum X { Y(<|>) }"#,
354 fn completes_module_items() {
369 /// Regression test for issue #6091.
371 fn correctly_completes_module_items_prefixed_with_underscore() {
390 fn completes_extern_prelude() {
393 //- /lib.rs crate:main deps:other_crate
396 //- /other_crate/lib.rs crate:other_crate
406 fn completes_module_items_in_nested_modules() {
423 fn completes_return_type() {
437 fn dont_show_both_completions_for_shadowing() {
448 // FIXME: should be only one bar here
458 fn completes_self_in_methods() {
460 r#"impl S { fn foo(&self) { <|> } }"#,
469 fn completes_prelude() {
472 //- /main.rs crate:main deps:std
473 fn foo() { let x: <|> }
475 //- /std/lib.rs crate:std
479 mod prelude { struct Option; }
490 fn completes_std_prelude_if_core_is_defined() {
493 //- /main.rs crate:main deps:core,std
494 fn foo() { let x: <|> }
496 //- /core/lib.rs crate:core
500 mod prelude { struct Option; }
502 //- /std/lib.rs crate:std deps:core
506 mod prelude { struct String; }
518 fn completes_macros_as_value() {
521 macro_rules! foo { () => {} }
525 macro_rules! bar { () => {} }
529 macro_rules! nope { () => {} }
532 macro_rules! baz { () => {} }
535 fn main() { let v = <|> }
538 ma bar!(…) macro_rules! bar
539 ma baz!(…) #[macro_export]
541 ma foo!(…) macro_rules! foo
550 fn completes_both_macro_and_value() {
553 macro_rules! foo { () => {} }
557 ma foo!(…) macro_rules! foo
564 fn completes_macros_as_type() {
567 macro_rules! foo { () => {} }
568 fn main() { let x: <|> }
571 ma foo!(…) macro_rules! foo
578 fn completes_macros_as_stmt() {
581 macro_rules! foo { () => {} }
585 ma foo!(…) macro_rules! foo
592 fn completes_local_item() {
601 fn frobnicate() fn frobnicate()
608 fn completes_in_simple_macro_1() {
611 macro_rules! m { ($e:expr) => { $e } }
618 ma m!(…) macro_rules! m
619 fn quux(…) fn quux(x: i32)
627 fn completes_in_simple_macro_2() {
630 macro_rules! m { ($e:expr) => { $e } }
637 ma m!(…) macro_rules! m
638 fn quux(…) fn quux(x: i32)
646 fn completes_in_simple_macro_without_closing_parens() {
649 macro_rules! m { ($e:expr) => { $e } }
656 ma m!(…) macro_rules! m
657 fn quux(…) fn quux(x: i32)
665 fn completes_unresolved_uses() {
679 fn completes_enum_variant_matcharm() {
682 enum Foo { Bar, Baz, Quux }
699 fn completes_enum_variant_iflet() {
702 enum Foo { Bar, Baz, Quux }
706 if let Qu<|> = foo { }
719 fn completes_enum_variant_basic_expr() {
722 enum Foo { Bar, Baz, Quux }
723 fn main() { let foo: Foo = Q<|> }
736 fn completes_enum_variant_from_module() {
739 mod m { pub enum E { V } }
740 fn f() -> m::E { V<|> }
743 fn f() fn f() -> m::E
751 fn dont_complete_attr() {
763 fn completes_type_or_trait_in_impl_block() {
780 fn function_fuzzy_completion() {
781 let mut completion_config = CompletionConfig::default();
783 .active_resolve_capabilities
784 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
786 check_edit_with_config(
790 //- /lib.rs crate:dep
795 //- /main.rs crate:main deps:dep
811 fn macro_fuzzy_completion() {
812 let mut completion_config = CompletionConfig::default();
814 .active_resolve_capabilities
815 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
817 check_edit_with_config(
819 "macro_with_curlies!",
821 //- /lib.rs crate:dep
822 /// Please call me as macro_with_curlies! {}
824 macro_rules! macro_with_curlies {
828 //- /main.rs crate:main deps:dep
834 use dep::macro_with_curlies;
837 macro_with_curlies! {$0}
844 fn struct_fuzzy_completion() {
845 let mut completion_config = CompletionConfig::default();
847 .active_resolve_capabilities
848 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
850 check_edit_with_config(
854 //- /lib.rs crate:dep
855 pub struct FirstStruct;
856 pub mod some_module {
857 pub struct SecondStruct;
858 pub struct ThirdStruct;
861 //- /main.rs crate:main deps:dep
862 use dep::{FirstStruct, some_module::SecondStruct};
869 use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};