Compare commits

...

1 Commits

Author SHA1 Message Date
Brent Westbrook
5810961b7f wip add ScopeKind::DunderClassCell like ruff 2025-08-25 13:55:17 -04:00
4 changed files with 37 additions and 6 deletions

View File

@@ -1267,6 +1267,12 @@ impl<'ast> Visitor<'ast> for SemanticIndexBuilder<'_, 'ast> {
self.visit_decorator(decorator);
}
let current_scope = &self.scopes[self.current_scope()];
let is_class = matches!(current_scope.kind(), ScopeKind::Class);
if is_class {
self.push_scope(NodeWithScopeRef::DunderClassCell);
}
self.with_type_params(
NodeWithScopeRef::FunctionTypeParameters(function_def),
type_params.as_deref(),
@@ -1295,6 +1301,11 @@ impl<'ast> Visitor<'ast> for SemanticIndexBuilder<'_, 'ast> {
builder.pop_scope()
},
);
if is_class {
self.pop_scope();
}
// The default value of the parameters needs to be evaluated in the
// enclosing scope.
for default in parameters
@@ -2649,7 +2660,8 @@ impl SemanticSyntaxContext for SemanticIndexBuilder<'_, '_> {
ScopeKind::Comprehension
| ScopeKind::Module
| ScopeKind::TypeAlias
| ScopeKind::TypeParams => {}
| ScopeKind::TypeParams
| ScopeKind::DunderClassCell => {}
}
}
false
@@ -2664,7 +2676,8 @@ impl SemanticSyntaxContext for SemanticIndexBuilder<'_, '_> {
ScopeKind::Comprehension
| ScopeKind::Module
| ScopeKind::TypeAlias
| ScopeKind::TypeParams => {}
| ScopeKind::TypeParams
| ScopeKind::DunderClassCell => {}
}
}
false
@@ -2676,7 +2689,10 @@ impl SemanticSyntaxContext for SemanticIndexBuilder<'_, '_> {
match scope.kind() {
ScopeKind::Class | ScopeKind::Comprehension => return false,
ScopeKind::Function | ScopeKind::Lambda => return true,
ScopeKind::Module | ScopeKind::TypeAlias | ScopeKind::TypeParams => {}
ScopeKind::Module
| ScopeKind::TypeAlias
| ScopeKind::TypeParams
| ScopeKind::DunderClassCell => {}
}
}
false

View File

@@ -64,6 +64,7 @@ impl<'db> ScopeId<'db> {
NodeWithScopeKind::SetComprehension(_) => "<setcomp>",
NodeWithScopeKind::DictComprehension(_) => "<dictcomp>",
NodeWithScopeKind::GeneratorExpression(_) => "<generator>",
NodeWithScopeKind::DunderClassCell => "<__class__ cell>",
}
}
}
@@ -206,6 +207,10 @@ pub(crate) enum ScopeKind {
Lambda,
Comprehension,
TypeAlias,
/// The implicit `__class__` scope surrounding a method which allows code in the method to
/// access `__class__` at runtime. The closure sits in between the class scope and the function
/// scope.
DunderClassCell,
}
impl ScopeKind {
@@ -218,7 +223,8 @@ impl ScopeKind {
ScopeKind::Module
| ScopeKind::Class
| ScopeKind::Comprehension
| ScopeKind::TypeParams => ScopeLaziness::Eager,
| ScopeKind::TypeParams
| ScopeKind::DunderClassCell => ScopeLaziness::Eager,
ScopeKind::Function | ScopeKind::Lambda | ScopeKind::TypeAlias => ScopeLaziness::Lazy,
}
}
@@ -230,7 +236,8 @@ impl ScopeKind {
| ScopeKind::TypeAlias
| ScopeKind::Function
| ScopeKind::Lambda
| ScopeKind::Comprehension => ScopeVisibility::Private,
| ScopeKind::Comprehension
| ScopeKind::DunderClassCell => ScopeVisibility::Private,
}
}
@@ -279,6 +286,7 @@ pub(crate) enum NodeWithScopeRef<'a> {
SetComprehension(&'a ast::ExprSetComp),
DictComprehension(&'a ast::ExprDictComp),
GeneratorExpression(&'a ast::ExprGenerator),
DunderClassCell,
}
impl NodeWithScopeRef<'_> {
@@ -321,6 +329,7 @@ impl NodeWithScopeRef<'_> {
NodeWithScopeRef::GeneratorExpression(generator) => {
NodeWithScopeKind::GeneratorExpression(AstNodeRef::new(module, generator))
}
NodeWithScopeRef::DunderClassCell => NodeWithScopeKind::DunderClassCell,
}
}
@@ -358,6 +367,7 @@ impl NodeWithScopeRef<'_> {
NodeWithScopeRef::GeneratorExpression(generator) => {
NodeWithScopeKey::GeneratorExpression(NodeKey::from_node(generator))
}
NodeWithScopeRef::DunderClassCell => NodeWithScopeKey::DunderClassCell,
}
}
}
@@ -377,6 +387,7 @@ pub(crate) enum NodeWithScopeKind {
SetComprehension(AstNodeRef<ast::ExprSetComp>),
DictComprehension(AstNodeRef<ast::ExprDictComp>),
GeneratorExpression(AstNodeRef<ast::ExprGenerator>),
DunderClassCell,
}
impl NodeWithScopeKind {
@@ -394,6 +405,7 @@ impl NodeWithScopeKind {
| Self::SetComprehension(_)
| Self::DictComprehension(_)
| Self::GeneratorExpression(_) => ScopeKind::Comprehension,
Self::DunderClassCell => ScopeKind::DunderClassCell,
}
}
@@ -459,4 +471,5 @@ pub(crate) enum NodeWithScopeKey {
SetComprehension(NodeKey),
DictComprehension(NodeKey),
GeneratorExpression(NodeKey),
DunderClassCell,
}

View File

@@ -1382,7 +1382,8 @@ mod resolve_definition {
| NodeWithScopeKind::ListComprehension(_)
| NodeWithScopeKind::SetComprehension(_)
| NodeWithScopeKind::DictComprehension(_)
| NodeWithScopeKind::GeneratorExpression(_) => {
| NodeWithScopeKind::GeneratorExpression(_)
| NodeWithScopeKind::DunderClassCell => {
// Not yet implemented
return Err(());
}

View File

@@ -1055,6 +1055,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
NodeWithScopeKind::GeneratorExpression(generator) => {
self.infer_generator_expression_scope(generator.node(self.module()));
}
NodeWithScopeKind::DunderClassCell => {}
}
// Infer the deferred types for the definitions here to consider the end-of-scope