aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/completions/unqualified_path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/completion/src/completions/unqualified_path.rs')
-rw-r--r--crates/completion/src/completions/unqualified_path.rs134
1 files changed, 58 insertions, 76 deletions
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 1482df8fb..2a315cb86 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -44,7 +44,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
44 acc.add_resolution(ctx, name.to_string(), &res) 44 acc.add_resolution(ctx, name.to_string(), &res)
45 }); 45 });
46 46
47 if ctx.config.enable_experimental_completions { 47 if !ctx.config.disable_fuzzy_autoimports && ctx.config.resolve_additional_edits_lazily() {
48 fuzzy_completion(acc, ctx).unwrap_or_default() 48 fuzzy_completion(acc, ctx).unwrap_or_default()
49 } 49 }
50} 50}
@@ -99,6 +99,7 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
99// 99//
100// To avoid an excessive amount of the results returned, completion input is checked for inclusion in the identifiers only 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. 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.
102// 103//
103// .Merge Behaviour 104// .Merge Behaviour
104// 105//
@@ -107,53 +108,53 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
107// 108//
108// .LSP and performance implications 109// .LSP and performance implications
109// 110//
110// LSP 3.16 provides the way to defer the computation of some completion data, including the import edits for this feature. 111// The feature is enabled only if the LSP client supports LSP protocol version 3.16+ and reports the `additionalTextEdits`
111// If the LSP client supports the `additionalTextEdits` (case sensitive) resolve client capability, rust-analyzer computes 112// (case sensitive) resolve client capability in its client capabilities.
112// the completion edits only when a corresponding completion item is selected. 113// This way the server is able to defer the costly computations, doing them for a selected completion item only.
113// For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones, 114// For clients with no such support, all edits have to be calculated on the completion request, including the fuzzy search completion ones,
114// which might be slow. 115// which might be slow ergo the feature is automatically disabled.
115// 116//
116// .Feature toggle 117// .Feature toggle
117// 118//
118// The feature can be turned off in the settings with the `rust-analyzer.completion.enableExperimental` flag. 119// The feature can be forcefully turned off in the settings with the `rust-analyzer.completion.disableFuzzyAutoimports` flag.
119fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { 120fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
120 let _p = profile::span("fuzzy_completion"); 121 let _p = profile::span("fuzzy_completion");
122 let potential_import_name = ctx.token.to_string();
123
124 if potential_import_name.len() < 3 {
125 return None;
126 }
127
121 let current_module = ctx.scope.module()?; 128 let current_module = ctx.scope.module()?;
122 let anchor = ctx.name_ref_syntax.as_ref()?; 129 let anchor = ctx.name_ref_syntax.as_ref()?;
123 let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; 130 let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;
124 131
125 let potential_import_name = ctx.token.to_string(); 132 let possible_imports =
126 133 imports_locator::find_similar_imports(&ctx.sema, ctx.krate?, &potential_import_name, true)
127 let possible_imports = imports_locator::find_similar_imports( 134 .filter_map(|import_candidate| {
128 &ctx.sema, 135 Some(match import_candidate {
129 ctx.krate?, 136 Either::Left(module_def) => (
130 &potential_import_name, 137 current_module.find_use_path(ctx.db, module_def)?,
131 50, 138 ScopeDef::ModuleDef(module_def),
132 true, 139 ),
133 ) 140 Either::Right(macro_def) => (
134 .filter_map(|import_candidate| { 141 current_module.find_use_path(ctx.db, macro_def)?,
135 Some(match import_candidate { 142 ScopeDef::MacroDef(macro_def),
136 Either::Left(module_def) => { 143 ),
137 (current_module.find_use_path(ctx.db, module_def)?, ScopeDef::ModuleDef(module_def)) 144 })
138 } 145 })
139 Either::Right(macro_def) => { 146 .filter(|(mod_path, _)| mod_path.len() > 1)
140 (current_module.find_use_path(ctx.db, macro_def)?, ScopeDef::MacroDef(macro_def)) 147 .filter_map(|(import_path, definition)| {
141 } 148 render_resolution_with_import(
142 }) 149 RenderContext::new(ctx),
143 }) 150 ImportEdit {
144 .filter(|(mod_path, _)| mod_path.len() > 1) 151 import_path: import_path.clone(),
145 .take(20) 152 import_scope: import_scope.clone(),
146 .filter_map(|(import_path, definition)| { 153 merge_behaviour: ctx.config.merge,
147 render_resolution_with_import( 154 },
148 RenderContext::new(ctx), 155 &definition,
149 ImportEdit { 156 )
150 import_path: import_path.clone(), 157 });
151 import_scope: import_scope.clone(),
152 merge_behaviour: ctx.config.merge,
153 },
154 &definition,
155 )
156 });
157 158
158 acc.add_all(possible_imports); 159 acc.add_all(possible_imports);
159 Some(()) 160 Some(())
@@ -775,7 +776,13 @@ impl My<|>
775 776
776 #[test] 777 #[test]
777 fn function_fuzzy_completion() { 778 fn function_fuzzy_completion() {
778 check_edit( 779 let mut completion_config = CompletionConfig::default();
780 completion_config
781 .active_resolve_capabilities
782 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
783
784 check_edit_with_config(
785 completion_config,
779 "stdin", 786 "stdin",
780 r#" 787 r#"
781//- /lib.rs crate:dep 788//- /lib.rs crate:dep
@@ -800,7 +807,13 @@ fn main() {
800 807
801 #[test] 808 #[test]
802 fn macro_fuzzy_completion() { 809 fn macro_fuzzy_completion() {
803 check_edit( 810 let mut completion_config = CompletionConfig::default();
811 completion_config
812 .active_resolve_capabilities
813 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
814
815 check_edit_with_config(
816 completion_config,
804 "macro_with_curlies!", 817 "macro_with_curlies!",
805 r#" 818 r#"
806//- /lib.rs crate:dep 819//- /lib.rs crate:dep
@@ -827,37 +840,6 @@ fn main() {
827 840
828 #[test] 841 #[test]
829 fn struct_fuzzy_completion() { 842 fn struct_fuzzy_completion() {
830 check_edit(
831 "ThirdStruct",
832 r#"
833//- /lib.rs crate:dep
834pub struct FirstStruct;
835pub mod some_module {
836 pub struct SecondStruct;
837 pub struct ThirdStruct;
838}
839
840//- /main.rs crate:main deps:dep
841use dep::{FirstStruct, some_module::SecondStruct};
842
843fn main() {
844 this<|>
845}
846"#,
847 r#"
848use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};
849
850fn main() {
851 ThirdStruct
852}
853"#,
854 );
855 }
856
857 /// LSP protocol supports separate completion resolve requests to do the heavy computations there.
858 /// This test checks that for a certain resolve capatilities no such operations (autoimport) are done.
859 #[test]
860 fn no_fuzzy_completions_applied_for_certain_resolve_capability() {
861 let mut completion_config = CompletionConfig::default(); 843 let mut completion_config = CompletionConfig::default();
862 completion_config 844 completion_config
863 .active_resolve_capabilities 845 .active_resolve_capabilities
@@ -870,22 +852,22 @@ fn main() {
870//- /lib.rs crate:dep 852//- /lib.rs crate:dep
871pub struct FirstStruct; 853pub struct FirstStruct;
872pub mod some_module { 854pub mod some_module {
873pub struct SecondStruct; 855 pub struct SecondStruct;
874pub struct ThirdStruct; 856 pub struct ThirdStruct;
875} 857}
876 858
877//- /main.rs crate:main deps:dep 859//- /main.rs crate:main deps:dep
878use dep::{FirstStruct, some_module::SecondStruct}; 860use dep::{FirstStruct, some_module::SecondStruct};
879 861
880fn main() { 862fn main() {
881this<|> 863 this<|>
882} 864}
883"#, 865"#,
884 r#" 866 r#"
885use dep::{FirstStruct, some_module::SecondStruct}; 867use dep::{FirstStruct, some_module::{SecondStruct, ThirdStruct}};
886 868
887fn main() { 869fn main() {
888ThirdStruct 870 ThirdStruct
889} 871}
890"#, 872"#,
891 ); 873 );