aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/completion/src/config.rs17
-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/rust-analyzer/src/config.rs2
-rw-r--r--crates/rust-analyzer/src/handlers.rs77
-rw-r--r--crates/rust-analyzer/src/to_proto.rs62
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
10use ide::{ 10use 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};
14use ide_db::helpers::{insert_use, mod_path_to_ast};
14use itertools::Itertools; 15use itertools::Itertools;
15use lsp_server::ErrorCode; 16use lsp_server::ErrorCode;
16use lsp_types::{ 17use 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
43pub(crate) fn handle_analyzer_status( 44pub(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
1602fn 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
1618fn 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::{
7use ide::{ 7use 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};
14use ide_db::{
15 base_db::{FileId, FileRange},
16 helpers::{insert_use, mod_path_to_ast},
17}; 12};
13use ide_db::base_db::{FileId, FileRange};
18use itertools::Itertools; 14use itertools::Itertools;
19use syntax::{algo, SyntaxKind, TextRange, TextSize}; 15use syntax::{SyntaxKind, TextRange, TextSize};
20 16
21use crate::{ 17use 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
831pub(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
856pub(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)]
873mod tests { 821mod 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#"