From cc2686c1a9cf9a9e089f669d9d179812618008a7 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 23 Sep 2024 05:03:54 +0300 Subject: [PATCH] Omit completion fields to be resolved later --- .../crates/ide-completion/src/lib.rs | 4 - .../crates/rust-analyzer/src/config.rs | 1 - .../rust-analyzer/src/handlers/request.rs | 55 +++++----- .../crates/rust-analyzer/src/lsp/to_proto.rs | 101 ++++++++++++------ 4 files changed, 99 insertions(+), 62 deletions(-) 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 1e022cf244b98..a78976d3fd8b8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -43,11 +43,8 @@ pub struct CompletionFieldsToResolve { 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, } @@ -58,7 +55,6 @@ impl CompletionFieldsToResolve { resolve_tags: false, resolve_detail: false, resolve_documentation: false, - resolve_sort_text: false, resolve_filter_text: false, resolve_text_edit: false, resolve_command: false, 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 a8a7e02ac38ec..69dd8aff4284b 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -1421,7 +1421,6 @@ impl Config { 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 9e3226fe79834..7d5a3946db161 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 @@ -1056,33 +1056,36 @@ pub(crate) fn handle_completion_resolve( }; let source_root = snap.analysis.source_root_id(file_id)?; - let additional_edits = snap - .analysis - .resolve_completion_edits( - &snap.config.completion(Some(source_root)), - FilePosition { file_id, offset }, - resolve_data - .imports - .into_iter() - .map(|import| (import.full_import_path, import.imported_name)), - )? - .into_iter() - .flat_map(|edit| edit.into_iter().map(|indel| to_proto::text_edit(&line_index, indel))) - .collect::>(); - - if !all_edits_are_disjoint(&original_completion, &additional_edits) { - return Err(LspError::new( - ErrorCode::InternalError as i32, - "Import edit overlaps with the original completion edits, this is not LSP-compliant" - .into(), - ) - .into()); - } + if !resolve_data.imports.is_empty() { + let additional_edits = snap + .analysis + .resolve_completion_edits( + &snap.config.completion(Some(source_root)), + FilePosition { file_id, offset }, + resolve_data + .imports + .into_iter() + .map(|import| (import.full_import_path, import.imported_name)), + )? + .into_iter() + .flat_map(|edit| edit.into_iter().map(|indel| to_proto::text_edit(&line_index, indel))) + .collect::>(); + + if !all_edits_are_disjoint(&original_completion, &additional_edits) { + return Err(LspError::new( + ErrorCode::InternalError as i32, + "Import edit overlaps with the original completion edits, this is not LSP-compliant" + .into(), + ) + .into()); + } - if let Some(original_additional_edits) = original_completion.additional_text_edits.as_mut() { - original_additional_edits.extend(additional_edits) - } else { - original_completion.additional_text_edits = Some(additional_edits); + if let Some(original_additional_edits) = original_completion.additional_text_edits.as_mut() + { + original_additional_edits.extend(additional_edits) + } else { + original_completion.additional_text_edits = Some(additional_edits); + } } Ok(original_completion) 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 6e6a70bb3bcaa..c7f4b22a77195 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 @@ -275,14 +275,23 @@ fn completion_item( ) { let insert_replace_support = config.insert_replace_support().then_some(tdpp.position); let ref_match = item.ref_match(); - let lookup = item.lookup().to_owned(); let mut additional_text_edits = Vec::new(); let mut something_to_resolve = false; + let filter_text = if fields_to_resolve.resolve_filter_text { + something_to_resolve = !item.lookup().is_empty(); + None + } else { + Some(item.lookup().to_owned()) + }; + // LSP does not allow arbitrary edits in completion, so we have to do a // non-trivial mapping here. - let text_edit = { + let text_edit = if fields_to_resolve.resolve_text_edit { + something_to_resolve = true; + None + } else { let mut text_edit = None; let source_range = item.source_range; for indel in item.text_edit { @@ -305,25 +314,49 @@ fn completion_item( additional_text_edits.push(text_edit); } } - text_edit.unwrap() + Some(text_edit.unwrap()) }; let insert_text_format = item.is_snippet.then_some(lsp_types::InsertTextFormat::SNIPPET); - let tags = item.deprecated.then(|| vec![lsp_types::CompletionItemTag::DEPRECATED]); + let tags = if fields_to_resolve.resolve_tags { + something_to_resolve = item.deprecated; + None + } else { + item.deprecated.then(|| vec![lsp_types::CompletionItemTag::DEPRECATED]) + }; let command = if item.trigger_call_info && config.client_commands().trigger_parameter_hints { - Some(command::trigger_parameter_hints()) + if fields_to_resolve.resolve_command { + something_to_resolve = true; + Some(command::trigger_parameter_hints()) + } else { + None + } } else { None }; + let detail = if fields_to_resolve.resolve_detail { + something_to_resolve = item.detail.is_some(); + None + } else { + item.detail + }; + + let documentation = if fields_to_resolve.resolve_documentation { + something_to_resolve = item.documentation.is_some(); + None + } else { + item.documentation.map(documentation) + }; + let mut lsp_item = lsp_types::CompletionItem { label: item.label.to_string(), - detail: item.detail, - filter_text: Some(lookup), + detail, + filter_text, kind: Some(completion_item_kind(item.kind)), - text_edit: Some(text_edit), + text_edit, additional_text_edits: Some(additional_text_edits), - documentation: item.documentation.map(documentation), + documentation, deprecated: Some(item.deprecated), tags, command, @@ -332,34 +365,40 @@ fn completion_item( }; if config.completion_label_details_support() { - lsp_item.label_details = Some(lsp_types::CompletionItemLabelDetails { - detail: item.label_detail.as_ref().map(ToString::to_string), - description: lsp_item.detail.clone(), - }); + if fields_to_resolve.resolve_label_details { + something_to_resolve = true; + } else { + lsp_item.label_details = Some(lsp_types::CompletionItemLabelDetails { + detail: item.label_detail.as_ref().map(ToString::to_string), + description: lsp_item.detail.clone(), + }); + } } else if let Some(label_detail) = item.label_detail { lsp_item.label.push_str(label_detail.as_str()); } set_score(&mut lsp_item, max_relevance, item.relevance); - if config.completion(None).enable_imports_on_the_fly && !item.import_to_add.is_empty() { - let imports = item - .import_to_add - .into_iter() - .map(|(import_path, import_name)| lsp_ext::CompletionImport { - full_import_path: import_path, - imported_name: import_name, - }) - .collect::>(); - if !imports.is_empty() { - let data = lsp_ext::CompletionResolveData { - position: tdpp.clone(), - imports, - version, - completion_trigger_character, - }; - lsp_item.data = Some(to_value(data).unwrap()); - } + let imports = + if config.completion(None).enable_imports_on_the_fly && !item.import_to_add.is_empty() { + item.import_to_add + .into_iter() + .map(|(import_path, import_name)| lsp_ext::CompletionImport { + full_import_path: import_path, + imported_name: import_name, + }) + .collect() + } else { + Vec::new() + }; + if something_to_resolve || !imports.is_empty() { + let data = lsp_ext::CompletionResolveData { + position: tdpp.clone(), + imports, + version, + completion_trigger_character, + }; + lsp_item.data = Some(to_value(data).unwrap()); } if let Some((label, indel, relevance)) = ref_match {