Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pyrefly/lib/lsp/non_wasm/workspace_symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ impl Transaction<'_> {
result.push((name, kind, location));
}
}
// Keep shared fuzzy ordering intact while preferring non-`__init__.py` matches here.
result.sort_by_key(|(_, _, location)| location.module.path().is_init());
Some(result)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from .implementation import workspace_symbol_prefers_non_init_over_init_reexport
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.


def workspace_symbol_prefers_non_init_over_init_reexport() -> None:
return
60 changes: 60 additions & 0 deletions pyrefly/lib/test/lsp/lsp_interaction/workspace_symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

use lsp_types::Url;
use lsp_types::WorkspaceSymbolResponse;
use lsp_types::request::WorkspaceSymbolRequest;
use serde_json::json;

Expand Down Expand Up @@ -54,3 +55,62 @@ fn test_workspace_symbol() {

interaction.shutdown().unwrap();
}

#[test]
fn test_workspace_symbol_prefers_non_init_result() {
let root = get_test_files_root();
let root_path = root.path().join("tests_requiring_config");
let scope_uri = Url::from_file_path(root_path.clone()).unwrap();
let mut interaction = LspInteraction::new();
interaction.set_root(root_path.clone());
interaction
.initialize(InitializeSettings {
workspace_folders: Some(vec![("test".to_owned(), scope_uri)]),
configuration: Some(Some(json!([{ "indexing_mode": "lazy_blocking"}]))),
..Default::default()
})
.unwrap();

interaction
.client
.did_open("workspace_symbol_prefer_non_init/implementation.py");
interaction
.client
.did_open("workspace_symbol_prefer_non_init/__init__.py");

let implementation_uri =
Url::from_file_path(root_path.join("workspace_symbol_prefer_non_init/implementation.py"))
.unwrap();
let init_uri =
Url::from_file_path(root_path.join("workspace_symbol_prefer_non_init/__init__.py"))
.unwrap();
let symbol_name = "workspace_symbol_prefers_non_init_over_init_reexport";

interaction
.client
.send_request::<WorkspaceSymbolRequest>(json!({ "query": symbol_name }))
.expect_response_with(|result| {
let Some(WorkspaceSymbolResponse::Flat(symbols)) = result else {
panic!("Unexpected workspace symbol response: {result:?}");
};
assert!(symbols.iter().all(|symbol| symbol.name == symbol_name));
assert!(symbols.iter().all(|symbol| {
symbol.location.uri == implementation_uri || symbol.location.uri == init_uri
}));

let first_init_index = symbols
.iter()
.position(|symbol| symbol.location.uri == init_uri)
.expect("expected at least one __init__.py result");
let last_non_init_index = symbols
.iter()
.rposition(|symbol| symbol.location.uri == implementation_uri)
.expect("expected at least one non-__init__.py result");

assert!(last_non_init_index < first_init_index);
true
})
.unwrap();

interaction.shutdown().unwrap();
}