diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/completion/src/config.rs | 17 | ||||
-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/rust-analyzer/src/config.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 77 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 62 |
8 files changed, 80 insertions, 103 deletions
diff --git a/crates/completion/src/config.rs b/crates/completion/src/config.rs index f2fa5c27b..eacdd3449 100644 --- a/crates/completion/src/config.rs +++ b/crates/completion/src/config.rs | |||
@@ -15,12 +15,12 @@ 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 | /// A set of capabilities, enabled on the client and supported on the server. |
19 | pub resolve_capabilities: FxHashSet<CompletionResolveCapability>, | 19 | pub active_resolve_capabilities: FxHashSet<CompletionResolveCapability>, |
20 | } | 20 | } |
21 | 21 | ||
22 | /// A resolve capability, supported on a server. | 22 | /// A resolve capability, supported on the server. |
23 | /// If the client registers any of those in its completion resolve capabilities, | 23 | /// If the client registers any completion resolve capabilities, |
24 | /// the server is able to render completion items' corresponding fields later, | 24 | /// the server is able to render completion items' corresponding fields later, |
25 | /// not during an initial completion item request. | 25 | /// not during an initial completion item request. |
26 | /// See https://github.com/rust-analyzer/rust-analyzer/issues/6366 for more details. | 26 | /// See https://github.com/rust-analyzer/rust-analyzer/issues/6366 for more details. |
@@ -37,8 +37,11 @@ impl CompletionConfig { | |||
37 | } | 37 | } |
38 | 38 | ||
39 | /// Whether the completions' additional edits are calculated later, during a resolve request or not. | 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 { | 40 | /// See `CompletionResolveCapability` for the details. |
41 | !self.resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits) | 41 | pub fn resolve_edits_immediately(&self) -> bool { |
42 | !self | ||
43 | .active_resolve_capabilities | ||
44 | .contains(&CompletionResolveCapability::AdditionalTextEdits) | ||
42 | } | 45 | } |
43 | } | 46 | } |
44 | 47 | ||
@@ -56,7 +59,7 @@ impl Default for CompletionConfig { | |||
56 | add_call_argument_snippets: true, | 59 | add_call_argument_snippets: true, |
57 | snippet_cap: Some(SnippetCap { _private: () }), | 60 | snippet_cap: Some(SnippetCap { _private: () }), |
58 | merge: Some(MergeBehaviour::Full), | 61 | merge: Some(MergeBehaviour::Full), |
59 | resolve_capabilities: FxHashSet::default(), | 62 | active_resolve_capabilities: FxHashSet::default(), |
60 | } | 63 | } |
61 | } | 64 | } |
62 | } | 65 | } |
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs index 3a793000b..2b4f1ea14 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs | |||
@@ -194,10 +194,7 @@ impl<'a> Render<'a> { | |||
194 | local_name, | 194 | local_name, |
195 | ) | 195 | ) |
196 | .kind(CompletionItemKind::UnresolvedReference) | 196 | .kind(CompletionItemKind::UnresolvedReference) |
197 | .add_import( | 197 | .add_import(import_to_add, self.ctx.completion.config.resolve_edits_immediately()) |
198 | import_to_add, | ||
199 | self.ctx.completion.config.should_resolve_additional_edits_immediately(), | ||
200 | ) | ||
201 | .build(); | 198 | .build(); |
202 | return Some(item); | 199 | return Some(item); |
203 | } | 200 | } |
@@ -252,10 +249,7 @@ impl<'a> Render<'a> { | |||
252 | 249 | ||
253 | let item = item | 250 | let item = item |
254 | .kind(kind) | 251 | .kind(kind) |
255 | .add_import( | 252 | .add_import(import_to_add, self.ctx.completion.config.resolve_edits_immediately()) |
256 | import_to_add, | ||
257 | self.ctx.completion.config.should_resolve_additional_edits_immediately(), | ||
258 | ) | ||
259 | .set_documentation(docs) | 253 | .set_documentation(docs) |
260 | .set_ref_match(ref_match) | 254 | .set_ref_match(ref_match) |
261 | .build(); | 255 | .build(); |
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs index 6548b4676..4a91fe3c7 100644 --- a/crates/completion/src/render/enum_variant.rs +++ b/crates/completion/src/render/enum_variant.rs | |||
@@ -71,10 +71,7 @@ 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( | 74 | .add_import(import_to_add, self.ctx.completion.config.resolve_edits_immediately()) |
75 | import_to_add, | ||
76 | self.ctx.completion.config.should_resolve_additional_edits_immediately(), | ||
77 | ) | ||
78 | .detail(self.detail()); | 75 | .detail(self.detail()); |
79 | 76 | ||
80 | if self.variant_kind == StructKind::Tuple { | 77 | if self.variant_kind == StructKind::Tuple { |
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs index b13e0dafc..20f2b9b7e 100644 --- a/crates/completion/src/render/function.rs +++ b/crates/completion/src/render/function.rs | |||
@@ -47,10 +47,7 @@ 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( | 50 | .add_import(import_to_add, self.ctx.completion.config.resolve_edits_immediately()) |
51 | import_to_add, | ||
52 | self.ctx.completion.config.should_resolve_additional_edits_immediately(), | ||
53 | ) | ||
54 | .build() | 51 | .build() |
55 | } | 52 | } |
56 | 53 | ||
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs index 7a8eeb7b9..be7c53659 100644 --- a/crates/completion/src/render/macro_.rs +++ b/crates/completion/src/render/macro_.rs | |||
@@ -50,10 +50,7 @@ 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( | 53 | .add_import(import_to_add, self.ctx.completion.config.resolve_edits_immediately()) |
54 | import_to_add, | ||
55 | self.ctx.completion.config.should_resolve_additional_edits_immediately(), | ||
56 | ) | ||
57 | .detail(self.detail()); | 54 | .detail(self.detail()); |
58 | 55 | ||
59 | let needs_bang = self.needs_bang(); | 56 | let needs_bang = self.needs_bang(); |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 5ce7ae426..f00605258 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -388,7 +388,7 @@ impl Config { | |||
388 | } | 388 | } |
389 | 389 | ||
390 | self.completion.allow_snippets(false); | 390 | self.completion.allow_snippets(false); |
391 | self.completion.resolve_capabilities = | 391 | self.completion.active_resolve_capabilities = |
392 | enabled_completions_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 { |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 2dc62ee51..55c7b0c66 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -8,9 +8,10 @@ use std::{ | |||
8 | }; | 8 | }; |
9 | 9 | ||
10 | use ide::{ | 10 | use ide::{ |
11 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, NavigationTarget, Query, | 11 | FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData, ImportToAdd, LineIndex, |
12 | RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit, | 12 | NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit, |
13 | }; | 13 | }; |
14 | use ide_db::helpers::{insert_use, mod_path_to_ast}; | ||
14 | use itertools::Itertools; | 15 | use itertools::Itertools; |
15 | use lsp_server::ErrorCode; | 16 | use lsp_server::ErrorCode; |
16 | use lsp_types::{ | 17 | use lsp_types::{ |
@@ -35,9 +36,9 @@ use crate::{ | |||
35 | config::RustfmtConfig, | 36 | config::RustfmtConfig, |
36 | from_json, from_proto, | 37 | from_json, from_proto, |
37 | global_state::{CompletionResolveData, GlobalState, GlobalStateSnapshot}, | 38 | global_state::{CompletionResolveData, GlobalState, GlobalStateSnapshot}, |
39 | line_endings::LineEndings, | ||
38 | lsp_ext::{self, InlayHint, InlayHintsParams}, | 40 | lsp_ext::{self, InlayHint, InlayHintsParams}, |
39 | to_proto::{self, append_import_edits}, | 41 | to_proto, LspError, Result, |
40 | LspError, Result, | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | pub(crate) fn handle_analyzer_status( | 44 | pub(crate) fn handle_analyzer_status( |
@@ -577,20 +578,19 @@ pub(crate) fn handle_completion( | |||
577 | .into_iter() | 578 | .into_iter() |
578 | .enumerate() | 579 | .enumerate() |
579 | .flat_map(|(item_index, item)| { | 580 | .flat_map(|(item_index, item)| { |
580 | let mut new_completion_items = to_proto::completion_item( | 581 | let mut new_completion_items = |
581 | &line_index, | 582 | to_proto::completion_item(&line_index, line_endings, item.clone()); |
582 | line_endings, | 583 | |
583 | item.clone(), | 584 | if !snap.config.completion.active_resolve_capabilities.is_empty() { |
584 | snap.config.completion.should_resolve_additional_edits_immediately(), | 585 | let item_id = serde_json::to_value(&item_index) |
585 | ); | 586 | .expect(&format!("Should be able to serialize usize value {}", item_index)); |
586 | 587 | completion_resolve_data | |
587 | let item_id = serde_json::to_value(&item_index) | 588 | .insert(item_index, CompletionResolveData { file_id: position.file_id, item }); |
588 | .expect(&format!("Should be able to serialize usize value {}", item_index)); | 589 | for new_item in &mut new_completion_items { |
589 | completion_resolve_data | 590 | new_item.data = Some(item_id.clone()); |
590 | .insert(item_index, CompletionResolveData { file_id: position.file_id, item }); | 591 | } |
591 | for new_item in &mut new_completion_items { | ||
592 | new_item.data = Some(item_id.clone()); | ||
593 | } | 592 | } |
593 | |||
594 | new_completion_items | 594 | new_completion_items |
595 | }) | 595 | }) |
596 | .collect(); | 596 | .collect(); |
@@ -620,7 +620,7 @@ pub(crate) fn handle_resolve_completion( | |||
620 | }; | 620 | }; |
621 | 621 | ||
622 | let snap = &global_state.snapshot(); | 622 | let snap = &global_state.snapshot(); |
623 | for supported_completion_resolve_cap in &snap.config.completion.resolve_capabilities { | 623 | for supported_completion_resolve_cap in &snap.config.completion.active_resolve_capabilities { |
624 | match supported_completion_resolve_cap { | 624 | match supported_completion_resolve_cap { |
625 | ide::CompletionResolveCapability::AdditionalTextEdits => { | 625 | ide::CompletionResolveCapability::AdditionalTextEdits => { |
626 | // FIXME actually add all additional edits here? | 626 | // FIXME actually add all additional edits here? |
@@ -1598,3 +1598,44 @@ fn should_skip_target(runnable: &Runnable, cargo_spec: Option<&CargoTargetSpec>) | |||
1598 | _ => false, | 1598 | _ => false, |
1599 | } | 1599 | } |
1600 | } | 1600 | } |
1601 | |||
1602 | fn append_import_edits( | ||
1603 | completion: &mut lsp_types::CompletionItem, | ||
1604 | import_to_add: &ImportToAdd, | ||
1605 | line_index: &LineIndex, | ||
1606 | line_endings: LineEndings, | ||
1607 | ) { | ||
1608 | let new_edits = import_into_edits(import_to_add, line_index, line_endings); | ||
1609 | if let Some(original_additional_edits) = completion.additional_text_edits.as_mut() { | ||
1610 | if let Some(mut new_edits) = new_edits { | ||
1611 | original_additional_edits.extend(new_edits.drain(..)) | ||
1612 | } | ||
1613 | } else { | ||
1614 | completion.additional_text_edits = new_edits; | ||
1615 | } | ||
1616 | } | ||
1617 | |||
1618 | fn import_into_edits( | ||
1619 | import_to_add: &ImportToAdd, | ||
1620 | line_index: &LineIndex, | ||
1621 | line_endings: LineEndings, | ||
1622 | ) -> Option<Vec<lsp_types::TextEdit>> { | ||
1623 | let _p = profile::span("add_import_edits"); | ||
1624 | |||
1625 | let rewriter = insert_use::insert_use( | ||
1626 | &import_to_add.import_scope, | ||
1627 | mod_path_to_ast(&import_to_add.import_path), | ||
1628 | import_to_add.merge_behaviour, | ||
1629 | ); | ||
1630 | let old_ast = rewriter.rewrite_root()?; | ||
1631 | let mut import_insert = TextEdit::builder(); | ||
1632 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert); | ||
1633 | let import_edit = import_insert.finish(); | ||
1634 | |||
1635 | Some( | ||
1636 | import_edit | ||
1637 | .into_iter() | ||
1638 | .map(|indel| to_proto::text_edit(line_index, line_endings, indel)) | ||
1639 | .collect_vec(), | ||
1640 | ) | ||
1641 | } | ||
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index f5337f3f1..01eabe852 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -7,16 +7,12 @@ use std::{ | |||
7 | use ide::{ | 7 | use ide::{ |
8 | Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, | 8 | Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, |
9 | FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange, | 9 | FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange, |
10 | ImportToAdd, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, | 10 | Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget, |
11 | NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, | 11 | ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, |
12 | SourceFileEdit, TextEdit, | ||
13 | }; | ||
14 | use ide_db::{ | ||
15 | base_db::{FileId, FileRange}, | ||
16 | helpers::{insert_use, mod_path_to_ast}, | ||
17 | }; | 12 | }; |
13 | use ide_db::base_db::{FileId, FileRange}; | ||
18 | use itertools::Itertools; | 14 | use itertools::Itertools; |
19 | use syntax::{algo, SyntaxKind, TextRange, TextSize}; | 15 | use syntax::{SyntaxKind, TextRange, TextSize}; |
20 | 16 | ||
21 | use crate::{ | 17 | use crate::{ |
22 | cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot, | 18 | cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot, |
@@ -162,7 +158,6 @@ pub(crate) fn completion_item( | |||
162 | line_index: &LineIndex, | 158 | line_index: &LineIndex, |
163 | line_endings: LineEndings, | 159 | line_endings: LineEndings, |
164 | completion_item: CompletionItem, | 160 | completion_item: CompletionItem, |
165 | should_resolve_additional_edits_immediately: bool, | ||
166 | ) -> Vec<lsp_types::CompletionItem> { | 161 | ) -> Vec<lsp_types::CompletionItem> { |
167 | fn set_score(res: &mut lsp_types::CompletionItem, label: &str) { | 162 | fn set_score(res: &mut lsp_types::CompletionItem, label: &str) { |
168 | res.preselect = Some(true); | 163 | res.preselect = Some(true); |
@@ -238,13 +233,7 @@ pub(crate) fn completion_item( | |||
238 | 233 | ||
239 | for mut r in all_results.iter_mut() { | 234 | for mut r in all_results.iter_mut() { |
240 | r.insert_text_format = Some(insert_text_format(completion_item.insert_text_format())); | 235 | r.insert_text_format = Some(insert_text_format(completion_item.insert_text_format())); |
241 | if !should_resolve_additional_edits_immediately { | ||
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 | } | ||
245 | } | ||
246 | } | 236 | } |
247 | |||
248 | all_results | 237 | all_results |
249 | } | 238 | } |
250 | 239 | ||
@@ -828,47 +817,6 @@ pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent { | |||
828 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value } | 817 | lsp_types::MarkupContent { kind: lsp_types::MarkupKind::Markdown, value } |
829 | } | 818 | } |
830 | 819 | ||
831 | pub(crate) fn import_into_edits( | ||
832 | import_to_add: &ImportToAdd, | ||
833 | line_index: &LineIndex, | ||
834 | line_endings: LineEndings, | ||
835 | ) -> Option<Vec<lsp_types::TextEdit>> { | ||
836 | let _p = profile::span("add_import_edits"); | ||
837 | |||
838 | let rewriter = insert_use::insert_use( | ||
839 | &import_to_add.import_scope, | ||
840 | mod_path_to_ast(&import_to_add.import_path), | ||
841 | import_to_add.merge_behaviour, | ||
842 | ); | ||
843 | let old_ast = rewriter.rewrite_root()?; | ||
844 | let mut import_insert = TextEdit::builder(); | ||
845 | algo::diff(&old_ast, &rewriter.rewrite(&old_ast)).into_text_edit(&mut import_insert); | ||
846 | let import_edit = import_insert.finish(); | ||
847 | |||
848 | Some( | ||
849 | import_edit | ||
850 | .into_iter() | ||
851 | .map(|indel| text_edit(line_index, line_endings, indel)) | ||
852 | .collect_vec(), | ||
853 | ) | ||
854 | } | ||
855 | |||
856 | pub(crate) fn append_import_edits( | ||
857 | completion: &mut lsp_types::CompletionItem, | ||
858 | import_to_add: &ImportToAdd, | ||
859 | line_index: &LineIndex, | ||
860 | line_endings: LineEndings, | ||
861 | ) { | ||
862 | let new_edits = import_into_edits(import_to_add, line_index, line_endings); | ||
863 | if let Some(original_additional_edits) = completion.additional_text_edits.as_mut() { | ||
864 | if let Some(mut new_edits) = new_edits { | ||
865 | original_additional_edits.extend(new_edits.drain(..)) | ||
866 | } | ||
867 | } else { | ||
868 | completion.additional_text_edits = new_edits; | ||
869 | } | ||
870 | } | ||
871 | |||
872 | #[cfg(test)] | 820 | #[cfg(test)] |
873 | mod tests { | 821 | mod tests { |
874 | use ide::Analysis; | 822 | use ide::Analysis; |
@@ -897,7 +845,7 @@ mod tests { | |||
897 | .unwrap() | 845 | .unwrap() |
898 | .into_iter() | 846 | .into_iter() |
899 | .filter(|c| c.label().ends_with("arg")) | 847 | .filter(|c| c.label().ends_with("arg")) |
900 | .map(|c| completion_item(&line_index, LineEndings::Unix, c, true)) | 848 | .map(|c| completion_item(&line_index, LineEndings::Unix, c)) |
901 | .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text))) | 849 | .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text))) |
902 | .collect(); | 850 | .collect(); |
903 | expect_test::expect![[r#" | 851 | expect_test::expect![[r#" |