Filter private builtins members from completions#19102
Conversation
|
| .map(|name| Completion { | ||
| name, | ||
| builtin: module.is_known(KnownModule::Builtins), | ||
| }) | ||
| // Filter out private members from `builtins` | ||
| .filter(|name| !builtin || !name.starts_with('_')) | ||
| .map(|name| Completion { name, builtin }) |
There was a problem hiding this comment.
We could also filter after constructing the Completion, or filter elsewhere in the file. I'm not familiar enough to gauge the trade-offs here, but this spot seems reasonable.
There was a problem hiding this comment.
Regarding _ vs __, see https://github.com/astral-sh/ruff/pull/19102/files#r2180951944 and the OP.
| ); | ||
| test.assert_completions_include("filter"); | ||
| test.assert_completions_do_not_include("_T"); | ||
| test.assert_completions_do_not_include("__annotations__"); |
There was a problem hiding this comment.
Note I'm guessing we do not want this last assertion.
There was a problem hiding this comment.
I took the time to do this fc3b1ed as it seems wrong as-is.
|
I'm interested in landing the incremental change given there was significant discussion around the alternative pattern and it'll take a bit longer to do. @BurntSushi can you give this an early look? |
|
This is the change you'd need to apply to diff --git a/crates/ty_python_semantic/src/types/ide_support.rs b/crates/ty_python_semantic/src/types/ide_support.rs
index 7cf05fa57f..aac637c561 100644
--- a/crates/ty_python_semantic/src/types/ide_support.rs
+++ b/crates/ty_python_semantic/src/types/ide_support.rs
@@ -1,10 +1,10 @@
use crate::Db;
-use crate::place::{imported_symbol, place_from_bindings, place_from_declarations};
+use crate::place::{Place, imported_symbol, place_from_bindings, place_from_declarations};
use crate::semantic_index::place::ScopeId;
use crate::semantic_index::{
attribute_scopes, global_scope, imported_modules, place_table, semantic_index, use_def_map,
};
-use crate::types::{ClassBase, ClassLiteral, KnownClass, Type};
+use crate::types::{ClassBase, ClassLiteral, KnownClass, KnownInstanceType, Type};
use ruff_python_ast::name::Name;
use rustc_hash::FxHashSet;
@@ -144,13 +144,39 @@ impl AllMembers {
let Some(symbol_name) = place_table.place_expr(symbol_id).as_name() else {
continue;
};
- if !imported_symbol(db, file, symbol_name, None)
- .place
- .is_unbound()
+ let Place::Type(ty, _) = imported_symbol(db, file, symbol_name, None).place
+ else {
+ continue;
+ };
+
+ // Filter out names in stub files that are almost certain to be private to the stub.
+ if symbol_name.starts_with('_')
+ && !symbol_name.starts_with("__")
+ && file.path(db).extension() == Some("pyi")
{
- self.members
- .insert(place_table.place_expr(symbol_id).expect_name().clone());
+ match ty {
+ Type::NominalInstance(instance) => {
+ if matches!(
+ instance.class.known(db),
+ Some(
+ KnownClass::TypeVar
+ | KnownClass::TypeVarTuple
+ | KnownClass::ParamSpec
+ )
+ ) {
+ continue;
+ }
+ }
+ Type::ClassLiteral(class) if class.is_protocol(db) => continue,
+ Type::KnownInstance(
+ KnownInstanceType::TypeVar(_) | KnownInstanceType::TypeAliasType(_),
+ ) => continue,
+
+ _ => {}
+ }
}
+ self.members
+ .insert(place_table.place_expr(symbol_id).expect_name().clone());
}
Local testing from running the playground seems to show everything working as expected, and it doesn't result in us doing any more work since we already have the type right there |
|
I think @AlexWaygood's approach would also include And I think that's generally consistent with how we do completions elsewhere. |
|
I'll pick that up then |
This implements filtering of private symbols from stub files based on type information as discussed in #19102. It extends the previous implementation to apply to all stub files, instead of just the `builtins` module, and uses type information to retain private names that are may be relevant at runtime.
|
Replaced by #19121 |
Closes astral-sh/ty#757
A few thoughts here
This doesn't distinguish between sunder and dunder, but probably should.There are dunder methods in the builtins stubs, but not at the top-level? It doesn't seem like the completions distinguish between these concepts though, as it'll suggest me__annotations__in the test? I added a test case around this for clarity. It'd be trivial to retain dunder completions, we'd just need to decide if we want to pull the niceKindsorter out of the classification code for re-use. N.B.: See thread — I changed this in fc3b1ed.And as pointed out by @AlexWaygood
There is some context in the internal Discord, here and here.
It seems plausible and reasonable to perform (3) and (4) as follow-ups.