From a6882391137bdcd03e93925153c61bf2d08584ef Mon Sep 17 00:00:00 2001
From: Alexander Andreev <117519751+alkasadist@users.noreply.github.com>
Date: Wed, 3 Dec 2025 15:51:18 +0300
Subject: [PATCH] python: Fix autocomplete sorting (#44050)
Closes:
#38727 (Python autocompletion being sorted alphabetically)
Release Notes:
- Improve sort order of pyright/basedpyright code completions
---
crates/languages/src/python.rs | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs
index bcdc7969b4f2b22f5136c733afd477f7d0cf0187..db61d5902d3f18444988caa0596f998f61636cee 100644
--- a/crates/languages/src/python.rs
+++ b/crates/languages/src/python.rs
@@ -101,9 +101,41 @@ impl FromStr for TestRunner {
/// The problem with it is that Pyright adjusts the sort text based on previous resolutions (items for which we've issued `completion/resolve` call have their sortText adjusted),
/// which - long story short - makes completion items list non-stable. Pyright probably relies on VSCode's implementation detail.
/// see https://github.com/microsoft/pyright/blob/95ef4e103b9b2f129c9320427e51b73ea7cf78bd/packages/pyright-internal/src/languageService/completionProvider.ts#LL2873
+///
+/// upd 02.12.25:
+/// 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 {
- item.sort_text.take();
+ let is_dunder = item.label.starts_with("__") && item.label.ends_with("__");
+
+ let visibility_priority = if is_dunder {
+ '3'
+ } else if item.label.starts_with("__") {
+ '2' // private non-dunder
+ } else if item.label.starts_with('_') {
+ '1' // protected
+ } else {
+ '0' // public
+ };
+
+ // 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',
+ };
+
+ item.sort_text = Some(format!(
+ "{}{}{}",
+ visibility_priority, kind_priority, item.label
+ ));
}
}