From d9bd1f171dde11ff04f0619b14d8f25e5e4fc56e Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 2 Dec 2020 23:55:35 +0200 Subject: Add eager resolve capability --- crates/completion/src/config.rs | 4 ++++ crates/completion/src/item.rs | 36 ++++++++++++++++++++++++---- crates/completion/src/render.rs | 4 ++-- crates/completion/src/render/enum_variant.rs | 2 +- crates/completion/src/render/function.rs | 2 +- crates/completion/src/render/macro_.rs | 2 +- crates/completion/src/test_utils.rs | 2 +- crates/rust-analyzer/src/handlers.rs | 4 ++-- 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 { pub fn allow_snippets(&mut self, yes: bool) { self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None } } + + pub fn should_resolve_immediately(&self) -> bool { + !self.resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits) + } } #[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 @@ use std::fmt; use hir::{Documentation, ModPath, Mutability}; -use ide_db::helpers::insert_use::{ImportScope, MergeBehaviour}; -use syntax::TextRange; +use ide_db::helpers::{ + insert_use::{self, ImportScope, MergeBehaviour}, + mod_path_to_ast, +}; +use syntax::{algo, TextRange}; use text_edit::TextEdit; use crate::config::SnippetCap; @@ -207,6 +210,7 @@ impl CompletionItem { score: None, ref_match: None, import_to_add: None, + resolve_import_immediately: true, } } @@ -279,6 +283,7 @@ pub(crate) struct Builder { source_range: TextRange, completion_kind: CompletionKind, import_to_add: Option, + resolve_import_immediately: bool, label: String, insert_text: Option, insert_text_format: InsertTextFormat, @@ -300,6 +305,7 @@ impl Builder { let mut label = self.label; let mut lookup = self.lookup; let mut insert_text = self.insert_text; + let mut text_edits = TextEdit::builder(); if let Some(import_to_add) = self.import_to_add.as_ref() { let mut import_path_without_last_segment = import_to_add.import_path.to_owned(); @@ -314,20 +320,35 @@ impl Builder { } label = format!("{}::{}", import_path_without_last_segment, label); } + + if self.resolve_import_immediately { + let rewriter = insert_use::insert_use( + &import_to_add.import_scope, + mod_path_to_ast(&import_to_add.import_path), + import_to_add.merge_behaviour, + ); + if let Some(old_ast) = rewriter.rewrite_root() { + algo::diff(&old_ast, &rewriter.rewrite(&old_ast)) + .into_text_edit(&mut text_edits); + } + } } - let text_edit = match self.text_edit { + let original_edit = match self.text_edit { Some(it) => it, None => { TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone())) } }; + let mut resulting_edit = text_edits.finish(); + resulting_edit.union(original_edit).expect("Failed to unite text edits"); + CompletionItem { source_range: self.source_range, label, insert_text_format: self.insert_text_format, - text_edit, + text_edit: resulting_edit, detail: self.detail, documentation: self.documentation, lookup, @@ -400,8 +421,13 @@ impl Builder { self.trigger_call_info = Some(true); self } - pub(crate) fn add_import(mut self, import_to_add: Option) -> Builder { + pub(crate) fn add_import( + mut self, + import_to_add: Option, + resolve_import_immediately: bool, + ) -> Builder { self.import_to_add = import_to_add; + self.resolve_import_immediately = resolve_import_immediately; self } 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> { local_name, ) .kind(CompletionItemKind::UnresolvedReference) - .add_import(import_to_add) + .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) .build(); return Some(item); } @@ -249,7 +249,7 @@ impl<'a> Render<'a> { let item = item .kind(kind) - .add_import(import_to_add) + .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) .set_documentation(docs) .set_ref_match(ref_match) .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> { .kind(CompletionItemKind::EnumVariant) .set_documentation(self.variant.docs(self.ctx.db())) .set_deprecated(self.ctx.is_deprecated(self.variant)) - .add_import(import_to_add) + .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) .detail(self.detail()); 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> { .set_deprecated(self.ctx.is_deprecated(self.func)) .detail(self.detail()) .add_call_parens(self.ctx.completion, self.name, params) - .add_import(import_to_add) + .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) .build() } 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> { .kind(CompletionItemKind::Macro) .set_documentation(self.docs.clone()) .set_deprecated(self.ctx.is_deprecated(self.macro_)) - .add_import(import_to_add) + .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) .detail(self.detail()); 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( .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions)); let mut actual = db.file_text(position.file_id).to_string(); completion.text_edit().apply(&mut actual); - // TODO kb how to apply imports now? + // git how to apply imports now? assert_eq_text!(&ra_fixture_after, &actual) } 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( for supported_completion_resolve_cap in &snap.config.completion.resolve_capabilities { match supported_completion_resolve_cap { ide::CompletionResolveCapability::AdditionalTextEdits => { - // TODO kb actually add all additional edits here? + // FIXME actually add all additional edits here? if let Some(import_to_add) = server_completion_data.item.import_to_add() { append_import_edits( &mut original_completion, @@ -633,7 +633,7 @@ pub(crate) fn handle_resolve_completion( ); } } - // TODO kb calculate the rest also? + // FIXME resolve the other capabilities also? _ => {} } } -- cgit v1.2.3