diff --git a/crates/ty_server/src/capabilities.rs b/crates/ty_server/src/capabilities.rs index fed7ac811e..bda8546b3d 100644 --- a/crates/ty_server/src/capabilities.rs +++ b/crates/ty_server/src/capabilities.rs @@ -36,6 +36,7 @@ bitflags::bitflags! { const DIAGNOSTIC_DYNAMIC_REGISTRATION = 1 << 14; const WORKSPACE_CONFIGURATION = 1 << 15; const RENAME_DYNAMIC_REGISTRATION = 1 << 16; + const COMPLETION_ITEM_LABEL_DETAILS_SUPPORT = 1 << 17; } } @@ -158,6 +159,11 @@ impl ResolvedClientCapabilities { self.contains(Self::RENAME_DYNAMIC_REGISTRATION) } + /// Returns `true` if the client supports "label details" in completion items. + pub(crate) const fn supports_completion_item_label_details(self) -> bool { + self.contains(Self::COMPLETION_ITEM_LABEL_DETAILS_SUPPORT) + } + pub(super) fn new(client_capabilities: &ClientCapabilities) -> Self { let mut flags = Self::empty(); @@ -314,6 +320,15 @@ impl ResolvedClientCapabilities { flags |= Self::WORK_DONE_PROGRESS; } + if text_document + .and_then(|text_document| text_document.completion.as_ref()) + .and_then(|completion| completion.completion_item.as_ref()) + .and_then(|completion_item| completion_item.label_details_support) + .unwrap_or_default() + { + flags |= Self::COMPLETION_ITEM_LABEL_DETAILS_SUPPORT; + } + flags } } diff --git a/crates/ty_server/src/server/api/requests/completion.rs b/crates/ty_server/src/server/api/requests/completion.rs index 35e1c3fd25..a3e7d91f94 100644 --- a/crates/ty_server/src/server/api/requests/completion.rs +++ b/crates/ty_server/src/server/api/requests/completion.rs @@ -81,15 +81,30 @@ impl BackgroundDocumentRequestHandler for CompletionRequestHandler { new_text: edit.content().map(ToString::to_string).unwrap_or_default(), } }); + + let name = comp.name.to_string(); + let import_suffix = comp.module_name.map(|name| format!(" (import {name})")); + let (label, label_details) = if snapshot + .resolved_client_capabilities() + .supports_completion_item_label_details() + { + let label_details = CompletionItemLabelDetails { + detail: import_suffix, + description: type_display.clone(), + }; + (name, Some(label_details)) + } else { + let label = import_suffix + .map(|suffix| format!("{name}{suffix}")) + .unwrap_or_else(|| name); + (label, None) + }; CompletionItem { - label: comp.name.into(), + label, kind, sort_text: Some(format!("{i:-max_index_len$}")), - detail: type_display.clone(), - label_details: Some(CompletionItemLabelDetails { - detail: comp.module_name.map(|name| format!(" (import {name})")), - description: type_display, - }), + detail: type_display, + label_details, insert_text: comp.insert.map(String::from), additional_text_edits: import_edit.map(|edit| vec![edit]), documentation: comp