aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2020-12-02 21:55:35 +0000
committerKirill Bulatov <[email protected]>2020-12-07 21:41:08 +0000
commitd9bd1f171dde11ff04f0619b14d8f25e5e4fc56e (patch)
treef5dde9ec4ee81337b0c87bb5e547dd3401f8fffd
parent2a7be4afb000d97948bb7f11bcd074fc1e11716e (diff)
Add eager resolve capability
-rw-r--r--crates/completion/src/config.rs4
-rw-r--r--crates/completion/src/item.rs36
-rw-r--r--crates/completion/src/render.rs4
-rw-r--r--crates/completion/src/render/enum_variant.rs2
-rw-r--r--crates/completion/src/render/function.rs2
-rw-r--r--crates/completion/src/render/macro_.rs2
-rw-r--r--crates/completion/src/test_utils.rs2
-rw-r--r--crates/rust-analyzer/src/handlers.rs4
8 files changed, 43 insertions, 13 deletions
diff --git a/crates/completion/src/config.rs b/crates/completion/src/config.rs
index 736af455e..e9a02aeb8 100644
--- a/crates/completion/src/config.rs
+++ b/crates/completion/src/config.rs
@@ -29,6 +29,10 @@ impl CompletionConfig {
29 pub fn allow_snippets(&mut self, yes: bool) { 29 pub fn allow_snippets(&mut self, yes: bool) {
30 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None } 30 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None }
31 } 31 }
32
33 pub fn should_resolve_immediately(&self) -> bool {
34 !self.resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits)
35 }
32} 36}
33 37
34#[derive(Clone, Copy, Debug, PartialEq, Eq)] 38#[derive(Clone, Copy, Debug, PartialEq, Eq)]
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs
index dc67df075..5906637a6 100644
--- a/crates/completion/src/item.rs
+++ b/crates/completion/src/item.rs
@@ -3,8 +3,11 @@
3use std::fmt; 3use std::fmt;
4 4
5use hir::{Documentation, ModPath, Mutability}; 5use hir::{Documentation, ModPath, Mutability};
6use ide_db::helpers::insert_use::{ImportScope, MergeBehaviour}; 6use ide_db::helpers::{
7use syntax::TextRange; 7 insert_use::{self, ImportScope, MergeBehaviour},
8 mod_path_to_ast,
9};
10use syntax::{algo, TextRange};
8use text_edit::TextEdit; 11use text_edit::TextEdit;
9 12
10use crate::config::SnippetCap; 13use crate::config::SnippetCap;
@@ -207,6 +210,7 @@ impl CompletionItem {
207 score: None, 210 score: None,
208 ref_match: None, 211 ref_match: None,
209 import_to_add: None, 212 import_to_add: None,
213 resolve_import_immediately: true,
210 } 214 }
211 } 215 }
212 216
@@ -279,6 +283,7 @@ pub(crate) struct Builder {
279 source_range: TextRange, 283 source_range: TextRange,
280 completion_kind: CompletionKind, 284 completion_kind: CompletionKind,
281 import_to_add: Option<ImportToAdd>, 285 import_to_add: Option<ImportToAdd>,
286 resolve_import_immediately: bool,
282 label: String, 287 label: String,
283 insert_text: Option<String>, 288 insert_text: Option<String>,
284 insert_text_format: InsertTextFormat, 289 insert_text_format: InsertTextFormat,
@@ -300,6 +305,7 @@ impl Builder {
300 let mut label = self.label; 305 let mut label = self.label;
301 let mut lookup = self.lookup; 306 let mut lookup = self.lookup;
302 let mut insert_text = self.insert_text; 307 let mut insert_text = self.insert_text;
308 let mut text_edits = TextEdit::builder();
303 309
304 if let Some(import_to_add) = self.import_to_add.as_ref() { 310 if let Some(import_to_add) = self.import_to_add.as_ref() {
305 let mut import_path_without_last_segment = import_to_add.import_path.to_owned(); 311 let mut import_path_without_last_segment = import_to_add.import_path.to_owned();
@@ -314,20 +320,35 @@ impl Builder {
314 } 320 }
315 label = format!("{}::{}", import_path_without_last_segment, label); 321 label = format!("{}::{}", import_path_without_last_segment, label);
316 } 322 }
323
324 if self.resolve_import_immediately {
325 let rewriter = insert_use::insert_use(
326 &import_to_add.import_scope,
327 mod_path_to_ast(&import_to_add.import_path),
328 import_to_add.merge_behaviour,
329 );
330 if let Some(old_ast) = rewriter.rewrite_root() {
331 algo::diff(&old_ast, &rewriter.rewrite(&old_ast))
332 .into_text_edit(&mut text_edits);
333 }
334 }
317 } 335 }
318 336
319 let text_edit = match self.text_edit { 337 let original_edit = match self.text_edit {
320 Some(it) => it, 338 Some(it) => it,
321 None => { 339 None => {
322 TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone())) 340 TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone()))
323 } 341 }
324 }; 342 };
325 343
344 let mut resulting_edit = text_edits.finish();
345 resulting_edit.union(original_edit).expect("Failed to unite text edits");
346
326 CompletionItem { 347 CompletionItem {
327 source_range: self.source_range, 348 source_range: self.source_range,
328 label, 349 label,
329 insert_text_format: self.insert_text_format, 350 insert_text_format: self.insert_text_format,
330 text_edit, 351 text_edit: resulting_edit,
331 detail: self.detail, 352 detail: self.detail,
332 documentation: self.documentation, 353 documentation: self.documentation,
333 lookup, 354 lookup,
@@ -400,8 +421,13 @@ impl Builder {
400 self.trigger_call_info = Some(true); 421 self.trigger_call_info = Some(true);
401 self 422 self
402 } 423 }
403 pub(crate) fn add_import(mut self, import_to_add: Option<ImportToAdd>) -> Builder { 424 pub(crate) fn add_import(
425 mut self,
426 import_to_add: Option<ImportToAdd>,
427 resolve_import_immediately: bool,
428 ) -> Builder {
404 self.import_to_add = import_to_add; 429 self.import_to_add = import_to_add;
430 self.resolve_import_immediately = resolve_import_immediately;
405 self 431 self
406 } 432 }
407 pub(crate) fn set_ref_match( 433 pub(crate) fn set_ref_match(
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index 504757a6a..b7a3a3935 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -194,7 +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(import_to_add) 197 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately())
198 .build(); 198 .build();
199 return Some(item); 199 return Some(item);
200 } 200 }
@@ -249,7 +249,7 @@ impl<'a> Render<'a> {
249 249
250 let item = item 250 let item = item
251 .kind(kind) 251 .kind(kind)
252 .add_import(import_to_add) 252 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately())
253 .set_documentation(docs) 253 .set_documentation(docs)
254 .set_ref_match(ref_match) 254 .set_ref_match(ref_match)
255 .build(); 255 .build();
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs
index f4bd02f25..c08824c6a 100644
--- a/crates/completion/src/render/enum_variant.rs
+++ b/crates/completion/src/render/enum_variant.rs
@@ -71,7 +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(import_to_add) 74 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately())
75 .detail(self.detail()); 75 .detail(self.detail());
76 76
77 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 00e3eb203..3492384c6 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -47,7 +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(import_to_add) 50 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately())
51 .build() 51 .build()
52 } 52 }
53 53
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index b4ab32c6e..15648b5b7 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -50,7 +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(import_to_add) 53 .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately())
54 .detail(self.detail()); 54 .detail(self.detail());
55 55
56 let needs_bang = self.needs_bang(); 56 let needs_bang = self.needs_bang();
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs
index 516a63b4d..88351ee15 100644
--- a/crates/completion/src/test_utils.rs
+++ b/crates/completion/src/test_utils.rs
@@ -97,7 +97,7 @@ 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 // TODO kb how to apply imports now? 100 // git how to apply imports now?
101 assert_eq_text!(&ra_fixture_after, &actual) 101 assert_eq_text!(&ra_fixture_after, &actual)
102} 102}
103 103
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index a186d2e5d..eeb2f6f93 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -623,7 +623,7 @@ pub(crate) fn handle_resolve_completion(
623 for supported_completion_resolve_cap in &snap.config.completion.resolve_capabilities { 623 for supported_completion_resolve_cap in &snap.config.completion.resolve_capabilities {
624 match supported_completion_resolve_cap { 624 match supported_completion_resolve_cap {
625 ide::CompletionResolveCapability::AdditionalTextEdits => { 625 ide::CompletionResolveCapability::AdditionalTextEdits => {
626 // TODO kb actually add all additional edits here? 626 // FIXME actually add all additional edits here?
627 if let Some(import_to_add) = server_completion_data.item.import_to_add() { 627 if let Some(import_to_add) = server_completion_data.item.import_to_add() {
628 append_import_edits( 628 append_import_edits(
629 &mut original_completion, 629 &mut original_completion,
@@ -633,7 +633,7 @@ pub(crate) fn handle_resolve_completion(
633 ); 633 );
634 } 634 }
635 } 635 }
636 // TODO kb calculate the rest also? 636 // FIXME resolve the other capabilities also?
637 _ => {} 637 _ => {}
638 } 638 }
639 } 639 }