aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/completion/src/config.rs9
-rw-r--r--crates/completion/src/item.rs3
-rw-r--r--crates/completion/src/render.rs10
-rw-r--r--crates/completion/src/render/enum_variant.rs5
-rw-r--r--crates/completion/src/render/function.rs5
-rw-r--r--crates/completion/src/render/macro_.rs5
-rw-r--r--crates/completion/src/test_utils.rs1
-rw-r--r--crates/rust-analyzer/src/caps.rs14
-rw-r--r--crates/rust-analyzer/src/config.rs4
-rw-r--r--crates/rust-analyzer/src/handlers.rs2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs24
11 files changed, 48 insertions, 34 deletions
diff --git a/crates/completion/src/config.rs b/crates/completion/src/config.rs
index e9a02aeb8..f2fa5c27b 100644
--- a/crates/completion/src/config.rs
+++ b/crates/completion/src/config.rs
@@ -15,9 +15,15 @@ pub struct CompletionConfig {
15 pub add_call_argument_snippets: bool, 15 pub add_call_argument_snippets: bool,
16 pub snippet_cap: Option<SnippetCap>, 16 pub snippet_cap: Option<SnippetCap>,
17 pub merge: Option<MergeBehaviour>, 17 pub merge: Option<MergeBehaviour>,
18 /// A set of capabilities, enabled on the cliend and supported on the server.
18 pub resolve_capabilities: FxHashSet<CompletionResolveCapability>, 19 pub resolve_capabilities: FxHashSet<CompletionResolveCapability>,
19} 20}
20 21
22/// A resolve capability, supported on a server.
23/// If the client registers any of those in its completion resolve capabilities,
24/// the server is able to render completion items' corresponding fields later,
25/// not during an initial completion item request.
26/// See https://github.com/rust-analyzer/rust-analyzer/issues/6366 for more details.
21#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] 27#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
22pub enum CompletionResolveCapability { 28pub enum CompletionResolveCapability {
23 Documentation, 29 Documentation,
@@ -30,7 +36,8 @@ impl CompletionConfig {
30 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None } 36 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None }
31 } 37 }
32 38
33 pub fn should_resolve_immediately(&self) -> bool { 39 /// Whether the completions' additional edits are calculated later, during a resolve request or not.
40 pub fn should_resolve_additional_edits_immediately(&self) -> bool {
34 !self.resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits) 41 !self.resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits)
35 } 42 }
36} 43}
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs
index 5906637a6..775245b3b 100644
--- a/crates/completion/src/item.rs
+++ b/crates/completion/src/item.rs
@@ -67,8 +67,7 @@ pub struct CompletionItem {
67 /// possible match. 67 /// possible match.
68 ref_match: Option<(Mutability, CompletionScore)>, 68 ref_match: Option<(Mutability, CompletionScore)>,
69 69
70 /// The data later to be used in the `completionItem/resolve` response 70 /// The import data to add to completion's edits.
71 /// to add the insert import edit.
72 import_to_add: Option<ImportToAdd>, 71 import_to_add: Option<ImportToAdd>,
73} 72}
74 73
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index b7a3a3935..3a793000b 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -194,7 +194,10 @@ impl<'a> Render<'a> {
194 local_name, 194 local_name,
195 ) 195 )
196 .kind(CompletionItemKind::UnresolvedReference) 196 .kind(CompletionItemKind::UnresolvedReference)
197 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) 197 .add_import(
198 import_to_add,
199 self.ctx.completion.config.should_resolve_additional_edits_immediately(),
200 )
198 .build(); 201 .build();
199 return Some(item); 202 return Some(item);
200 } 203 }
@@ -249,7 +252,10 @@ impl<'a> Render<'a> {
249 252
250 let item = item 253 let item = item
251 .kind(kind) 254 .kind(kind)
252 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) 255 .add_import(
256 import_to_add,
257 self.ctx.completion.config.should_resolve_additional_edits_immediately(),
258 )
253 .set_documentation(docs) 259 .set_documentation(docs)
254 .set_ref_match(ref_match) 260 .set_ref_match(ref_match)
255 .build(); 261 .build();
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs
index c08824c6a..6548b4676 100644
--- a/crates/completion/src/render/enum_variant.rs
+++ b/crates/completion/src/render/enum_variant.rs
@@ -71,7 +71,10 @@ impl<'a> EnumVariantRender<'a> {
71 .kind(CompletionItemKind::EnumVariant) 71 .kind(CompletionItemKind::EnumVariant)
72 .set_documentation(self.variant.docs(self.ctx.db())) 72 .set_documentation(self.variant.docs(self.ctx.db()))
73 .set_deprecated(self.ctx.is_deprecated(self.variant)) 73 .set_deprecated(self.ctx.is_deprecated(self.variant))
74 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) 74 .add_import(
75 import_to_add,
76 self.ctx.completion.config.should_resolve_additional_edits_immediately(),
77 )
75 .detail(self.detail()); 78 .detail(self.detail());
76 79
77 if self.variant_kind == StructKind::Tuple { 80 if self.variant_kind == StructKind::Tuple {
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index 3492384c6..b13e0dafc 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -47,7 +47,10 @@ impl<'a> FunctionRender<'a> {
47 .set_deprecated(self.ctx.is_deprecated(self.func)) 47 .set_deprecated(self.ctx.is_deprecated(self.func))
48 .detail(self.detail()) 48 .detail(self.detail())
49 .add_call_parens(self.ctx.completion, self.name, params) 49 .add_call_parens(self.ctx.completion, self.name, params)
50 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) 50 .add_import(
51 import_to_add,
52 self.ctx.completion.config.should_resolve_additional_edits_immediately(),
53 )
51 .build() 54 .build()
52 } 55 }
53 56
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index 15648b5b7..7a8eeb7b9 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -50,7 +50,10 @@ impl<'a> MacroRender<'a> {
50 .kind(CompletionItemKind::Macro) 50 .kind(CompletionItemKind::Macro)
51 .set_documentation(self.docs.clone()) 51 .set_documentation(self.docs.clone())
52 .set_deprecated(self.ctx.is_deprecated(self.macro_)) 52 .set_deprecated(self.ctx.is_deprecated(self.macro_))
53 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) 53 .add_import(
54 import_to_add,
55 self.ctx.completion.config.should_resolve_additional_edits_immediately(),
56 )
54 .detail(self.detail()); 57 .detail(self.detail());
55 58
56 let needs_bang = self.needs_bang(); 59 let needs_bang = self.needs_bang();
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs
index 88351ee15..4c1b1a839 100644
--- a/crates/completion/src/test_utils.rs
+++ b/crates/completion/src/test_utils.rs
@@ -97,7 +97,6 @@ pub(crate) fn check_edit_with_config(
97 .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions)); 97 .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions));
98 let mut actual = db.file_text(position.file_id).to_string(); 98 let mut actual = db.file_text(position.file_id).to_string();
99 completion.text_edit().apply(&mut actual); 99 completion.text_edit().apply(&mut actual);
100 // git how to apply imports now?
101 assert_eq_text!(&ra_fixture_after, &actual) 100 assert_eq_text!(&ra_fixture_after, &actual)
102} 101}
103 102
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index d6b862088..0b6ca76e2 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -32,7 +32,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
32 })), 32 })),
33 hover_provider: Some(HoverProviderCapability::Simple(true)), 33 hover_provider: Some(HoverProviderCapability::Simple(true)),
34 completion_provider: Some(CompletionOptions { 34 completion_provider: Some(CompletionOptions {
35 resolve_provider: Some(true), 35 resolve_provider: completions_resolve_provider(client_caps),
36 trigger_characters: Some(vec![":".to_string(), ".".to_string()]), 36 trigger_characters: Some(vec![":".to_string(), ".".to_string()]),
37 work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, 37 work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
38 }), 38 }),
@@ -50,9 +50,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
50 document_symbol_provider: Some(OneOf::Left(true)), 50 document_symbol_provider: Some(OneOf::Left(true)),
51 workspace_symbol_provider: Some(OneOf::Left(true)), 51 workspace_symbol_provider: Some(OneOf::Left(true)),
52 code_action_provider: Some(code_action_capabilities(client_caps)), 52 code_action_provider: Some(code_action_capabilities(client_caps)),
53 code_lens_provider: Some(CodeLensOptions { 53 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
54 resolve_provider: resolve_provider(client_caps),
55 }),
56 document_formatting_provider: Some(OneOf::Left(true)), 54 document_formatting_provider: Some(OneOf::Left(true)),
57 document_range_formatting_provider: None, 55 document_range_formatting_provider: None,
58 document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { 56 document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions {
@@ -97,16 +95,16 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
97 } 95 }
98} 96}
99 97
100fn resolve_provider(client_caps: &ClientCapabilities) -> Option<bool> { 98fn completions_resolve_provider(client_caps: &ClientCapabilities) -> Option<bool> {
101 if enabled_resolve_capabilities(client_caps)?.is_empty() { 99 if enabled_completions_resolve_capabilities(client_caps)?.is_empty() {
102 None 100 None
103 } else { 101 } else {
104 Some(true) 102 Some(true)
105 } 103 }
106} 104}
107 105
108/// Parses client capabilities and returns all that rust-analyzer supports. 106/// Parses client capabilities and returns all completion resolve capabilities rust-analyzer supports.
109pub fn enabled_resolve_capabilities( 107pub fn enabled_completions_resolve_capabilities(
110 caps: &ClientCapabilities, 108 caps: &ClientCapabilities,
111) -> Option<FxHashSet<CompletionResolveCapability>> { 109) -> Option<FxHashSet<CompletionResolveCapability>> {
112 Some( 110 Some(
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 83f097829..5ce7ae426 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -19,7 +19,7 @@ use rustc_hash::FxHashSet;
19use serde::Deserialize; 19use serde::Deserialize;
20use vfs::AbsPathBuf; 20use vfs::AbsPathBuf;
21 21
22use crate::{caps::enabled_resolve_capabilities, diagnostics::DiagnosticsMapConfig}; 22use crate::{caps::enabled_completions_resolve_capabilities, diagnostics::DiagnosticsMapConfig};
23 23
24#[derive(Debug, Clone)] 24#[derive(Debug, Clone)]
25pub struct Config { 25pub struct Config {
@@ -389,7 +389,7 @@ impl Config {
389 389
390 self.completion.allow_snippets(false); 390 self.completion.allow_snippets(false);
391 self.completion.resolve_capabilities = 391 self.completion.resolve_capabilities =
392 enabled_resolve_capabilities(caps).unwrap_or_default(); 392 enabled_completions_resolve_capabilities(caps).unwrap_or_default();
393 if let Some(completion) = &doc_caps.completion { 393 if let Some(completion) = &doc_caps.completion {
394 if let Some(completion_item) = &completion.completion_item { 394 if let Some(completion_item) = &completion.completion_item {
395 if let Some(value) = completion_item.snippet_support { 395 if let Some(value) = completion_item.snippet_support {
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index eeb2f6f93..2dc62ee51 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -581,7 +581,7 @@ pub(crate) fn handle_completion(
581 &line_index, 581 &line_index,
582 line_endings, 582 line_endings,
583 item.clone(), 583 item.clone(),
584 &snap.config.completion.resolve_capabilities, 584 snap.config.completion.should_resolve_additional_edits_immediately(),
585 ); 585 );
586 586
587 let item_id = serde_json::to_value(&item_index) 587 let item_id = serde_json::to_value(&item_index)
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index aa542f5d1..f5337f3f1 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -5,10 +5,10 @@ use std::{
5}; 5};
6 6
7use ide::{ 7use ide::{
8 Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, CompletionResolveCapability, 8 Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation,
9 Documentation, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, 9 FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange,
10 HighlightedRange, ImportToAdd, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, 10 ImportToAdd, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup,
11 Markup, NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, 11 NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange,
12 SourceFileEdit, TextEdit, 12 SourceFileEdit, TextEdit,
13}; 13};
14use ide_db::{ 14use ide_db::{
@@ -16,7 +16,6 @@ use ide_db::{
16 helpers::{insert_use, mod_path_to_ast}, 16 helpers::{insert_use, mod_path_to_ast},
17}; 17};
18use itertools::Itertools; 18use itertools::Itertools;
19use rustc_hash::FxHashSet;
20use syntax::{algo, SyntaxKind, TextRange, TextSize}; 19use syntax::{algo, SyntaxKind, TextRange, TextSize};
21 20
22use crate::{ 21use crate::{
@@ -163,7 +162,7 @@ pub(crate) fn completion_item(
163 line_index: &LineIndex, 162 line_index: &LineIndex,
164 line_endings: LineEndings, 163 line_endings: LineEndings,
165 completion_item: CompletionItem, 164 completion_item: CompletionItem,
166 resolve_capabilities: &FxHashSet<CompletionResolveCapability>, 165 should_resolve_additional_edits_immediately: bool,
167) -> Vec<lsp_types::CompletionItem> { 166) -> Vec<lsp_types::CompletionItem> {
168 fn set_score(res: &mut lsp_types::CompletionItem, label: &str) { 167 fn set_score(res: &mut lsp_types::CompletionItem, label: &str) {
169 res.preselect = Some(true); 168 res.preselect = Some(true);
@@ -237,14 +236,12 @@ pub(crate) fn completion_item(
237 None => vec![res], 236 None => vec![res],
238 }; 237 };
239 238
240 let unapplied_import_data = completion_item.import_to_add().filter(|_| {
241 !resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits)
242 });
243
244 for mut r in all_results.iter_mut() { 239 for mut r in all_results.iter_mut() {
245 r.insert_text_format = Some(insert_text_format(completion_item.insert_text_format())); 240 r.insert_text_format = Some(insert_text_format(completion_item.insert_text_format()));
246 if let Some(unapplied_import_data) = unapplied_import_data { 241 if !should_resolve_additional_edits_immediately {
247 append_import_edits(r, unapplied_import_data, line_index, line_endings); 242 if let Some(unapplied_import_data) = completion_item.import_to_add() {
243 append_import_edits(r, unapplied_import_data, line_index, line_endings);
244 }
248 } 245 }
249 } 246 }
250 247
@@ -891,7 +888,6 @@ mod tests {
891 let (offset, text) = test_utils::extract_offset(fixture); 888 let (offset, text) = test_utils::extract_offset(fixture);
892 let line_index = LineIndex::new(&text); 889 let line_index = LineIndex::new(&text);
893 let (analysis, file_id) = Analysis::from_single_file(text); 890 let (analysis, file_id) = Analysis::from_single_file(text);
894 let resolve_caps = FxHashSet::default();
895 let completions: Vec<(String, Option<String>)> = analysis 891 let completions: Vec<(String, Option<String>)> = analysis
896 .completions( 892 .completions(
897 &ide::CompletionConfig::default(), 893 &ide::CompletionConfig::default(),
@@ -901,7 +897,7 @@ mod tests {
901 .unwrap() 897 .unwrap()
902 .into_iter() 898 .into_iter()
903 .filter(|c| c.label().ends_with("arg")) 899 .filter(|c| c.label().ends_with("arg"))
904 .map(|c| completion_item(&line_index, LineEndings::Unix, c, &resolve_caps)) 900 .map(|c| completion_item(&line_index, LineEndings::Unix, c, true))
905 .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text))) 901 .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text)))
906 .collect(); 902 .collect();
907 expect_test::expect![[r#" 903 expect_test::expect![[r#"