From 008d5130b7dce96693cd9c39cd5e71d9dc73bd5b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 22 Sep 2024 20:10:15 +0300 Subject: [PATCH] Prepare for omittiong parts of completion data that need to be resolved --- .../crates/ide-completion/src/config.rs | 3 +- .../crates/ide-completion/src/lib.rs | 29 ++++++++++++++++++ .../crates/ide-completion/src/tests.rs | 5 ++-- src/tools/rust-analyzer/crates/ide/src/lib.rs | 4 +-- .../crates/rust-analyzer/src/config.rs | 19 +++++++++--- .../rust-analyzer/src/handlers/request.rs | 2 ++ .../src/integrated_benchmarks.rs | 6 +++- .../rust-analyzer/src/lsp/capabilities.rs | 16 +++++++++- .../crates/rust-analyzer/src/lsp/ext.rs | 1 + .../crates/rust-analyzer/src/lsp/to_proto.rs | 30 +++++++++++++++---- 10 files changed, 99 insertions(+), 16 deletions(-) diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs index 0d403f49b7a87..1d05419c96dea 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs @@ -7,7 +7,7 @@ use hir::ImportPathConfig; use ide_db::{imports::insert_use::InsertUseConfig, SnippetCap}; -use crate::snippet::Snippet; +use crate::{snippet::Snippet, CompletionFieldsToResolve}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct CompletionConfig { @@ -27,6 +27,7 @@ pub struct CompletionConfig { pub prefer_absolute: bool, pub snippets: Vec, pub limit: Option, + pub fields_to_resolve: CompletionFieldsToResolve, } #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs index 58d1fad09504f..1e022cf244b98 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -37,6 +37,35 @@ pub use crate::{ snippet::{Snippet, SnippetScope}, }; +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub struct CompletionFieldsToResolve { + pub resolve_label_details: bool, + pub resolve_tags: bool, + pub resolve_detail: bool, + pub resolve_documentation: bool, + pub resolve_sort_text: bool, + pub resolve_filter_text: bool, + pub resolve_text_edit: bool, + // FIXME: those are always resolved + // pub resolve_additional_text_edits: bool, + pub resolve_command: bool, +} + +impl CompletionFieldsToResolve { + pub const fn empty() -> Self { + Self { + resolve_label_details: false, + resolve_tags: false, + resolve_detail: false, + resolve_documentation: false, + resolve_sort_text: false, + resolve_filter_text: false, + resolve_text_edit: false, + resolve_command: false, + } + } +} + //FIXME: split the following feature into fine-grained features. // Feature: Magic Completions diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs index 9d77d9700718c..f371012de3f58 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs @@ -37,8 +37,8 @@ use test_fixture::ChangeFixture; use test_utils::assert_eq_text; use crate::{ - resolve_completion_edits, CallableSnippets, CompletionConfig, CompletionItem, - CompletionItemKind, + resolve_completion_edits, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, + CompletionItem, CompletionItemKind, }; /// Lots of basic item definitions @@ -84,6 +84,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig { prefer_absolute: false, snippets: Vec::new(), limit: None, + fields_to_resolve: CompletionFieldsToResolve::empty(), }; pub(crate) fn completion_list(ra_fixture: &str) -> String { diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index 547286c3f4d64..c46c4c8ce94bb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -119,8 +119,8 @@ pub use ide_assists::{ Assist, AssistConfig, AssistId, AssistKind, AssistResolveStrategy, SingleResolve, }; pub use ide_completion::{ - CallableSnippets, CompletionConfig, CompletionItem, CompletionItemKind, CompletionRelevance, - Snippet, SnippetScope, + CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem, + CompletionItemKind, CompletionRelevance, Snippet, SnippetScope, }; pub use ide_db::{ base_db::{Cancelled, CrateGraph, CrateId, FileChange, SourceRoot, SourceRootId}, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 4cc60695fe668..a8a7e02ac38ec 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -12,10 +12,10 @@ use std::{ use cfg::{CfgAtom, CfgDiff}; use hir::Symbol; use ide::{ - AssistConfig, CallableSnippets, CompletionConfig, DiagnosticsConfig, ExprFillDefaultMode, - GenericParameterHints, HighlightConfig, HighlightRelatedConfig, HoverConfig, HoverDocFormat, - InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig, MemoryLayoutHoverConfig, - MemoryLayoutHoverRenderKind, Snippet, SnippetScope, SourceRootId, + AssistConfig, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, DiagnosticsConfig, + ExprFillDefaultMode, GenericParameterHints, HighlightConfig, HighlightRelatedConfig, + HoverConfig, HoverDocFormat, InlayFieldsToResolve, InlayHintsConfig, JoinLinesConfig, + MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, Snippet, SnippetScope, SourceRootId, }; use ide_db::{ imports::insert_use::{ImportGranularity, InsertUseConfig, PrefixKind}, @@ -1391,6 +1391,7 @@ impl Config { } pub fn completion(&self, source_root: Option) -> CompletionConfig { + let client_capability_fields = self.completion_resolve_support_properties(); CompletionConfig { enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(), enable_imports_on_the_fly: self.completion_autoimport_enable(source_root).to_owned() @@ -1415,6 +1416,16 @@ 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_sort_text: client_capability_fields.contains("sortText"), + resolve_filter_text: client_capability_fields.contains("filterText"), + resolve_text_edit: client_capability_fields.contains("textEdit"), + resolve_command: client_capability_fields.contains("command"), + }, } } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index bcbd970a0d214..9e3226fe79834 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -1019,9 +1019,11 @@ pub(crate) fn handle_completion( let items = to_proto::completion_items( &snap.config, + &completion_config.fields_to_resolve, &line_index, snap.file_version(position.file_id), text_document_position, + completion_trigger_character, items, ); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs index 118469df730ce..be0509a19aa78 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -12,7 +12,8 @@ use hir::ChangeWithProcMacros; use ide::{ - AnalysisHost, CallableSnippets, CompletionConfig, DiagnosticsConfig, FilePosition, TextSize, + AnalysisHost, CallableSnippets, CompletionConfig, CompletionFieldsToResolve, DiagnosticsConfig, + FilePosition, TextSize, }; use ide_db::{ imports::insert_use::{ImportGranularity, InsertUseConfig}, @@ -168,6 +169,7 @@ fn integrated_completion_benchmark() { snippets: Vec::new(), limit: None, add_semicolon_to_unit: true, + fields_to_resolve: CompletionFieldsToResolve::empty(), }; let position = FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; @@ -215,6 +217,7 @@ fn integrated_completion_benchmark() { snippets: Vec::new(), limit: None, add_semicolon_to_unit: true, + fields_to_resolve: CompletionFieldsToResolve::empty(), }; let position = FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; @@ -260,6 +263,7 @@ fn integrated_completion_benchmark() { snippets: Vec::new(), limit: None, add_semicolon_to_unit: true, + fields_to_resolve: CompletionFieldsToResolve::empty(), }; let position = FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() }; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs index 9610808c27e18..e5df7947f2d72 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs @@ -458,7 +458,21 @@ impl ClientCapabilities { .into_iter() .flatten() .cloned() - .collect::>() + .collect() + } + + pub fn completion_resolve_support_properties(&self) -> FxHashSet { + self.0 + .text_document + .as_ref() + .and_then(|text| text.completion.as_ref()) + .and_then(|completion_caps| completion_caps.completion_item.as_ref()) + .and_then(|completion_item_caps| completion_item_caps.resolve_support.as_ref()) + .map(|resolve_support| resolve_support.properties.iter()) + .into_iter() + .flatten() + .cloned() + .collect() } pub fn hover_markdown_support(&self) -> bool { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index 618481bbc66b6..990fadc6719ca 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -825,6 +825,7 @@ pub struct CompletionResolveData { pub position: lsp_types::TextDocumentPositionParams, pub imports: Vec, pub version: Option, + pub completion_trigger_character: Option, } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index 4902c9f88c143..6e6a70bb3bcaa 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -6,9 +6,9 @@ use std::{ }; use ide::{ - Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionItem, - CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, - Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, + Annotation, AnnotationKind, Assist, AssistKind, Cancellable, CompletionFieldsToResolve, + CompletionItem, CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, + FileSystemEdit, Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp, SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize, @@ -227,9 +227,11 @@ pub(crate) fn snippet_text_edit_vec( pub(crate) fn completion_items( config: &Config, + fields_to_resolve: &CompletionFieldsToResolve, line_index: &LineIndex, version: Option, tdpp: lsp_types::TextDocumentPositionParams, + completion_trigger_character: Option, mut items: Vec, ) -> Vec { if config.completion_hide_deprecated() { @@ -239,7 +241,17 @@ pub(crate) fn completion_items( let max_relevance = items.iter().map(|it| it.relevance.score()).max().unwrap_or_default(); let mut res = Vec::with_capacity(items.len()); for item in items { - completion_item(&mut res, config, line_index, version, &tdpp, max_relevance, item); + completion_item( + &mut res, + config, + fields_to_resolve, + line_index, + version, + &tdpp, + max_relevance, + completion_trigger_character, + item, + ); } if let Some(limit) = config.completion(None).limit { @@ -253,10 +265,12 @@ pub(crate) fn completion_items( fn completion_item( acc: &mut Vec, config: &Config, + fields_to_resolve: &CompletionFieldsToResolve, line_index: &LineIndex, version: Option, tdpp: &lsp_types::TextDocumentPositionParams, max_relevance: u32, + completion_trigger_character: Option, item: CompletionItem, ) { let insert_replace_support = config.insert_replace_support().then_some(tdpp.position); @@ -264,6 +278,7 @@ fn completion_item( let lookup = item.lookup().to_owned(); let mut additional_text_edits = Vec::new(); + let mut something_to_resolve = false; // LSP does not allow arbitrary edits in completion, so we have to do a // non-trivial mapping here. @@ -337,7 +352,12 @@ fn completion_item( }) .collect::>(); if !imports.is_empty() { - let data = lsp_ext::CompletionResolveData { position: tdpp.clone(), imports, version }; + let data = lsp_ext::CompletionResolveData { + position: tdpp.clone(), + imports, + version, + completion_trigger_character, + }; lsp_item.data = Some(to_value(data).unwrap()); } }