diff options
-rw-r--r-- | crates/completion/src/config.rs | 9 | ||||
-rw-r--r-- | crates/completion/src/item.rs | 3 | ||||
-rw-r--r-- | crates/completion/src/render.rs | 10 | ||||
-rw-r--r-- | crates/completion/src/render/enum_variant.rs | 5 | ||||
-rw-r--r-- | crates/completion/src/render/function.rs | 5 | ||||
-rw-r--r-- | crates/completion/src/render/macro_.rs | 5 | ||||
-rw-r--r-- | crates/completion/src/test_utils.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/caps.rs | 14 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 24 |
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)] |
22 | pub enum CompletionResolveCapability { | 28 | pub 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 | ||
100 | fn resolve_provider(client_caps: &ClientCapabilities) -> Option<bool> { | 98 | fn 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. |
109 | pub fn enabled_resolve_capabilities( | 107 | pub 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; | |||
19 | use serde::Deserialize; | 19 | use serde::Deserialize; |
20 | use vfs::AbsPathBuf; | 20 | use vfs::AbsPathBuf; |
21 | 21 | ||
22 | use crate::{caps::enabled_resolve_capabilities, diagnostics::DiagnosticsMapConfig}; | 22 | use crate::{caps::enabled_completions_resolve_capabilities, diagnostics::DiagnosticsMapConfig}; |
23 | 23 | ||
24 | #[derive(Debug, Clone)] | 24 | #[derive(Debug, Clone)] |
25 | pub struct Config { | 25 | pub 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 | ||
7 | use ide::{ | 7 | use 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 | }; |
14 | use ide_db::{ | 14 | use 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 | }; |
18 | use itertools::Itertools; | 18 | use itertools::Itertools; |
19 | use rustc_hash::FxHashSet; | ||
20 | use syntax::{algo, SyntaxKind, TextRange, TextSize}; | 19 | use syntax::{algo, SyntaxKind, TextRange, TextSize}; |
21 | 20 | ||
22 | use crate::{ | 21 | use 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#" |