From 50e06ee95ab12bc204fdce557ab0fb7aa5e5ab2f Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 3 Dec 2020 00:13:32 +0200 Subject: Refactor the code --- crates/completion/src/config.rs | 9 ++++++++- crates/completion/src/item.rs | 3 +-- crates/completion/src/render.rs | 10 ++++++++-- crates/completion/src/render/enum_variant.rs | 5 ++++- crates/completion/src/render/function.rs | 5 ++++- crates/completion/src/render/macro_.rs | 5 ++++- crates/completion/src/test_utils.rs | 1 - crates/rust-analyzer/src/caps.rs | 14 ++++++-------- crates/rust-analyzer/src/config.rs | 4 ++-- crates/rust-analyzer/src/handlers.rs | 2 +- crates/rust-analyzer/src/to_proto.rs | 24 ++++++++++-------------- 11 files changed, 48 insertions(+), 34 deletions(-) (limited to 'crates') 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 { pub add_call_argument_snippets: bool, pub snippet_cap: Option, pub merge: Option, + /// A set of capabilities, enabled on the cliend and supported on the server. pub resolve_capabilities: FxHashSet, } +/// A resolve capability, supported on a server. +/// If the client registers any of those in its completion resolve capabilities, +/// the server is able to render completion items' corresponding fields later, +/// not during an initial completion item request. +/// See https://github.com/rust-analyzer/rust-analyzer/issues/6366 for more details. #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] pub enum CompletionResolveCapability { Documentation, @@ -30,7 +36,8 @@ impl CompletionConfig { self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None } } - pub fn should_resolve_immediately(&self) -> bool { + /// Whether the completions' additional edits are calculated later, during a resolve request or not. + pub fn should_resolve_additional_edits_immediately(&self) -> bool { !self.resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits) } } 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 { /// possible match. ref_match: Option<(Mutability, CompletionScore)>, - /// The data later to be used in the `completionItem/resolve` response - /// to add the insert import edit. + /// The import data to add to completion's edits. import_to_add: Option, } 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> { local_name, ) .kind(CompletionItemKind::UnresolvedReference) - .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) + .add_import( + import_to_add, + self.ctx.completion.config.should_resolve_additional_edits_immediately(), + ) .build(); return Some(item); } @@ -249,7 +252,10 @@ impl<'a> Render<'a> { let item = item .kind(kind) - .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) + .add_import( + import_to_add, + self.ctx.completion.config.should_resolve_additional_edits_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 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> { .kind(CompletionItemKind::EnumVariant) .set_documentation(self.variant.docs(self.ctx.db())) .set_deprecated(self.ctx.is_deprecated(self.variant)) - .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) + .add_import( + import_to_add, + self.ctx.completion.config.should_resolve_additional_edits_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 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> { .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, self.ctx.completion.config.should_resolve_immediately()) + .add_import( + import_to_add, + self.ctx.completion.config.should_resolve_additional_edits_immediately(), + ) .build() } 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> { .kind(CompletionItemKind::Macro) .set_documentation(self.docs.clone()) .set_deprecated(self.ctx.is_deprecated(self.macro_)) - .add_import(import_to_add, self.ctx.completion.config.should_resolve_immediately()) + .add_import( + import_to_add, + self.ctx.completion.config.should_resolve_additional_edits_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 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( .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); - // git how to apply imports now? assert_eq_text!(&ra_fixture_after, &actual) } 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 })), hover_provider: Some(HoverProviderCapability::Simple(true)), completion_provider: Some(CompletionOptions { - resolve_provider: Some(true), + resolve_provider: completions_resolve_provider(client_caps), trigger_characters: Some(vec![":".to_string(), ".".to_string()]), work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), @@ -50,9 +50,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti document_symbol_provider: Some(OneOf::Left(true)), workspace_symbol_provider: Some(OneOf::Left(true)), code_action_provider: Some(code_action_capabilities(client_caps)), - code_lens_provider: Some(CodeLensOptions { - resolve_provider: resolve_provider(client_caps), - }), + code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), document_formatting_provider: Some(OneOf::Left(true)), document_range_formatting_provider: None, document_on_type_formatting_provider: Some(DocumentOnTypeFormattingOptions { @@ -97,16 +95,16 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti } } -fn resolve_provider(client_caps: &ClientCapabilities) -> Option { - if enabled_resolve_capabilities(client_caps)?.is_empty() { +fn completions_resolve_provider(client_caps: &ClientCapabilities) -> Option { + if enabled_completions_resolve_capabilities(client_caps)?.is_empty() { None } else { Some(true) } } -/// Parses client capabilities and returns all that rust-analyzer supports. -pub fn enabled_resolve_capabilities( +/// Parses client capabilities and returns all completion resolve capabilities rust-analyzer supports. +pub fn enabled_completions_resolve_capabilities( caps: &ClientCapabilities, ) -> Option> { 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; use serde::Deserialize; use vfs::AbsPathBuf; -use crate::{caps::enabled_resolve_capabilities, diagnostics::DiagnosticsMapConfig}; +use crate::{caps::enabled_completions_resolve_capabilities, diagnostics::DiagnosticsMapConfig}; #[derive(Debug, Clone)] pub struct Config { @@ -389,7 +389,7 @@ impl Config { self.completion.allow_snippets(false); self.completion.resolve_capabilities = - enabled_resolve_capabilities(caps).unwrap_or_default(); + enabled_completions_resolve_capabilities(caps).unwrap_or_default(); if let Some(completion) = &doc_caps.completion { if let Some(completion_item) = &completion.completion_item { 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( &line_index, line_endings, item.clone(), - &snap.config.completion.resolve_capabilities, + snap.config.completion.should_resolve_additional_edits_immediately(), ); 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::{ }; use ide::{ - Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, CompletionResolveCapability, - Documentation, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, - HighlightedRange, ImportToAdd, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, - Markup, NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, + Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, + FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange, + ImportToAdd, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, + NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit, }; use ide_db::{ @@ -16,7 +16,6 @@ use ide_db::{ helpers::{insert_use, mod_path_to_ast}, }; use itertools::Itertools; -use rustc_hash::FxHashSet; use syntax::{algo, SyntaxKind, TextRange, TextSize}; use crate::{ @@ -163,7 +162,7 @@ pub(crate) fn completion_item( line_index: &LineIndex, line_endings: LineEndings, completion_item: CompletionItem, - resolve_capabilities: &FxHashSet, + should_resolve_additional_edits_immediately: bool, ) -> Vec { fn set_score(res: &mut lsp_types::CompletionItem, label: &str) { res.preselect = Some(true); @@ -237,14 +236,12 @@ pub(crate) fn completion_item( None => vec![res], }; - let unapplied_import_data = completion_item.import_to_add().filter(|_| { - !resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits) - }); - for mut r in all_results.iter_mut() { r.insert_text_format = Some(insert_text_format(completion_item.insert_text_format())); - if let Some(unapplied_import_data) = unapplied_import_data { - append_import_edits(r, unapplied_import_data, line_index, line_endings); + if !should_resolve_additional_edits_immediately { + if let Some(unapplied_import_data) = completion_item.import_to_add() { + append_import_edits(r, unapplied_import_data, line_index, line_endings); + } } } @@ -891,7 +888,6 @@ mod tests { let (offset, text) = test_utils::extract_offset(fixture); let line_index = LineIndex::new(&text); let (analysis, file_id) = Analysis::from_single_file(text); - let resolve_caps = FxHashSet::default(); let completions: Vec<(String, Option)> = analysis .completions( &ide::CompletionConfig::default(), @@ -901,7 +897,7 @@ mod tests { .unwrap() .into_iter() .filter(|c| c.label().ends_with("arg")) - .map(|c| completion_item(&line_index, LineEndings::Unix, c, &resolve_caps)) + .map(|c| completion_item(&line_index, LineEndings::Unix, c, true)) .flat_map(|comps| comps.into_iter().map(|c| (c.label, c.sort_text))) .collect(); expect_test::expect![[r#" -- cgit v1.2.3