From 8c681d0db3b804faa7167b02e748d7a526966edb Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Thu, 16 May 2024 13:26:07 +0200 Subject: [PATCH] lsp: Use itemDefaults if sent along with completion items (#11902) This fixes #10532 by properly making use of `itemDefaults.data` when that is sent along next to completion `items`. With this line here we tell the language server that we support `data` in `itemDefaults`, but we actually never checked for it and never used it: https://github.com/zed-industries/zed/blob/a0d7ec9f8e70799163313767b5a8bc34d9e4aa1b/crates/lsp/src/lsp.rs#L653 In the case of `tailwindcss-language-server` that means that most of the items it returns (more than 10k items!) were missing the `data` attribute, since the language server thought it can send it along in the `itemDefaults` (because we advertised our capability to use it.) When we then did a `completionItem/resolve`, we would not send a `data` attribute along, which lead to an error on the `tailwindcss-language-server` side and thus no documentation. This PR also adds support for the other `itemDefaults` that could be sent along and that we say we support: https://github.com/zed-industries/zed/blob/a0d7ec9f8e70799163313767b5a8bc34d9e4aa1b/crates/lsp/src/lsp.rs#L650-L653 `editRange` we handle separately, so this PR only adds the other 3. Release Notes: - Fixed documentation not showing up for completion items coming from `tailwindcss-language-server`. ([#10532](https://github.com/zed-industries/zed/issues/10532)). Demo: https://github.com/zed-industries/zed/assets/1185253/bc5ea0b3-7d83-499f-a908-b0d2a1db8a41 --- crates/project/src/lsp_command.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 4c006bb864..a3917e4ef1 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1495,6 +1495,33 @@ impl LspCommand for GetCompletions { })? .ok_or_else(|| anyhow!("no such language server"))?; + let item_defaults = response_list + .as_ref() + .and_then(|list| list.item_defaults.as_ref()); + + if let Some(item_defaults) = item_defaults { + let default_data = item_defaults.data.as_ref(); + let default_commit_characters = item_defaults.commit_characters.as_ref(); + let default_insert_text_mode = item_defaults.insert_text_mode.as_ref(); + + if default_data.is_some() + || default_commit_characters.is_some() + || default_insert_text_mode.is_some() + { + for item in completions.iter_mut() { + if let Some(data) = default_data { + item.data = Some(data.clone()) + } + if let Some(characters) = default_commit_characters { + item.commit_characters = Some(characters.clone()) + } + if let Some(text_mode) = default_insert_text_mode { + item.insert_text_mode = Some(*text_mode) + } + } + } + } + let mut completion_edits = Vec::new(); buffer.update(&mut cx, |buffer, _cx| { let snapshot = buffer.snapshot();