Unnamed repository; edit this file 'description' to name the repository.
Omit completion fields to be resolved later
Kirill Bulatov 2024-09-23
parent 2395a4e · commit ba1c914
-rw-r--r--crates/ide-completion/src/lib.rs4
-rw-r--r--crates/rust-analyzer/src/config.rs1
-rw-r--r--crates/rust-analyzer/src/handlers/request.rs55
-rw-r--r--crates/rust-analyzer/src/lsp/to_proto.rs101
4 files changed, 99 insertions, 62 deletions
diff --git a/crates/ide-completion/src/lib.rs b/crates/ide-completion/src/lib.rs
index 1e022cf244..a78976d3fd 100644
--- a/crates/ide-completion/src/lib.rs
+++ b/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/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index a8a7e02ac3..69dd8aff42 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/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/crates/rust-analyzer/src/handlers/request.rs b/crates/rust-analyzer/src/handlers/request.rs
index 9e3226fe79..7d5a3946db 100644
--- a/crates/rust-analyzer/src/handlers/request.rs
+++ b/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::<Vec<_>>();
-
- 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::<Vec<_>>();
+
+ 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/crates/rust-analyzer/src/lsp/to_proto.rs b/crates/rust-analyzer/src/lsp/to_proto.rs
index 6e6a70bb3b..c7f4b22a77 100644
--- a/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/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::<Vec<_>>();
- 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 {