From 4261ac7856e5f88d16993edd3ff7631c8e7abe10 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 3 Dec 2024 10:41:29 +0200 Subject: [PATCH] Advertise completions and inlay hints resolve server capabilities based on the client capabilities. --- crates/ide-completion/src/lib.rs | 14 ++++++++++++- crates/ide/src/inlay_hints.rs | 12 ++++++++++- crates/rust-analyzer/src/config.rs | 22 ++++++-------------- crates/rust-analyzer/src/lsp/capabilities.rs | 19 +++++++++++++---- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs index dfee01b187e9..cffdfa29f1a3 100644 --- a/crates/ide-completion/src/lib.rs +++ b/crates/ide-completion/src/lib.rs @@ -19,7 +19,7 @@ use ide_db::{ }, items_locator, syntax_helpers::tree_diff::diff, - FilePosition, RootDatabase, + FilePosition, FxHashSet, RootDatabase, }; use crate::{ @@ -50,6 +50,18 @@ pub struct CompletionFieldsToResolve { } impl CompletionFieldsToResolve { + pub fn from_client_capabilities(client_capability_fields: &FxHashSet<&str>) -> Self { + Self { + resolve_label_details: client_capability_fields.contains("labelDetails"), + resolve_tags: client_capability_fields.contains("tags"), + resolve_detail: client_capability_fields.contains("detail"), + resolve_documentation: client_capability_fields.contains("documentation"), + resolve_filter_text: client_capability_fields.contains("filterText"), + resolve_text_edit: client_capability_fields.contains("textEdit"), + resolve_command: client_capability_fields.contains("command"), + } + } + pub const fn empty() -> Self { Self { resolve_label_details: false, diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index c58ca0f01cd6..1ae8bfa9b6e1 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs @@ -8,8 +8,8 @@ use hir::{ sym, ClosureStyle, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef, ModuleDefId, Semantics, }; -use ide_db::text_edit::TextEdit; use ide_db::{famous_defs::FamousDefs, FileRange, RootDatabase}; +use ide_db::{text_edit::TextEdit, FxHashSet}; use itertools::Itertools; use smallvec::{smallvec, SmallVec}; use span::{Edition, EditionedFileId}; @@ -289,6 +289,16 @@ pub struct InlayFieldsToResolve { } impl InlayFieldsToResolve { + pub fn from_client_capabilities(client_capability_fields: &FxHashSet<&str>) -> Self { + Self { + resolve_text_edits: client_capability_fields.contains("textEdits"), + resolve_hint_tooltip: client_capability_fields.contains("tooltip"), + resolve_label_tooltip: client_capability_fields.contains("label.tooltip"), + resolve_label_location: client_capability_fields.contains("label.location"), + resolve_label_command: client_capability_fields.contains("label.command"), + } + } + pub const fn empty() -> Self { Self { resolve_text_edits: false, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 37d45255e29d..152ce2944a0d 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -1446,15 +1446,9 @@ impl Config { limit: self.completion_limit(source_root).to_owned(), enable_term_search: self.completion_termSearch_enable(source_root).to_owned(), term_search_fuel: self.completion_termSearch_fuel(source_root).to_owned() as u64, - fields_to_resolve: CompletionFieldsToResolve { - resolve_label_details: client_capability_fields.contains("labelDetails"), - resolve_tags: client_capability_fields.contains("tags"), - resolve_detail: client_capability_fields.contains("detail"), - resolve_documentation: client_capability_fields.contains("documentation"), - resolve_filter_text: client_capability_fields.contains("filterText"), - resolve_text_edit: client_capability_fields.contains("textEdit"), - resolve_command: client_capability_fields.contains("command"), - }, + fields_to_resolve: CompletionFieldsToResolve::from_client_capabilities( + &client_capability_fields, + ), } } @@ -1614,13 +1608,9 @@ impl Config { } else { None }, - fields_to_resolve: InlayFieldsToResolve { - resolve_text_edits: client_capability_fields.contains("textEdits"), - resolve_hint_tooltip: client_capability_fields.contains("tooltip"), - resolve_label_tooltip: client_capability_fields.contains("label.tooltip"), - resolve_label_location: client_capability_fields.contains("label.location"), - resolve_label_command: client_capability_fields.contains("label.command"), - }, + fields_to_resolve: InlayFieldsToResolve::from_client_capabilities( + &client_capability_fields, + ), implicit_drop_hints: self.inlayHints_implicitDrops_enable().to_owned(), range_exclusive_hints: self.inlayHints_rangeExclusiveHints_enable().to_owned(), } diff --git a/crates/rust-analyzer/src/lsp/capabilities.rs b/crates/rust-analyzer/src/lsp/capabilities.rs index 1db616898e8d..bd496e8ddc36 100644 --- a/crates/rust-analyzer/src/lsp/capabilities.rs +++ b/crates/rust-analyzer/src/lsp/capabilities.rs @@ -1,4 +1,5 @@ //! Advertises the capabilities of the LSP Server. +use ide::{CompletionFieldsToResolve, InlayFieldsToResolve}; use ide_db::{line_index::WideEncoding, FxHashSet}; use lsp_types::{ CallHierarchyServerCapability, CodeActionKind, CodeActionOptions, CodeActionProviderCapability, @@ -40,7 +41,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { })), hover_provider: Some(HoverProviderCapability::Simple(true)), completion_provider: Some(CompletionOptions { - resolve_provider: config.caps().completions_resolve_provider(), + resolve_provider: Some(config.caps().completions_resolve_provider()), trigger_characters: Some(vec![ ":".to_owned(), ".".to_owned(), @@ -136,7 +137,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities { inlay_hint_provider: Some(OneOf::Right(InlayHintServerCapabilities::Options( InlayHintOptions { work_done_progress_options: Default::default(), - resolve_provider: Some(true), + resolve_provider: Some(config.caps().inlay_hints_resolve_provider()), }, ))), inline_value_provider: None, @@ -176,8 +177,18 @@ impl ClientCapabilities { Self(caps) } - fn completions_resolve_provider(&self) -> Option { - self.completion_item_edit_resolve().then_some(true) + fn completions_resolve_provider(&self) -> bool { + let client_capabilities = self.completion_resolve_support_properties(); + let fields_to_resolve = + CompletionFieldsToResolve::from_client_capabilities(&client_capabilities); + fields_to_resolve != CompletionFieldsToResolve::empty() + } + + fn inlay_hints_resolve_provider(&self) -> bool { + let client_capabilities = self.inlay_hint_resolve_support_properties(); + let fields_to_resolve = + InlayFieldsToResolve::from_client_capabilities(&client_capabilities); + fields_to_resolve != InlayFieldsToResolve::empty() } fn experimental_bool(&self, index: &'static str) -> bool {