languages: Improve completion sorting for Python-based LSPs (#47160)
Closes #47086 This PR detects completion items ending with `=` (which typically represent keyword arguments in function calls provided by `Pyright`/`BasedPyright`/`pylsp`) and assigns them the highest sorting priority. This ensures that when a user is filling out function arguments, the named parameters appear at the top of the list, rather than being buried mixed with other symbols. After fix: <img width="786" height="460" alt="image" src="https://github.com/user-attachments/assets/75e94b0f-a2e7-4876-b9bd-02ad98cc8c50" /> > **Note on Sorting:** Currently, these named arguments will be sorted alphabetically by label. Preserving the original order of the function definition would be ideal, but it requires information not currently available in this logical block. Insights on how to retrieve the definition order would be appreciated. > **Note on other LSPs:** > * **`ty`**: Already provides well-sorted completions natively, so no intervention is required. Release Notes: - Improved completion order for Python-based LSPs
This commit is contained in:
1 parent
823f9dda40
commit
6b7c97eb8d
1 file changed
+34
-13
@@ -112,6 +112,8 @@ impl FromStr for TestRunner {
|
||||
/// Decided to ignore Pyright's sortText() completely and to manually sort all entries
|
||||
fn process_pyright_completions(items: &mut [lsp::CompletionItem]) {
|
||||
for item in items {
|
||||
let is_named_argument = item.label.ends_with('=');
|
||||
|
||||
let is_dunder = item.label.starts_with("__") && item.label.ends_with("__");
|
||||
|
||||
let visibility_priority = if is_dunder {
|
||||
@@ -124,23 +126,35 @@ fn process_pyright_completions(items: &mut [lsp::CompletionItem]) {
|
||||
'0' // public
|
||||
};
|
||||
|
||||
let is_external = item
|
||||
.detail
|
||||
.as_ref()
|
||||
.is_some_and(|detail| detail == "Auto-import");
|
||||
|
||||
let source_priority = if is_external { '1' } else { '0' };
|
||||
|
||||
// Kind priority within same visibility level
|
||||
let kind_priority = match item.kind {
|
||||
Some(lsp::CompletionItemKind::ENUM_MEMBER) => '0',
|
||||
Some(lsp::CompletionItemKind::FIELD) => '1',
|
||||
Some(lsp::CompletionItemKind::PROPERTY) => '2',
|
||||
Some(lsp::CompletionItemKind::VARIABLE) => '3',
|
||||
Some(lsp::CompletionItemKind::CONSTANT) => '4',
|
||||
Some(lsp::CompletionItemKind::METHOD) => '5',
|
||||
Some(lsp::CompletionItemKind::FUNCTION) => '5',
|
||||
Some(lsp::CompletionItemKind::CLASS) => '6',
|
||||
Some(lsp::CompletionItemKind::MODULE) => '7',
|
||||
_ => '8',
|
||||
Some(lsp::CompletionItemKind::KEYWORD) => '0',
|
||||
Some(lsp::CompletionItemKind::ENUM_MEMBER) => '1',
|
||||
Some(lsp::CompletionItemKind::FIELD) => '2',
|
||||
Some(lsp::CompletionItemKind::PROPERTY) => '3',
|
||||
Some(lsp::CompletionItemKind::VARIABLE) => '4',
|
||||
Some(lsp::CompletionItemKind::CONSTANT) => '5',
|
||||
Some(lsp::CompletionItemKind::METHOD) => '6',
|
||||
Some(lsp::CompletionItemKind::FUNCTION) => '6',
|
||||
Some(lsp::CompletionItemKind::CLASS) => '7',
|
||||
Some(lsp::CompletionItemKind::MODULE) => '8',
|
||||
|
||||
_ => 'z',
|
||||
};
|
||||
|
||||
// Named arguments get higher priority
|
||||
let argument_priority = if is_named_argument { '0' } else { '1' };
|
||||
|
||||
item.sort_text = Some(format!(
|
||||
"{}{}{}",
|
||||
visibility_priority, kind_priority, item.label
|
||||
"{}{}{}{}{}",
|
||||
argument_priority, source_priority, visibility_priority, kind_priority, item.label
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1689,7 +1703,14 @@ impl LspAdapter for PyLspAdapter {
|
||||
Self::SERVER_NAME
|
||||
}
|
||||
|
||||
async fn process_completions(&self, _items: &mut [lsp::CompletionItem]) {}
|
||||
async fn process_completions(&self, items: &mut [lsp::CompletionItem]) {
|
||||
for item in items {
|
||||
let is_named_argument = item.label.ends_with('=');
|
||||
let priority = if is_named_argument { '0' } else { '1' };
|
||||
let sort_text = item.sort_text.take().unwrap_or_else(|| item.label.clone());
|
||||
item.sort_text = Some(format!("{}{}", priority, sort_text));
|
||||
}
|
||||
}
|
||||
|
||||
async fn label_for_completion(
|
||||
&self,
|
||||
|
||||
Reference in new issue
Block a user