mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 05:45:24 +00:00
[red-knot] Clarify how scopes are pushed and popped for comprehensions and generator expressions (#13353)
This commit is contained in:
parent
8b49845537
commit
f4de49ab37
1 changed files with 33 additions and 23 deletions
|
@ -325,11 +325,23 @@ impl<'db> SemanticIndexBuilder<'db> {
|
||||||
nested_scope
|
nested_scope
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visit a list of [`Comprehension`] nodes, assumed to be the "generators" that compose a
|
/// This method does several things:
|
||||||
/// comprehension (that is, the `for x in y` and `for y in z` parts of `x for x in y for y in z`.)
|
/// - It pushes a new scope onto the stack for visiting
|
||||||
|
/// a list/dict/set comprehension or generator expression
|
||||||
|
/// - Inside that scope, it visits a list of [`Comprehension`] nodes,
|
||||||
|
/// assumed to be the "generators" that compose a comprehension
|
||||||
|
/// (that is, the `for x in y` and `for y in z` parts of `x for x in y for y in z`).
|
||||||
|
/// - Inside that scope, it also calls a closure for visiting the outer `elt`
|
||||||
|
/// of a list/dict/set comprehension or generator expression
|
||||||
|
/// - It then pops the new scope off the stack
|
||||||
///
|
///
|
||||||
/// [`Comprehension`]: ast::Comprehension
|
/// [`Comprehension`]: ast::Comprehension
|
||||||
fn visit_generators(&mut self, scope: NodeWithScopeRef, generators: &'db [ast::Comprehension]) {
|
fn with_generators_scope(
|
||||||
|
&mut self,
|
||||||
|
scope: NodeWithScopeRef,
|
||||||
|
generators: &'db [ast::Comprehension],
|
||||||
|
visit_outer_elt: impl FnOnce(&mut Self),
|
||||||
|
) {
|
||||||
let mut generators_iter = generators.iter();
|
let mut generators_iter = generators.iter();
|
||||||
|
|
||||||
let Some(generator) = generators_iter.next() else {
|
let Some(generator) = generators_iter.next() else {
|
||||||
|
@ -368,6 +380,9 @@ impl<'db> SemanticIndexBuilder<'db> {
|
||||||
self.visit_expr(expr);
|
self.visit_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
visit_outer_elt(self);
|
||||||
|
self.pop_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_parameter(&mut self, parameter: AnyParameterRef) {
|
fn declare_parameter(&mut self, parameter: AnyParameterRef) {
|
||||||
|
@ -878,6 +893,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
self.visit_expr(lambda.body.as_ref());
|
self.visit_expr(lambda.body.as_ref());
|
||||||
|
self.pop_scope();
|
||||||
}
|
}
|
||||||
ast::Expr::If(ast::ExprIf {
|
ast::Expr::If(ast::ExprIf {
|
||||||
body, test, orelse, ..
|
body, test, orelse, ..
|
||||||
|
@ -898,30 +914,33 @@ where
|
||||||
elt, generators, ..
|
elt, generators, ..
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
self.visit_generators(
|
self.with_generators_scope(
|
||||||
NodeWithScopeRef::ListComprehension(list_comprehension),
|
NodeWithScopeRef::ListComprehension(list_comprehension),
|
||||||
generators,
|
generators,
|
||||||
|
|builder| builder.visit_expr(elt),
|
||||||
);
|
);
|
||||||
self.visit_expr(elt);
|
|
||||||
}
|
}
|
||||||
ast::Expr::SetComp(
|
ast::Expr::SetComp(
|
||||||
set_comprehension @ ast::ExprSetComp {
|
set_comprehension @ ast::ExprSetComp {
|
||||||
elt, generators, ..
|
elt, generators, ..
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
self.visit_generators(
|
self.with_generators_scope(
|
||||||
NodeWithScopeRef::SetComprehension(set_comprehension),
|
NodeWithScopeRef::SetComprehension(set_comprehension),
|
||||||
generators,
|
generators,
|
||||||
|
|builder| builder.visit_expr(elt),
|
||||||
);
|
);
|
||||||
self.visit_expr(elt);
|
|
||||||
}
|
}
|
||||||
ast::Expr::Generator(
|
ast::Expr::Generator(
|
||||||
generator @ ast::ExprGenerator {
|
generator @ ast::ExprGenerator {
|
||||||
elt, generators, ..
|
elt, generators, ..
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
self.visit_generators(NodeWithScopeRef::GeneratorExpression(generator), generators);
|
self.with_generators_scope(
|
||||||
self.visit_expr(elt);
|
NodeWithScopeRef::GeneratorExpression(generator),
|
||||||
|
generators,
|
||||||
|
|builder| builder.visit_expr(elt),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ast::Expr::DictComp(
|
ast::Expr::DictComp(
|
||||||
dict_comprehension @ ast::ExprDictComp {
|
dict_comprehension @ ast::ExprDictComp {
|
||||||
|
@ -931,28 +950,19 @@ where
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
self.visit_generators(
|
self.with_generators_scope(
|
||||||
NodeWithScopeRef::DictComprehension(dict_comprehension),
|
NodeWithScopeRef::DictComprehension(dict_comprehension),
|
||||||
generators,
|
generators,
|
||||||
|
|builder| {
|
||||||
|
builder.visit_expr(key);
|
||||||
|
builder.visit_expr(value);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
self.visit_expr(key);
|
|
||||||
self.visit_expr(value);
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches!(
|
|
||||||
expr,
|
|
||||||
ast::Expr::Lambda(_)
|
|
||||||
| ast::Expr::ListComp(_)
|
|
||||||
| ast::Expr::SetComp(_)
|
|
||||||
| ast::Expr::Generator(_)
|
|
||||||
| ast::Expr::DictComp(_)
|
|
||||||
) {
|
|
||||||
self.pop_scope();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_parameters(&mut self, parameters: &'ast ast::Parameters) {
|
fn visit_parameters(&mut self, parameters: &'ast ast::Parameters) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue