[ty] Favour imported symbols over builtin symbols (#21285)

<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

Raised by @AlexWaygood.

We previously did not favour imported symbols, when we probably
should've

## Test Plan

Add test showing that we favour imported symbol even if it is
alphabetically after other symbols that are builtin.
This commit is contained in:
Matthew Mckee 2025-11-06 11:46:08 +00:00 committed by GitHub
parent c6573b16ac
commit b5ff96595d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 2 deletions

View File

@ -17,7 +17,7 @@ numpy-array,main.py,1,1
object-attr-instance-methods,main.py,0,1
object-attr-instance-methods,main.py,1,1
raise-uses-base-exception,main.py,0,2
scope-existing-over-new-import,main.py,0,13
scope-existing-over-new-import,main.py,0,1
scope-prioritize-closer,main.py,0,2
scope-simple-long-identifier,main.py,0,1
tstring-completions,main.py,0,1

1 name file index rank
17 object-attr-instance-methods main.py 0 1
18 object-attr-instance-methods main.py 1 1
19 raise-uses-base-exception main.py 0 2
20 scope-existing-over-new-import main.py 0 13 1
21 scope-prioritize-closer main.py 0 2
22 scope-simple-long-identifier main.py 0 1
23 tstring-completions main.py 0 1

View File

@ -883,9 +883,10 @@ fn is_in_definition_place(db: &dyn Db, tokens: &[Token], file: File) -> bool {
/// This has the effect of putting all dunder attributes after "normal"
/// attributes, and all single-underscore attributes after dunder attributes.
fn compare_suggestions(c1: &Completion, c2: &Completion) -> Ordering {
fn key<'a>(completion: &'a Completion) -> (bool, NameKind, bool, &'a Name) {
fn key<'a>(completion: &'a Completion) -> (bool, bool, NameKind, bool, &'a Name) {
(
completion.module_name.is_some(),
completion.builtin,
NameKind::classify(&completion.name),
completion.is_type_check_only,
&completion.name,
@ -4196,6 +4197,25 @@ type <CURSOR>
");
}
#[test]
fn favour_imported_over_builtin() {
let snapshot =
completion_test_builder("from typing import Protocol\nclass Foo(P<CURSOR>: ...")
.filter(|c| c.name.starts_with('P'))
.build()
.snapshot();
// Here we favour `Protocol` over the other completions
// because `Protocol` has been imported, and the other completions are builtin.
assert_snapshot!(snapshot, @r"
Protocol
PendingDeprecationWarning
PermissionError
ProcessLookupError
PythonFinalizationError
");
}
/// A way to create a simple single-file (named `main.py`) completion test
/// builder.
///