MCPcopy Create free account
hub / github.com/astral-sh/ruff / visit_expr

Method visit_expr

crates/ty_python_core/src/builder.rs:4348–4656  ·  view source on GitHub ↗
(&mut self, expr: &'ast ast::Expr)

Source from the content-addressed store, hash-verified

4346 }
4347
4348 fn visit_expr(&mut self, expr: &'ast ast::Expr) {
4349 self.with_semantic_checker(|semantic, context| semantic.visit_expr(expr, context));
4350
4351 self.scopes_by_expression
4352 .record_expression(expr, self.current_scope());
4353
4354 match expr {
4355 ast::Expr::Name(ast::ExprName { ctx, .. })
4356 | ast::Expr::Attribute(ast::ExprAttribute { ctx, .. })
4357 | ast::Expr::Subscript(ast::ExprSubscript { ctx, .. }) => {
4358 // Record place effects after walking the expression. For names, this is
4359 // equivalent because `walk_expr` is a no-op; for attribute/subscript places,
4360 // child evaluation can introduce bindings (for example via walrus operators),
4361 // and those bindings need to exist before we register parent/member associations.
4362 let mut deferred_effects = None;
4363 if let Some(mut place_expr) = PlaceExpr::try_from_expr(expr) {
4364 if let Some(method_scope_id) = self.is_method_or_eagerly_executed_in_method()
4365 && let PlaceExpr::Member(member) = &mut place_expr
4366 && member.is_instance_attribute_candidate()
4367 && let Some(attribute) = expr.as_attribute_expr()
4368 {
4369 // We specifically mark direct attribute assignments to the first
4370 // parameter of a method, i.e. typically `self` or `cls`.
4371 // However, we must check that the symbol hasn't been shadowed by an
4372 // intermediate scope (e.g., a comprehension variable: `for self in [...]`)
4373 // and that the AST base is still the original name rather than a
4374 // rebinding expression such as `(self := other).x`.
4375 let accessed_object_refers_to_first_parameter =
4376 self.current_first_parameter_name.is_some_and(|first| {
4377 attribute
4378 .value
4379 .as_name_expr()
4380 .is_some_and(|name| name.id == first)
4381 && !self.is_symbol_bound_in_intermediate_eager_scopes(
4382 first,
4383 method_scope_id,
4384 )
4385 });
4386
4387 if accessed_object_refers_to_first_parameter {
4388 member.mark_instance_attribute();
4389 }
4390 }
4391
4392 let (is_use, is_definition) = match (ctx, self.current_assignment()) {
4393 (ast::ExprContext::Store, Some(CurrentAssignment::AugAssign(_))) => {
4394 // For augmented assignment, the target expression is also used.
4395 (true, true)
4396 }
4397 (ast::ExprContext::Load, _) => (true, false),
4398 (ast::ExprContext::Store, _) => (false, true),
4399 (ast::ExprContext::Del, _) => (true, true),
4400 (ast::ExprContext::Invalid, _) => (false, false),
4401 };
4402 deferred_effects = Some((place_expr, is_use, is_definition));
4403 }
4404
4405 walk_expr(self, expr);

Callers 5

with_type_paramsMethod · 0.45
with_generators_scopeMethod · 0.45
visit_stmt_implMethod · 0.45

Tested by

no test coverage detected