diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index 1cd0e596d5..f6419c1e58 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -71,7 +71,7 @@ pub(crate) struct Checker<'a> { pub(crate) indexer: &'a Indexer, pub(crate) importer: Importer<'a>, // Stateful fields. - pub(crate) model: SemanticModel<'a>, + semantic_model: SemanticModel<'a>, pub(crate) diagnostics: Vec, pub(crate) deletions: FxHashSet>, deferred: Deferred<'a>, @@ -105,7 +105,7 @@ impl<'a> Checker<'a> { stylist, indexer, importer, - model: SemanticModel::new(&settings.typing_modules, path, module), + semantic_model: SemanticModel::new(&settings.typing_modules, path, module), deferred: Deferred::default(), diagnostics: Vec::default(), deletions: FxHashSet::default(), @@ -162,10 +162,15 @@ impl<'a> Checker<'a> { Generator::new( self.stylist.indentation(), - quote_style(&self.model, self.locator, self.indexer).unwrap_or(self.stylist.quote()), + quote_style(&self.semantic_model, self.locator, self.indexer) + .unwrap_or(self.stylist.quote()), self.stylist.line_ending(), ) } + + pub(crate) fn semantic_model(&self) -> &SemanticModel<'a> { + &self.semantic_model + } } impl<'a, 'b> Visitor<'b> for Checker<'a> @@ -173,7 +178,7 @@ where 'b: 'a, { fn visit_stmt(&mut self, stmt: &'b Stmt) { - self.model.push_stmt(stmt); + self.semantic_model.push_stmt(stmt); // Track whether we've seen docstrings, non-imports, etc. match stmt { @@ -184,55 +189,55 @@ where .iter() .any(|alias| alias.name.as_str() == "annotations") { - self.model.flags |= ContextFlags::FUTURE_ANNOTATIONS; + self.semantic_model.flags |= ContextFlags::FUTURE_ANNOTATIONS; } } else { - self.model.flags |= ContextFlags::FUTURES_BOUNDARY; + self.semantic_model.flags |= ContextFlags::FUTURES_BOUNDARY; } } Stmt::Import(_) => { - self.model.flags |= ContextFlags::FUTURES_BOUNDARY; + self.semantic_model.flags |= ContextFlags::FUTURES_BOUNDARY; } _ => { - self.model.flags |= ContextFlags::FUTURES_BOUNDARY; - if !self.model.seen_import_boundary() + self.semantic_model.flags |= ContextFlags::FUTURES_BOUNDARY; + if !self.semantic_model.seen_import_boundary() && !helpers::is_assignment_to_a_dunder(stmt) - && !helpers::in_nested_block(self.model.parents()) + && !helpers::in_nested_block(self.semantic_model.parents()) { - self.model.flags |= ContextFlags::IMPORT_BOUNDARY; + self.semantic_model.flags |= ContextFlags::IMPORT_BOUNDARY; } } } // Track each top-level import, to guide import insertions. if matches!(stmt, Stmt::Import(_) | Stmt::ImportFrom(_)) { - if self.model.at_top_level() { + if self.semantic_model.at_top_level() { self.importer.visit_import(stmt); } } // Store the flags prior to any further descent, so that we can restore them after visiting // the node. - let flags_snapshot = self.model.flags; + let flags_snapshot = self.semantic_model.flags; // Pre-visit. match stmt { Stmt::Global(ast::StmtGlobal { names, range: _ }) => { let ranges: Vec = helpers::find_names(stmt, self.locator).collect(); - if !self.model.scope_id.is_global() { + if !self.semantic_model.scope_id.is_global() { // Add the binding to the current scope. - let context = self.model.execution_context(); - let exceptions = self.model.exceptions(); - let scope = &mut self.model.scopes[self.model.scope_id]; - let usage = Some((self.model.scope_id, stmt.range())); + let context = self.semantic_model.execution_context(); + let exceptions = self.semantic_model.exceptions(); + let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id]; + let usage = Some((self.semantic_model.scope_id, stmt.range())); for (name, range) in names.iter().zip(ranges.iter()) { - let id = self.model.bindings.push(Binding { + let id = self.semantic_model.bindings.push(Binding { kind: BindingKind::Global, runtime_usage: None, synthetic_usage: usage, typing_usage: None, range: *range, - source: self.model.stmt_id, + source: self.semantic_model.stmt_id, context, exceptions, }); @@ -249,20 +254,20 @@ where } Stmt::Nonlocal(ast::StmtNonlocal { names, range: _ }) => { let ranges: Vec = helpers::find_names(stmt, self.locator).collect(); - if !self.model.scope_id.is_global() { - let context = self.model.execution_context(); - let exceptions = self.model.exceptions(); - let scope = &mut self.model.scopes[self.model.scope_id]; - let usage = Some((self.model.scope_id, stmt.range())); + if !self.semantic_model.scope_id.is_global() { + let context = self.semantic_model.execution_context(); + let exceptions = self.semantic_model.exceptions(); + let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id]; + let usage = Some((self.semantic_model.scope_id, stmt.range())); for (name, range) in names.iter().zip(ranges.iter()) { // Add a binding to the current scope. - let id = self.model.bindings.push(Binding { + let id = self.semantic_model.bindings.push(Binding { kind: BindingKind::Nonlocal, runtime_usage: None, synthetic_usage: usage, typing_usage: None, range: *range, - source: self.model.stmt_id, + source: self.semantic_model.stmt_id, context, exceptions, }); @@ -273,15 +278,15 @@ where // and the current scope.) for (name, range) in names.iter().zip(ranges.iter()) { let binding_id = self - .model + .semantic_model .scopes - .ancestors(self.model.scope_id) + .ancestors(self.semantic_model.scope_id) .skip(1) .take_while(|scope| !scope.kind.is_module()) .find_map(|scope| scope.get(name.as_str())); if let Some(binding_id) = binding_id { - self.model.bindings[*binding_id].runtime_usage = usage; + self.semantic_model.bindings[*binding_id].runtime_usage = usage; } else { // Ensure that every nonlocal has an existing binding from a parent scope. if self.settings.rules.enabled(Rule::NonlocalWithoutBinding) { @@ -305,9 +310,10 @@ where } Stmt::Break(_) => { if self.settings.rules.enabled(Rule::BreakOutsideLoop) { - if let Some(diagnostic) = - pyflakes::rules::break_outside_loop(stmt, &mut self.model.parents().skip(1)) - { + if let Some(diagnostic) = pyflakes::rules::break_outside_loop( + stmt, + &mut self.semantic_model.parents().skip(1), + ) { self.diagnostics.push(diagnostic); } } @@ -316,7 +322,7 @@ where if self.settings.rules.enabled(Rule::ContinueOutsideLoop) { if let Some(diagnostic) = pyflakes::rules::continue_outside_loop( stmt, - &mut self.model.parents().skip(1), + &mut self.semantic_model.parents().skip(1), ) { self.diagnostics.push(diagnostic); } @@ -346,7 +352,7 @@ where self.diagnostics .extend(flake8_django::rules::non_leading_receiver_decorator( decorator_list, - |expr| self.model.resolve_call_path(expr), + |expr| self.semantic_model.resolve_call_path(expr), )); } @@ -366,7 +372,7 @@ where name, decorator_list, &self.settings.pep8_naming.ignore_names, - &self.model, + &self.semantic_model, self.locator, ) { self.diagnostics.push(diagnostic); @@ -381,7 +387,7 @@ where if let Some(diagnostic) = pep8_naming::rules::invalid_first_argument_name_for_class_method( self, - self.model.scope(), + self.semantic_model.scope(), name, decorator_list, args, @@ -399,7 +405,7 @@ where if let Some(diagnostic) = pep8_naming::rules::invalid_first_argument_name_for_method( self, - self.model.scope(), + self.semantic_model.scope(), name, decorator_list, args, @@ -420,7 +426,7 @@ where if self.settings.rules.enabled(Rule::DunderFunctionName) { if let Some(diagnostic) = pep8_naming::rules::dunder_function_name( - self.model.scope(), + self.semantic_model.scope(), stmt, name, self.locator, @@ -618,7 +624,7 @@ where pyupgrade::rules::yield_in_for_loop(self, stmt); } - if self.model.scope().kind.is_class() { + if self.semantic_model.scope().kind.is_class() { if self.settings.rules.enabled(Rule::BuiltinAttributeShadowing) { flake8_builtins::rules::builtin_attribute_shadowing(self, name, stmt); } @@ -778,7 +784,7 @@ where if self.settings.rules.any_enabled(&[ Rule::MutableDataclassDefault, Rule::FunctionCallInDataclassDefaultArgument, - ]) && ruff::rules::is_dataclass(&self.model, decorator_list) + ]) && ruff::rules::is_dataclass(&self.semantic_model, decorator_list) { if self.settings.rules.enabled(Rule::MutableDataclassDefault) { ruff::rules::mutable_dataclass_default(self, body); @@ -843,17 +849,20 @@ where kind: BindingKind::FutureImportation, runtime_usage: None, // Always mark `__future__` imports as used. - synthetic_usage: Some((self.model.scope_id, alias.range())), + synthetic_usage: Some(( + self.semantic_model.scope_id, + alias.range(), + )), typing_usage: None, range: alias.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); if self.settings.rules.enabled(Rule::LateFutureImport) { - if self.model.seen_futures_boundary() { + if self.semantic_model.seen_futures_boundary() { self.diagnostics.push(Diagnostic::new( pyflakes::rules::LateFutureImport, stmt.range(), @@ -876,9 +885,9 @@ where synthetic_usage: None, typing_usage: None, range: alias.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); } else { @@ -897,15 +906,15 @@ where kind: BindingKind::Importation(Importation { name, full_name }), runtime_usage: None, synthetic_usage: if is_explicit_reexport { - Some((self.model.scope_id, alias.range())) + Some((self.semantic_model.scope_id, alias.range())) } else { None }, typing_usage: None, range: alias.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); @@ -1158,12 +1167,15 @@ where kind: BindingKind::FutureImportation, runtime_usage: None, // Always mark `__future__` imports as used. - synthetic_usage: Some((self.model.scope_id, alias.range())), + synthetic_usage: Some(( + self.semantic_model.scope_id, + alias.range(), + )), typing_usage: None, range: alias.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); @@ -1172,7 +1184,7 @@ where } if self.settings.rules.enabled(Rule::LateFutureImport) { - if self.model.seen_futures_boundary() { + if self.semantic_model.seen_futures_boundary() { self.diagnostics.push(Diagnostic::new( pyflakes::rules::LateFutureImport, stmt.range(), @@ -1180,7 +1192,7 @@ where } } } else if &alias.name == "*" { - self.model + self.semantic_model .scope_mut() .add_star_import(StarImportation { level, module }); @@ -1189,7 +1201,7 @@ where .rules .enabled(Rule::UndefinedLocalWithNestedImportStarUsage) { - let scope = self.model.scope(); + let scope = self.semantic_model.scope(); if !matches!(scope.kind, ScopeKind::Module) { self.diagnostics.push(Diagnostic::new( pyflakes::rules::UndefinedLocalWithNestedImportStarUsage { @@ -1243,15 +1255,15 @@ where }), runtime_usage: None, synthetic_usage: if is_explicit_reexport { - Some((self.model.scope_id, alias.range())) + Some((self.semantic_model.scope_id, alias.range())) } else { None }, typing_usage: None, range: alias.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); } @@ -1495,11 +1507,15 @@ where test, body, orelse, - self.model.stmt_parent(), + self.semantic_model.stmt_parent(), ); } if self.settings.rules.enabled(Rule::IfWithSameArms) { - flake8_simplify::rules::if_with_same_arms(self, stmt, self.model.stmt_parent()); + flake8_simplify::rules::if_with_same_arms( + self, + stmt, + self.semantic_model.stmt_parent(), + ); } if self.settings.rules.enabled(Rule::NeedlessBool) { flake8_simplify::rules::needless_bool(self, stmt); @@ -1515,14 +1531,14 @@ where test, body, orelse, - self.model.stmt_parent(), + self.semantic_model.stmt_parent(), ); } if self.settings.rules.enabled(Rule::IfElseBlockInsteadOfIfExp) { flake8_simplify::rules::use_ternary_operator( self, stmt, - self.model.stmt_parent(), + self.semantic_model.stmt_parent(), ); } if self @@ -1536,7 +1552,7 @@ where test, body, orelse, - self.model.stmt_parent(), + self.semantic_model.stmt_parent(), ); } if self.settings.rules.enabled(Rule::TypeCheckWithoutTypeError) { @@ -1545,7 +1561,7 @@ where body, test, orelse, - self.model.stmt_parent(), + self.semantic_model.stmt_parent(), ); } if self.settings.rules.enabled(Rule::OutdatedVersionBlock) { @@ -1564,7 +1580,7 @@ where msg, range: _, }) => { - if !self.model.in_type_checking_block() { + if !self.semantic_model.in_type_checking_block() { if self.settings.rules.enabled(Rule::Assert) { self.diagnostics .push(flake8_bandit::rules::assert_used(stmt)); @@ -1610,7 +1626,7 @@ where self, stmt, body, - self.model.stmt_parent(), + self.semantic_model.stmt_parent(), ); } if self.settings.rules.enabled(Rule::RedefinedLoopName) { @@ -1640,7 +1656,7 @@ where .. }) => { if self.settings.rules.enabled(Rule::UnusedLoopControlVariable) { - self.deferred.for_loops.push(self.model.snapshot()); + self.deferred.for_loops.push(self.semantic_model.snapshot()); } if self .settings @@ -1666,7 +1682,7 @@ where flake8_simplify::rules::convert_for_loop_to_any_all( self, stmt, - self.model.sibling_stmt(), + self.semantic_model.sibling_stmt(), ); } if self.settings.rules.enabled(Rule::InDictKeys) { @@ -1810,7 +1826,11 @@ where Rule::UnannotatedAssignmentInStub, ]) { // Ignore assignments in function bodies; those are covered by other rules. - if !self.model.scopes().any(|scope| scope.kind.is_function()) { + if !self + .semantic_model + .scopes() + .any(|scope| scope.kind.is_function()) + { if self.settings.rules.enabled(Rule::UnprefixedTypeParam) { flake8_pyi::rules::prefix_type_params(self, value, targets); } @@ -1863,14 +1883,21 @@ where if let Some(value) = value { if self.settings.rules.enabled(Rule::AssignmentDefaultInStub) { // Ignore assignments in function bodies; those are covered by other rules. - if !self.model.scopes().any(|scope| scope.kind.is_function()) { + if !self + .semantic_model + .scopes() + .any(|scope| scope.kind.is_function()) + { flake8_pyi::rules::annotated_assignment_default_in_stub( self, target, value, annotation, ); } } } - if self.model.match_typing_expr(annotation, "TypeAlias") { + if self + .semantic_model + .match_typing_expr(annotation, "TypeAlias") + { if self.settings.rules.enabled(Rule::SnakeCaseTypeAlias) { flake8_pyi::rules::snake_case_type_alias(self, target); } @@ -1904,7 +1931,7 @@ where } if self.settings.rules.enabled(Rule::AsyncioDanglingTask) { if let Some(diagnostic) = ruff::rules::asyncio_dangling_task(value, |expr| { - self.model.resolve_call_path(expr) + self.semantic_model.resolve_call_path(expr) }) { self.diagnostics.push(diagnostic); } @@ -1939,7 +1966,7 @@ where // Function annotations are always evaluated at runtime, unless future annotations // are enabled. - let runtime_annotation = !self.model.future_annotations(); + let runtime_annotation = !self.semantic_model.future_annotations(); for arg in &args.posonlyargs { if let Some(expr) = &arg.annotation { @@ -2008,50 +2035,56 @@ where synthetic_usage: None, typing_usage: None, range: stmt.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); // If any global bindings don't already exist in the global scope, add it. let globals = helpers::extract_globals(body); for (name, stmt) in helpers::extract_globals(body) { - if self.model.global_scope().get(name).map_or(true, |index| { - self.model.bindings[*index].kind.is_annotation() - }) { - let id = self.model.bindings.push(Binding { + if self + .semantic_model + .global_scope() + .get(name) + .map_or(true, |index| { + self.semantic_model.bindings[*index].kind.is_annotation() + }) + { + let id = self.semantic_model.bindings.push(Binding { kind: BindingKind::Assignment, runtime_usage: None, synthetic_usage: None, typing_usage: None, range: stmt.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }); - self.model.global_scope_mut().add(name, id); + self.semantic_model.global_scope_mut().add(name, id); } } let definition = docstrings::extraction::extract_definition( ExtractionTarget::Function, stmt, - self.model.definition_id, - &self.model.definitions, + self.semantic_model.definition_id, + &self.semantic_model.definitions, ); - self.model.push_definition(definition); + self.semantic_model.push_definition(definition); - self.model.push_scope(ScopeKind::Function(FunctionDef { - name, - body, - args, - decorator_list, - async_: matches!(stmt, Stmt::AsyncFunctionDef(_)), - globals, - })); + self.semantic_model + .push_scope(ScopeKind::Function(FunctionDef { + name, + body, + args, + decorator_list, + async_: matches!(stmt, Stmt::AsyncFunctionDef(_)), + globals, + })); - self.deferred.functions.push(self.model.snapshot()); + self.deferred.functions.push(self.semantic_model.snapshot()); } Stmt::ClassDef(ast::StmtClassDef { body, @@ -2074,32 +2107,37 @@ where // If any global bindings don't already exist in the global scope, add it. let globals = helpers::extract_globals(body); for (name, stmt) in &globals { - if self.model.global_scope().get(name).map_or(true, |index| { - self.model.bindings[*index].kind.is_annotation() - }) { - let id = self.model.bindings.push(Binding { + if self + .semantic_model + .global_scope() + .get(name) + .map_or(true, |index| { + self.semantic_model.bindings[*index].kind.is_annotation() + }) + { + let id = self.semantic_model.bindings.push(Binding { kind: BindingKind::Assignment, runtime_usage: None, synthetic_usage: None, typing_usage: None, range: stmt.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }); - self.model.global_scope_mut().add(name, id); + self.semantic_model.global_scope_mut().add(name, id); } } let definition = docstrings::extraction::extract_definition( ExtractionTarget::Class, stmt, - self.model.definition_id, - &self.model.definitions, + self.semantic_model.definition_id, + &self.semantic_model.definitions, ); - self.model.push_definition(definition); + self.semantic_model.push_definition(definition); - self.model.push_scope(ScopeKind::Class(ClassDef { + self.semantic_model.push_scope(ScopeKind::Class(ClassDef { name, bases, keywords, @@ -2125,7 +2163,7 @@ where }) => { let mut handled_exceptions = Exceptions::empty(); for type_ in extract_handled_exceptions(handlers) { - if let Some(call_path) = self.model.resolve_call_path(type_) { + if let Some(call_path) = self.semantic_model.resolve_call_path(type_) { if call_path.as_slice() == ["", "NameError"] { handled_exceptions |= Exceptions::NAME_ERROR; } else if call_path.as_slice() == ["", "ModuleNotFoundError"] { @@ -2134,7 +2172,9 @@ where } } - self.model.handled_exceptions.push(handled_exceptions); + self.semantic_model + .handled_exceptions + .push(handled_exceptions); if self.settings.rules.enabled(Rule::JumpStatementInFinally) { flake8_bugbear::rules::jump_statement_in_finally(self, finalbody); @@ -2147,9 +2187,9 @@ where } self.visit_body(body); - self.model.handled_exceptions.pop(); + self.semantic_model.handled_exceptions.pop(); - self.model.flags |= ContextFlags::EXCEPTION_HANDLER; + self.semantic_model.flags |= ContextFlags::EXCEPTION_HANDLER; for excepthandler in handlers { self.visit_excepthandler(excepthandler); } @@ -2166,8 +2206,8 @@ where // If we're in a class or module scope, then the annotation needs to be // available at runtime. // See: https://docs.python.org/3/reference/simple_stmts.html#annotated-assignment-statements - let runtime_annotation = if self.model.future_annotations() { - if matches!(self.model.scope().kind, ScopeKind::Class(..)) { + let runtime_annotation = if self.semantic_model.future_annotations() { + if matches!(self.semantic_model.scope().kind, ScopeKind::Class(..)) { let baseclasses = &self .settings .flake8_type_checking @@ -2177,7 +2217,7 @@ where .flake8_type_checking .runtime_evaluated_decorators; flake8_type_checking::helpers::runtime_evaluated( - &self.model, + &self.semantic_model, baseclasses, decorators, ) @@ -2186,7 +2226,7 @@ where } } else { matches!( - self.model.scope().kind, + self.semantic_model.scope().kind, ScopeKind::Class(..) | ScopeKind::Module ) }; @@ -2197,7 +2237,10 @@ where self.visit_annotation(annotation); } if let Some(expr) = value { - if self.model.match_typing_expr(annotation, "TypeAlias") { + if self + .semantic_model + .match_typing_expr(annotation, "TypeAlias") + { self.visit_type_definition(expr); } else { self.visit_expr(expr); @@ -2233,7 +2276,8 @@ where }) => { self.visit_boolean_test(test); - if flake8_type_checking::helpers::is_type_checking_block(&self.model, test) { + if flake8_type_checking::helpers::is_type_checking_block(&self.semantic_model, test) + { if self.settings.rules.enabled(Rule::EmptyTypeCheckingBlock) { flake8_type_checking::rules::empty_type_checking_block(self, stmt, body); } @@ -2251,12 +2295,12 @@ where // Post-visit. match stmt { Stmt::FunctionDef(_) | Stmt::AsyncFunctionDef(_) => { - self.model.pop_scope(); - self.model.pop_definition(); + self.semantic_model.pop_scope(); + self.semantic_model.pop_definition(); } Stmt::ClassDef(ast::StmtClassDef { name, .. }) => { - self.model.pop_scope(); - self.model.pop_definition(); + self.semantic_model.pop_scope(); + self.semantic_model.pop_definition(); self.add_binding( name, Binding { @@ -2265,31 +2309,31 @@ where synthetic_usage: None, typing_usage: None, range: stmt.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); } _ => {} } - self.model.flags = flags_snapshot; - self.model.pop_stmt(); + self.semantic_model.flags = flags_snapshot; + self.semantic_model.pop_stmt(); } fn visit_annotation(&mut self, expr: &'b Expr) { - let flags_snapshot = self.model.flags; - self.model.flags |= ContextFlags::ANNOTATION; + let flags_snapshot = self.semantic_model.flags; + self.semantic_model.flags |= ContextFlags::ANNOTATION; self.visit_type_definition(expr); - self.model.flags = flags_snapshot; + self.semantic_model.flags = flags_snapshot; } fn visit_expr(&mut self, expr: &'b Expr) { - if !self.model.in_f_string() - && !self.model.in_deferred_type_definition() - && self.model.in_type_definition() - && self.model.future_annotations() + if !self.semantic_model.in_f_string() + && !self.semantic_model.in_deferred_type_definition() + && self.semantic_model.in_type_definition() + && self.semantic_model.future_annotations() { if let Expr::Constant(ast::ExprConstant { value: Constant::Str(value), @@ -2299,21 +2343,21 @@ where self.deferred.string_type_definitions.push(( expr.range(), value, - self.model.snapshot(), + self.semantic_model.snapshot(), )); } else { self.deferred .future_type_definitions - .push((expr, self.model.snapshot())); + .push((expr, self.semantic_model.snapshot())); } return; } - self.model.push_expr(expr); + self.semantic_model.push_expr(expr); // Store the flags prior to any further descent, so that we can restore them after visiting // the node. - let flags_snapshot = self.model.flags; + let flags_snapshot = self.semantic_model.flags; // If we're in a boolean test (e.g., the `test` of a `Stmt::If`), but now within a // subexpression (e.g., `a` in `f(a)`), then we're no longer in a boolean test. @@ -2325,7 +2369,7 @@ where .. }) ) { - self.model.flags -= ContextFlags::BOOLEAN_TEST; + self.semantic_model.flags -= ContextFlags::BOOLEAN_TEST; } // Pre-visit. @@ -2337,7 +2381,7 @@ where Rule::NonPEP604Annotation, ]) { if let Some(operator) = - analyze::typing::to_pep604_operator(value, slice, &self.model) + analyze::typing::to_pep604_operator(value, slice, &self.semantic_model) { if self .settings @@ -2346,8 +2390,8 @@ where { if self.settings.target_version < PythonVersion::Py310 && self.settings.target_version >= PythonVersion::Py37 - && !self.model.future_annotations() - && self.model.in_annotation() + && !self.semantic_model.future_annotations() + && self.semantic_model.in_annotation() { flake8_future_annotations::rules::missing_future_annotations( self, value, @@ -2357,8 +2401,8 @@ where if self.settings.rules.enabled(Rule::NonPEP604Annotation) { if self.settings.target_version >= PythonVersion::Py310 || (self.settings.target_version >= PythonVersion::Py37 - && self.model.future_annotations() - && self.model.in_annotation()) + && self.semantic_model.future_annotations() + && self.semantic_model.in_annotation()) { pyupgrade::rules::use_pep604_annotation( self, expr, slice, operator, @@ -2368,8 +2412,8 @@ where } } - if self.model.match_typing_expr(value, "Literal") { - self.model.flags |= ContextFlags::LITERAL; + if self.semantic_model.match_typing_expr(value, "Literal") { + self.semantic_model.flags |= ContextFlags::LITERAL; } if self.settings.rules.any_enabled(&[ @@ -2436,7 +2480,7 @@ where Rule::NonPEP585Annotation, ]) { if let Some(replacement) = - analyze::typing::to_pep585_generic(expr, &self.model) + analyze::typing::to_pep585_generic(expr, &self.semantic_model) { if self .settings @@ -2445,8 +2489,8 @@ where { if self.settings.target_version < PythonVersion::Py39 && self.settings.target_version >= PythonVersion::Py37 - && !self.model.future_annotations() - && self.model.in_annotation() + && !self.semantic_model.future_annotations() + && self.semantic_model.in_annotation() { flake8_future_annotations::rules::missing_future_annotations( self, expr, @@ -2456,8 +2500,8 @@ where if self.settings.rules.enabled(Rule::NonPEP585Annotation) { if self.settings.target_version >= PythonVersion::Py39 || (self.settings.target_version >= PythonVersion::Py37 - && self.model.future_annotations() - && self.model.in_annotation()) + && self.semantic_model.future_annotations() + && self.semantic_model.in_annotation()) { pyupgrade::rules::use_pep585_annotation( self, @@ -2480,7 +2524,7 @@ where } } - if self.model.scope().kind.is_class() { + if self.semantic_model.scope().kind.is_class() { if self.settings.rules.enabled(Rule::BuiltinAttributeShadowing) { flake8_builtins::rules::builtin_attribute_shadowing(self, id, expr); } @@ -2513,7 +2557,8 @@ where Rule::MissingFutureAnnotationsImport, Rule::NonPEP585Annotation, ]) { - if let Some(replacement) = analyze::typing::to_pep585_generic(expr, &self.model) + if let Some(replacement) = + analyze::typing::to_pep585_generic(expr, &self.semantic_model) { if self .settings @@ -2522,8 +2567,8 @@ where { if self.settings.target_version < PythonVersion::Py39 && self.settings.target_version >= PythonVersion::Py37 - && !self.model.future_annotations() - && self.model.in_annotation() + && !self.semantic_model.future_annotations() + && self.semantic_model.in_annotation() { flake8_future_annotations::rules::missing_future_annotations( self, expr, @@ -2533,8 +2578,8 @@ where if self.settings.rules.enabled(Rule::NonPEP585Annotation) { if self.settings.target_version >= PythonVersion::Py39 || (self.settings.target_version >= PythonVersion::Py37 - && self.model.future_annotations() - && self.model.in_annotation()) + && self.semantic_model.future_annotations() + && self.semantic_model.in_annotation()) { pyupgrade::rules::use_pep585_annotation(self, expr, &replacement); } @@ -2888,7 +2933,7 @@ where flake8_comprehensions::rules::unnecessary_generator_set( self, expr, - self.model.expr_parent(), + self.semantic_model.expr_parent(), func, args, keywords, @@ -2898,7 +2943,7 @@ where flake8_comprehensions::rules::unnecessary_generator_dict( self, expr, - self.model.expr_parent(), + self.semantic_model.expr_parent(), func, args, keywords, @@ -3003,7 +3048,7 @@ where flake8_comprehensions::rules::unnecessary_map( self, expr, - self.model.expr_parent(), + self.semantic_model.expr_parent(), func, args, ); @@ -3030,7 +3075,7 @@ where } if let Expr::Name(ast::ExprName { id, ctx, range: _ }) = func.as_ref() { if id == "locals" && matches!(ctx, ExprContext::Load) { - let scope = self.model.scope_mut(); + let scope = self.semantic_model.scope_mut(); scope.uses_locals = true; } } @@ -3539,8 +3584,8 @@ where }) => { if self.is_stub { if self.settings.rules.enabled(Rule::DuplicateUnionMember) - && self.model.in_type_definition() - && self.model.expr_parent().map_or(true, |parent| { + && self.semantic_model.in_type_definition() + && self.semantic_model.expr_parent().map_or(true, |parent| { !matches!( parent, Expr::BinOp(ast::ExprBinOp { @@ -3690,14 +3735,14 @@ where kind, range: _, }) => { - if self.model.in_type_definition() - && !self.model.in_literal() - && !self.model.in_f_string() + if self.semantic_model.in_type_definition() + && !self.semantic_model.in_literal() + && !self.semantic_model.in_f_string() { self.deferred.string_type_definitions.push(( expr.range(), value, - self.model.snapshot(), + self.semantic_model.snapshot(), )); } if self @@ -3742,7 +3787,7 @@ where for expr in &args.defaults { self.visit_expr(expr); } - self.model + self.semantic_model .push_scope(ScopeKind::Lambda(Lambda { args, body })); } Expr::IfExp(ast::ExprIfExp { @@ -3899,7 +3944,9 @@ where self.visit_expr(value); } Expr::Lambda(_) => { - self.deferred.lambdas.push((expr, self.model.snapshot())); + self.deferred + .lambdas + .push((expr, self.semantic_model.snapshot())); } Expr::IfExp(ast::ExprIfExp { test, @@ -3917,35 +3964,53 @@ where keywords, range: _, }) => { - let callable = self.model.resolve_call_path(func).and_then(|call_path| { - if self.model.match_typing_call_path(&call_path, "cast") { - Some(Callable::Cast) - } else if self.model.match_typing_call_path(&call_path, "NewType") { - Some(Callable::NewType) - } else if self.model.match_typing_call_path(&call_path, "TypeVar") { - Some(Callable::TypeVar) - } else if self.model.match_typing_call_path(&call_path, "NamedTuple") { - Some(Callable::NamedTuple) - } else if self.model.match_typing_call_path(&call_path, "TypedDict") { - Some(Callable::TypedDict) - } else if [ - "Arg", - "DefaultArg", - "NamedArg", - "DefaultNamedArg", - "VarArg", - "KwArg", - ] - .iter() - .any(|target| call_path.as_slice() == ["mypy_extensions", target]) - { - Some(Callable::MypyExtension) - } else if call_path.as_slice() == ["", "bool"] { - Some(Callable::Bool) - } else { - None - } - }); + let callable = self + .semantic_model + .resolve_call_path(func) + .and_then(|call_path| { + if self + .semantic_model + .match_typing_call_path(&call_path, "cast") + { + Some(Callable::Cast) + } else if self + .semantic_model + .match_typing_call_path(&call_path, "NewType") + { + Some(Callable::NewType) + } else if self + .semantic_model + .match_typing_call_path(&call_path, "TypeVar") + { + Some(Callable::TypeVar) + } else if self + .semantic_model + .match_typing_call_path(&call_path, "NamedTuple") + { + Some(Callable::NamedTuple) + } else if self + .semantic_model + .match_typing_call_path(&call_path, "TypedDict") + { + Some(Callable::TypedDict) + } else if [ + "Arg", + "DefaultArg", + "NamedArg", + "DefaultNamedArg", + "VarArg", + "KwArg", + ] + .iter() + .any(|target| call_path.as_slice() == ["mypy_extensions", target]) + { + Some(Callable::MypyExtension) + } else if call_path.as_slice() == ["", "bool"] { + Some(Callable::Bool) + } else { + None + } + }); match callable { Some(Callable::Bool) => { self.visit_expr(func); @@ -4103,15 +4168,15 @@ where // `obj["foo"]["bar"]`, we need to avoid treating the `obj["foo"]` // portion as an annotation, despite having `ExprContext::Load`. Thus, we track // the `ExprContext` at the top-level. - if self.model.in_subscript() { + if self.semantic_model.in_subscript() { visitor::walk_expr(self, expr); } else if matches!(ctx, ExprContext::Store | ExprContext::Del) { - self.model.flags |= ContextFlags::SUBSCRIPT; + self.semantic_model.flags |= ContextFlags::SUBSCRIPT; visitor::walk_expr(self, expr); } else { match analyze::typing::match_annotated_subscript( value, - &self.model, + &self.semantic_model, self.settings.typing_modules.iter().map(String::as_str), ) { Some(subscript) => { @@ -4154,7 +4219,7 @@ where } } Expr::JoinedStr(_) => { - self.model.flags |= ContextFlags::F_STRING; + self.semantic_model.flags |= ContextFlags::F_STRING; visitor::walk_expr(self, expr); } _ => visitor::walk_expr(self, expr), @@ -4167,13 +4232,13 @@ where | Expr::ListComp(_) | Expr::DictComp(_) | Expr::SetComp(_) => { - self.model.pop_scope(); + self.semantic_model.pop_scope(); } _ => {} }; - self.model.flags = flags_snapshot; - self.model.pop_expr(); + self.semantic_model.flags = flags_snapshot; + self.semantic_model.pop_expr(); } fn visit_excepthandler(&mut self, excepthandler: &'b Excepthandler) { @@ -4265,7 +4330,7 @@ where let name_range = helpers::excepthandler_name_range(excepthandler, self.locator).unwrap(); - if self.model.scope().defines(name) { + if self.semantic_model.scope().defines(name) { self.handle_node_store( name, &Expr::Name(ast::ExprName { @@ -4276,7 +4341,7 @@ where ); } - let definition = self.model.scope().get(name).copied(); + let definition = self.semantic_model.scope().get(name).copied(); self.handle_node_store( name, &Expr::Name(ast::ExprName { @@ -4289,10 +4354,10 @@ where walk_excepthandler(self, excepthandler); if let Some(index) = { - let scope = self.model.scope_mut(); + let scope = self.semantic_model.scope_mut(); &scope.remove(name) } { - if !self.model.bindings[*index].used() { + if !self.semantic_model.bindings[*index].used() { if self.settings.rules.enabled(Rule::UnusedVariable) { let mut diagnostic = Diagnostic::new( pyflakes::rules::UnusedVariable { name: name.into() }, @@ -4313,7 +4378,7 @@ where } if let Some(index) = definition { - let scope = self.model.scope_mut(); + let scope = self.semantic_model.scope_mut(); scope.add(name, index); } } @@ -4391,9 +4456,9 @@ where synthetic_usage: None, typing_usage: None, range: arg.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); @@ -4440,9 +4505,9 @@ where synthetic_usage: None, typing_usage: None, range: pattern.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); } @@ -4455,18 +4520,18 @@ where flake8_pie::rules::no_unnecessary_pass(self, body); } - let prev_body = self.model.body; - let prev_body_index = self.model.body_index; - self.model.body = body; - self.model.body_index = 0; + let prev_body = self.semantic_model.body; + let prev_body_index = self.semantic_model.body_index; + self.semantic_model.body = body; + self.semantic_model.body_index = 0; for stmt in body { self.visit_stmt(stmt); - self.model.body_index += 1; + self.semantic_model.body_index += 1; } - self.model.body = prev_body; - self.model.body_index = prev_body_index; + self.semantic_model.body = prev_body; + self.semantic_model.body_index = prev_body_index; } } @@ -4517,7 +4582,7 @@ impl<'a> Checker<'a> { // while all subsequent reads and writes are evaluated in the inner scope. In particular, // `x` is local to `foo`, and the `T` in `y=T` skips the class scope when resolving. self.visit_expr(&generator.iter); - self.model.push_scope(ScopeKind::Generator); + self.semantic_model.push_scope(ScopeKind::Generator); self.visit_expr(&generator.target); for expr in &generator.ifs { self.visit_boolean_test(expr); @@ -4534,56 +4599,56 @@ impl<'a> Checker<'a> { /// Visit an body of [`Stmt`] nodes within a type-checking block. fn visit_type_checking_block(&mut self, body: &'a [Stmt]) { - let snapshot = self.model.flags; - self.model.flags |= ContextFlags::TYPE_CHECKING_BLOCK; + let snapshot = self.semantic_model.flags; + self.semantic_model.flags |= ContextFlags::TYPE_CHECKING_BLOCK; self.visit_body(body); - self.model.flags = snapshot; + self.semantic_model.flags = snapshot; } /// Visit an [`Expr`], and treat it as a type definition. pub(crate) fn visit_type_definition(&mut self, expr: &'a Expr) { - let snapshot = self.model.flags; - self.model.flags |= ContextFlags::TYPE_DEFINITION; + let snapshot = self.semantic_model.flags; + self.semantic_model.flags |= ContextFlags::TYPE_DEFINITION; self.visit_expr(expr); - self.model.flags = snapshot; + self.semantic_model.flags = snapshot; } /// Visit an [`Expr`], and treat it as _not_ a type definition. pub(crate) fn visit_non_type_definition(&mut self, expr: &'a Expr) { - let snapshot = self.model.flags; - self.model.flags -= ContextFlags::TYPE_DEFINITION; + let snapshot = self.semantic_model.flags; + self.semantic_model.flags -= ContextFlags::TYPE_DEFINITION; self.visit_expr(expr); - self.model.flags = snapshot; + self.semantic_model.flags = snapshot; } /// Visit an [`Expr`], and treat it as a boolean test. This is useful for detecting whether an /// expressions return value is significant, or whether the calling context only relies on /// its truthiness. pub(crate) fn visit_boolean_test(&mut self, expr: &'a Expr) { - let snapshot = self.model.flags; - self.model.flags |= ContextFlags::BOOLEAN_TEST; + let snapshot = self.semantic_model.flags; + self.semantic_model.flags |= ContextFlags::BOOLEAN_TEST; self.visit_expr(expr); - self.model.flags = snapshot; + self.semantic_model.flags = snapshot; } /// Add a [`Binding`] to the current scope, bound to the given name. fn add_binding(&mut self, name: &'a str, binding: Binding<'a>) { - let binding_id = self.model.bindings.next_id(); + let binding_id = self.semantic_model.bindings.next_id(); if let Some((stack_index, existing_binding_id)) = self - .model + .semantic_model .scopes - .ancestors(self.model.scope_id) + .ancestors(self.semantic_model.scope_id) .enumerate() .find_map(|(stack_index, scope)| { scope.get(name).map(|binding_id| (stack_index, *binding_id)) }) { - let existing = &self.model.bindings[existing_binding_id]; + let existing = &self.semantic_model.bindings[existing_binding_id]; let in_current_scope = stack_index == 0; if !existing.kind.is_builtin() && existing.source.map_or(true, |left| { binding.source.map_or(true, |right| { - !branch_detection::different_forks(left, right, &self.model.stmts) + !branch_detection::different_forks(left, right, &self.semantic_model.stmts) }) }) { @@ -4613,8 +4678,10 @@ impl<'a> Checker<'a> { && (!self.settings.dummy_variable_rgx.is_match(name) || existing_is_import) && !(existing.kind.is_function_definition() && analyze::visibility::is_overload( - &self.model, - cast::decorator_list(self.model.stmts[existing.source.unwrap()]), + &self.semantic_model, + cast::decorator_list( + self.semantic_model.stmts[existing.source.unwrap()], + ), )) { if self.settings.rules.enabled(Rule::RedefinedWhileUnused) { @@ -4633,7 +4700,7 @@ impl<'a> Checker<'a> { .then(|| { binding.source.map_or(binding.range, |source| { helpers::identifier_range( - self.model.stmts[source], + self.semantic_model.stmts[source], self.locator, ) }) @@ -4641,7 +4708,7 @@ impl<'a> Checker<'a> { .unwrap_or(binding.range), ); if let Some(parent) = binding.source { - let parent = self.model.stmts[parent]; + let parent = self.semantic_model.stmts[parent]; if matches!(parent, Stmt::ImportFrom(_)) && parent.range().contains_range(binding.range) { @@ -4652,7 +4719,7 @@ impl<'a> Checker<'a> { } } } else if existing_is_import && binding.redefines(existing) { - self.model + self.semantic_model .shadowed_bindings .entry(existing_binding_id) .or_insert_with(Vec::new) @@ -4665,18 +4732,18 @@ impl<'a> Checker<'a> { // expressions in generators and comprehensions bind to the scope that contains the // outermost comprehension. let scope_id = if binding.kind.is_named_expr_assignment() { - self.model + self.semantic_model .scopes - .ancestor_ids(self.model.scope_id) - .find_or_last(|scope_id| !self.model.scopes[*scope_id].kind.is_generator()) - .unwrap_or(self.model.scope_id) + .ancestor_ids(self.semantic_model.scope_id) + .find_or_last(|scope_id| !self.semantic_model.scopes[*scope_id].kind.is_generator()) + .unwrap_or(self.semantic_model.scope_id) } else { - self.model.scope_id + self.semantic_model.scope_id }; - let scope = &mut self.model.scopes[scope_id]; + let scope = &mut self.semantic_model.scopes[scope_id]; let binding = if let Some(index) = scope.get(name) { - let existing = &self.model.bindings[*index]; + let existing = &self.semantic_model.bindings[*index]; match &existing.kind { BindingKind::Builtin => { // Avoid overriding builtins. @@ -4707,7 +4774,7 @@ impl<'a> Checker<'a> { // Don't treat annotations as assignments if there is an existing value // in scope. if binding.kind.is_annotation() && scope.defines(name) { - self.model.bindings.push(binding); + self.semantic_model.bindings.push(binding); return; } @@ -4715,11 +4782,11 @@ impl<'a> Checker<'a> { scope.add(name, binding_id); // Add the binding to the arena. - self.model.bindings.push(binding); + self.semantic_model.bindings.push(binding); } fn bind_builtins(&mut self) { - let scope = &mut self.model.scopes[self.model.scope_id]; + let scope = &mut self.semantic_model.scopes[self.semantic_model.scope_id]; for builtin in BUILTINS .iter() @@ -4727,7 +4794,7 @@ impl<'a> Checker<'a> { .copied() .chain(self.settings.builtins.iter().map(String::as_str)) { - let id = self.model.bindings.push(Binding { + let id = self.semantic_model.bindings.push(Binding { kind: BindingKind::Builtin, range: TextRange::default(), runtime_usage: None, @@ -4745,7 +4812,7 @@ impl<'a> Checker<'a> { let Expr::Name(ast::ExprName { id, .. } )= expr else { return; }; - match self.model.resolve_reference(id, expr.range()) { + match self.semantic_model.resolve_reference(id, expr.range()) { ResolvedReference::Resolved(..) | ResolvedReference::ImplicitGlobal => { // Nothing to do. } @@ -4757,7 +4824,7 @@ impl<'a> Checker<'a> { .enabled(Rule::UndefinedLocalWithImportStarUsage) { let sources: Vec = self - .model + .semantic_model .scopes .iter() .flat_map(Scope::star_imports) @@ -4786,7 +4853,7 @@ impl<'a> Checker<'a> { // Avoid flagging if `NameError` is handled. if self - .model + .semantic_model .handled_exceptions .iter() .any(|handler_names| handler_names.contains(Exceptions::NAME_ERROR)) @@ -4806,7 +4873,7 @@ impl<'a> Checker<'a> { } fn handle_node_store(&mut self, id: &'a str, expr: &Expr) { - let parent = self.model.stmt(); + let parent = self.semantic_model.stmt(); if self.settings.rules.enabled(Rule::UndefinedLocal) { pyflakes::rules::undefined_local(self, id); @@ -4817,14 +4884,11 @@ impl<'a> Checker<'a> { .rules .enabled(Rule::NonLowercaseVariableInFunction) { - if matches!(self.model.scope().kind, ScopeKind::Function(..)) { + if matches!(self.semantic_model.scope().kind, ScopeKind::Function(..)) { // Ignore globals. - if !self - .model - .scope() - .get(id) - .map_or(false, |index| self.model.bindings[*index].kind.is_global()) - { + if !self.semantic_model.scope().get(id).map_or(false, |index| { + self.semantic_model.bindings[*index].kind.is_global() + }) { pep8_naming::rules::non_lowercase_variable_in_function(self, expr, parent, id); } } @@ -4835,7 +4899,7 @@ impl<'a> Checker<'a> { .rules .enabled(Rule::MixedCaseVariableInClassScope) { - if let ScopeKind::Class(class) = &self.model.scope().kind { + if let ScopeKind::Class(class) = &self.semantic_model.scope().kind { pep8_naming::rules::mixed_case_variable_in_class_scope( self, expr, @@ -4851,7 +4915,7 @@ impl<'a> Checker<'a> { .rules .enabled(Rule::MixedCaseVariableInGlobalScope) { - if matches!(self.model.scope().kind, ScopeKind::Module) { + if matches!(self.semantic_model.scope().kind, ScopeKind::Module) { pep8_naming::rules::mixed_case_variable_in_global_scope(self, expr, parent, id); } } @@ -4868,9 +4932,9 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: expr.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); return; @@ -4885,9 +4949,9 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: expr.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); return; @@ -4902,15 +4966,15 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: expr.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); return; } - let scope = self.model.scope(); + let scope = self.semantic_model.scope(); if id == "__all__" && scope.kind.is_module() @@ -4945,13 +5009,13 @@ impl<'a> Checker<'a> { } { let (all_names, all_names_flags) = { let (mut names, flags) = - extract_all_names(parent, |name| self.model.is_builtin(name)); + extract_all_names(parent, |name| self.semantic_model.is_builtin(name)); // Grab the existing bound __all__ values. if let Stmt::AugAssign(_) = parent { if let Some(index) = scope.get("__all__") { if let BindingKind::Export(Export { names: existing }) = - &self.model.bindings[*index].kind + &self.semantic_model.bindings[*index].kind { names.extend_from_slice(existing); } @@ -4983,9 +5047,9 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: expr.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); return; @@ -4993,7 +5057,7 @@ impl<'a> Checker<'a> { } if self - .model + .semantic_model .expr_ancestors() .any(|expr| matches!(expr, Expr::NamedExpr(_))) { @@ -5005,9 +5069,9 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: expr.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); return; @@ -5021,9 +5085,9 @@ impl<'a> Checker<'a> { synthetic_usage: None, typing_usage: None, range: expr.range(), - source: self.model.stmt_id, - context: self.model.execution_context(), - exceptions: self.model.exceptions(), + source: self.semantic_model.stmt_id, + context: self.semantic_model.execution_context(), + exceptions: self.semantic_model.exceptions(), }, ); } @@ -5032,11 +5096,11 @@ impl<'a> Checker<'a> { let Expr::Name(ast::ExprName { id, .. } )= expr else { return; }; - if helpers::on_conditional_branch(&mut self.model.parents()) { + if helpers::on_conditional_branch(&mut self.semantic_model.parents()) { return; } - let scope = self.model.scope_mut(); + let scope = self.semantic_model.scope_mut(); if scope.remove(id.as_str()).is_some() { return; } @@ -5056,9 +5120,9 @@ impl<'a> Checker<'a> { while !self.deferred.future_type_definitions.is_empty() { let type_definitions = std::mem::take(&mut self.deferred.future_type_definitions); for (expr, snapshot) in type_definitions { - self.model.restore(snapshot); + self.semantic_model.restore(snapshot); - self.model.flags |= + self.semantic_model.flags |= ContextFlags::TYPE_DEFINITION | ContextFlags::FUTURE_TYPE_DEFINITION; self.visit_expr(expr); } @@ -5072,9 +5136,11 @@ impl<'a> Checker<'a> { if let Ok((expr, kind)) = parse_type_annotation(value, range, self.locator) { let expr = allocator.alloc(expr); - self.model.restore(snapshot); + self.semantic_model.restore(snapshot); - if self.model.in_annotation() && self.model.future_annotations() { + if self.semantic_model.in_annotation() + && self.semantic_model.future_annotations() + { if self.settings.rules.enabled(Rule::QuotedAnnotation) { pyupgrade::rules::quoted_annotation(self, value, range); } @@ -5090,7 +5156,8 @@ impl<'a> Checker<'a> { AnnotationKind::Complex => ContextFlags::COMPLEX_STRING_TYPE_DEFINITION, }; - self.model.flags |= ContextFlags::TYPE_DEFINITION | type_definition_flag; + self.semantic_model.flags |= + ContextFlags::TYPE_DEFINITION | type_definition_flag; self.visit_expr(expr); } else { if self @@ -5114,9 +5181,9 @@ impl<'a> Checker<'a> { while !self.deferred.functions.is_empty() { let deferred_functions = std::mem::take(&mut self.deferred.functions); for snapshot in deferred_functions { - self.model.restore(snapshot); + self.semantic_model.restore(snapshot); - match &self.model.stmt() { + match &self.semantic_model.stmt() { Stmt::FunctionDef(ast::StmtFunctionDef { body, args, .. }) | Stmt::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, args, .. }) => { self.visit_arguments(args); @@ -5136,7 +5203,7 @@ impl<'a> Checker<'a> { while !self.deferred.lambdas.is_empty() { let lambdas = std::mem::take(&mut self.deferred.lambdas); for (expr, snapshot) in lambdas { - self.model.restore(snapshot); + self.semantic_model.restore(snapshot); if let Expr::Lambda(ast::ExprLambda { args, @@ -5159,14 +5226,14 @@ impl<'a> Checker<'a> { while !self.deferred.assignments.is_empty() { let assignments = std::mem::take(&mut self.deferred.assignments); for snapshot in assignments { - self.model.restore(snapshot); + self.semantic_model.restore(snapshot); // pyflakes if self.settings.rules.enabled(Rule::UnusedVariable) { - pyflakes::rules::unused_variable(self, self.model.scope_id); + pyflakes::rules::unused_variable(self, self.semantic_model.scope_id); } if self.settings.rules.enabled(Rule::UnusedAnnotation) { - pyflakes::rules::unused_annotation(self, self.model.scope_id); + pyflakes::rules::unused_annotation(self, self.semantic_model.scope_id); } if !self.is_stub { @@ -5178,14 +5245,14 @@ impl<'a> Checker<'a> { Rule::UnusedStaticMethodArgument, Rule::UnusedLambdaArgument, ]) { - let scope = &self.model.scopes[self.model.scope_id]; - let parent = &self.model.scopes[scope.parent.unwrap()]; + let scope = &self.semantic_model.scopes[self.semantic_model.scope_id]; + let parent = &self.semantic_model.scopes[scope.parent.unwrap()]; self.diagnostics .extend(flake8_unused_arguments::rules::unused_arguments( self, parent, scope, - &self.model.bindings, + &self.semantic_model.bindings, )); } } @@ -5198,10 +5265,11 @@ impl<'a> Checker<'a> { let for_loops = std::mem::take(&mut self.deferred.for_loops); for snapshot in for_loops { - self.model.restore(snapshot); + self.semantic_model.restore(snapshot); if let Stmt::For(ast::StmtFor { target, body, .. }) - | Stmt::AsyncFor(ast::StmtAsyncFor { target, body, .. }) = &self.model.stmt() + | Stmt::AsyncFor(ast::StmtAsyncFor { target, body, .. }) = + &self.semantic_model.stmt() { if self.settings.rules.enabled(Rule::UnusedLoopControlVariable) { flake8_bugbear::rules::unused_loop_control_variable(self, target, body); @@ -5236,10 +5304,10 @@ impl<'a> Checker<'a> { // Mark anything referenced in `__all__` as used. let all_bindings: Option<(Vec, TextRange)> = { - let global_scope = self.model.global_scope(); + let global_scope = self.semantic_model.global_scope(); let all_names: Option<(&[&str], TextRange)> = global_scope .get("__all__") - .map(|index| &self.model.bindings[*index]) + .map(|index| &self.semantic_model.bindings[*index]) .and_then(|binding| match &binding.kind { BindingKind::Export(Export { names }) => { Some((names.as_slice(), binding.range)) @@ -5260,7 +5328,7 @@ impl<'a> Checker<'a> { if let Some((bindings, range)) = all_bindings { for index in bindings { - self.model.bindings[index].mark_used( + self.semantic_model.bindings[index].mark_used( ScopeId::global(), range, ExecutionContext::Runtime, @@ -5270,10 +5338,10 @@ impl<'a> Checker<'a> { // Extract `__all__` names from the global scope. let all_names: Option<(&[&str], TextRange)> = self - .model + .semantic_model .global_scope() .get("__all__") - .map(|index| &self.model.bindings[*index]) + .map(|index| &self.semantic_model.bindings[*index]) .and_then(|binding| match &binding.kind { BindingKind::Export(Export { names }) => Some((names.as_slice(), binding.range)), _ => None, @@ -5286,13 +5354,13 @@ impl<'a> Checker<'a> { if self.settings.flake8_type_checking.strict { vec![] } else { - self.model + self.semantic_model .scopes .iter() .map(|scope| { scope .binding_ids() - .map(|index| &self.model.bindings[*index]) + .map(|index| &self.semantic_model.bindings[*index]) .filter(|binding| { flake8_type_checking::helpers::is_valid_runtime_import(binding) }) @@ -5305,8 +5373,8 @@ impl<'a> Checker<'a> { }; let mut diagnostics: Vec = vec![]; - for scope_id in self.model.dead_scopes.iter().rev() { - let scope = &self.model.scopes[*scope_id]; + for scope_id in self.semantic_model.dead_scopes.iter().rev() { + let scope = &self.semantic_model.scopes[*scope_id]; if scope.kind.is_module() { // F822 @@ -5354,10 +5422,10 @@ impl<'a> Checker<'a> { // PLW0602 if self.settings.rules.enabled(Rule::GlobalVariableNotAssigned) { for (name, index) in scope.bindings() { - let binding = &self.model.bindings[*index]; + let binding = &self.semantic_model.bindings[*index]; if binding.kind.is_global() { if let Some(source) = binding.source { - let stmt = &self.model.stmts[source]; + let stmt = &self.semantic_model.stmts[source]; if matches!(stmt, Stmt::Global(_)) { diagnostics.push(Diagnostic::new( pylint::rules::GlobalVariableNotAssigned { @@ -5381,7 +5449,7 @@ impl<'a> Checker<'a> { // the bindings are in different scopes. if self.settings.rules.enabled(Rule::RedefinedWhileUnused) { for (name, index) in scope.bindings() { - let binding = &self.model.bindings[*index]; + let binding = &self.semantic_model.bindings[*index]; if matches!( binding.kind, @@ -5394,9 +5462,9 @@ impl<'a> Checker<'a> { continue; } - if let Some(indices) = self.model.shadowed_bindings.get(index) { + if let Some(indices) = self.semantic_model.shadowed_bindings.get(index) { for index in indices { - let rebound = &self.model.bindings[*index]; + let rebound = &self.semantic_model.bindings[*index]; #[allow(deprecated)] let line = self.locator.compute_line_index(binding.range.start()); @@ -5413,7 +5481,7 @@ impl<'a> Checker<'a> { .then(|| { rebound.source.map_or(rebound.range, |source| { helpers::identifier_range( - self.model.stmts[source], + self.semantic_model.stmts[source], self.locator, ) }) @@ -5421,7 +5489,7 @@ impl<'a> Checker<'a> { .unwrap_or(rebound.range), ); if let Some(source) = rebound.source { - let parent = &self.model.stmts[source]; + let parent = &self.semantic_model.stmts[source]; if matches!(parent, Stmt::ImportFrom(_)) && parent.range().contains_range(rebound.range) { @@ -5439,7 +5507,7 @@ impl<'a> Checker<'a> { let runtime_imports: Vec<&Binding> = if self.settings.flake8_type_checking.strict { vec![] } else { - self.model + self.semantic_model .scopes .ancestor_ids(*scope_id) .flat_map(|scope_id| runtime_imports[usize::from(scope_id)].iter()) @@ -5447,7 +5515,7 @@ impl<'a> Checker<'a> { .collect() }; for index in scope.binding_ids() { - let binding = &self.model.bindings[*index]; + let binding = &self.semantic_model.bindings[*index]; if let Some(diagnostic) = flake8_type_checking::rules::runtime_import_in_type_checking_block(binding) @@ -5482,7 +5550,7 @@ impl<'a> Checker<'a> { FxHashMap::default(); for index in scope.binding_ids() { - let binding = &self.model.bindings[*index]; + let binding = &self.semantic_model.bindings[*index]; let full_name = match &binding.kind { BindingKind::Importation(Importation { full_name, .. }) => full_name, @@ -5501,11 +5569,11 @@ impl<'a> Checker<'a> { } let child_id = binding.source.unwrap(); - let parent_id = self.model.stmts.parent_id(child_id); + let parent_id = self.semantic_model.stmts.parent_id(child_id); let exceptions = binding.exceptions; let diagnostic_offset = binding.range.start(); - let child = &self.model.stmts[child_id]; + let child = &self.semantic_model.stmts[child_id]; let parent_offset = if matches!(child, Stmt::ImportFrom(_)) { Some(child.start()) } else { @@ -5535,8 +5603,8 @@ impl<'a> Checker<'a> { .into_iter() .sorted_by_key(|((defined_by, ..), ..)| *defined_by) { - let child = self.model.stmts[defined_by]; - let parent = defined_in.map(|defined_in| self.model.stmts[defined_in]); + let child = self.semantic_model.stmts[defined_by]; + let parent = defined_in.map(|defined_in| self.semantic_model.stmts[defined_in]); let multiple = unused_imports.len() > 1; let in_except_handler = exceptions .intersects(Exceptions::MODULE_NOT_FOUND_ERROR | Exceptions::IMPORT_ERROR); @@ -5597,7 +5665,7 @@ impl<'a> Checker<'a> { .into_iter() .sorted_by_key(|((defined_by, ..), ..)| *defined_by) { - let child = self.model.stmts[child]; + let child = self.semantic_model.stmts[child]; let multiple = unused_imports.len() > 1; let in_except_handler = exceptions .intersects(Exceptions::MODULE_NOT_FOUND_ERROR | Exceptions::IMPORT_ERROR); @@ -5702,15 +5770,15 @@ impl<'a> Checker<'a> { } // Compute visibility of all definitions. - let global_scope = self.model.global_scope(); + let global_scope = self.semantic_model.global_scope(); let exports: Option<&[&str]> = global_scope .get("__all__") - .map(|index| &self.model.bindings[*index]) + .map(|index| &self.semantic_model.bindings[*index]) .and_then(|binding| match &binding.kind { BindingKind::Export(Export { names }) => Some(names.as_slice()), _ => None, }); - let definitions = std::mem::take(&mut self.model.definitions); + let definitions = std::mem::take(&mut self.semantic_model.definitions); let mut overloaded_name: Option = None; for ContextualizedDefinition { @@ -5729,7 +5797,7 @@ impl<'a> Checker<'a> { // classes, etc.). if !overloaded_name.map_or(false, |overloaded_name| { flake8_annotations::helpers::is_overload_impl( - &self.model, + &self.semantic_model, definition, &overloaded_name, ) @@ -5742,7 +5810,7 @@ impl<'a> Checker<'a> { )); } overloaded_name = - flake8_annotations::helpers::overloaded_name(&self.model, definition); + flake8_annotations::helpers::overloaded_name(&self.semantic_model, definition); } // flake8-pyi @@ -5757,7 +5825,7 @@ impl<'a> Checker<'a> { // pydocstyle if enforce_docstrings { if pydocstyle::helpers::should_ignore_definition( - &self.model, + &self.semantic_model, definition, &self.settings.pydocstyle.ignore_decorators, ) { @@ -5964,8 +6032,8 @@ pub(crate) fn check_ast( checker.check_definitions(); // Reset the scope to module-level, and check all consumed scopes. - checker.model.scope_id = ScopeId::global(); - checker.model.dead_scopes.push(ScopeId::global()); + checker.semantic_model.scope_id = ScopeId::global(); + checker.semantic_model.dead_scopes.push(ScopeId::global()); checker.check_dead_scopes(); checker.diagnostics diff --git a/crates/ruff/src/rules/flake8_2020/rules.rs b/crates/ruff/src/rules/flake8_2020/rules.rs index 3c94f342d2..a8973c30b6 100644 --- a/crates/ruff/src/rules/flake8_2020/rules.rs +++ b/crates/ruff/src/rules/flake8_2020/rules.rs @@ -122,7 +122,7 @@ fn is_sys(model: &SemanticModel, expr: &Expr, target: &str) -> bool { /// YTT101, YTT102, YTT301, YTT303 pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) { - if is_sys(&checker.model, value, "version") { + if is_sys(checker.semantic_model(), value, "version") { match slice { Expr::Slice(ast::ExprSlice { lower: None, @@ -176,7 +176,7 @@ pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) { pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &[Expr]) { match left { Expr::Subscript(ast::ExprSubscript { value, slice, .. }) - if is_sys(&checker.model, value, "version_info") => + if is_sys(checker.semantic_model(), value, "version_info") => { if let Expr::Constant(ast::ExprConstant { value: Constant::Int(i), @@ -220,7 +220,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara } Expr::Attribute(ast::ExprAttribute { value, attr, .. }) - if is_sys(&checker.model, value, "version_info") && attr == "minor" => + if is_sys(checker.semantic_model(), value, "version_info") && attr == "minor" => { if let ( [Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], @@ -245,7 +245,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara _ => {} } - if is_sys(&checker.model, left, "version") { + if is_sys(checker.semantic_model(), left, "version") { if let ( [Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], [Expr::Constant(ast::ExprConstant { @@ -272,7 +272,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara /// YTT202 pub(crate) fn name_or_attribute(checker: &mut Checker, expr: &Expr) { if checker - .model + .semantic_model() .resolve_call_path(expr) .map_or(false, |call_path| call_path.as_slice() == ["six", "PY3"]) { diff --git a/crates/ruff/src/rules/flake8_annotations/rules.rs b/crates/ruff/src/rules/flake8_annotations/rules.rs index 0f2612e7e2..02ca3c1418 100644 --- a/crates/ruff/src/rules/flake8_annotations/rules.rs +++ b/crates/ruff/src/rules/flake8_annotations/rules.rs @@ -480,7 +480,7 @@ pub(crate) fn definition( // unless configured to suppress ANN* for declarations that are fully untyped. let mut diagnostics = Vec::new(); - let is_overridden = visibility::is_override(&checker.model, decorator_list); + let is_overridden = visibility::is_override(checker.semantic_model(), decorator_list); // ANN001, ANN401 for arg in args @@ -492,7 +492,10 @@ pub(crate) fn definition( // If this is a non-static method, skip `cls` or `self`. usize::from( is_method - && !visibility::is_staticmethod(&checker.model, cast::decorator_list(stmt)), + && !visibility::is_staticmethod( + checker.semantic_model(), + cast::decorator_list(stmt), + ), ), ) { @@ -501,7 +504,7 @@ pub(crate) fn definition( has_any_typed_arg = true; if checker.settings.rules.enabled(Rule::AnyType) { check_dynamically_typed( - &checker.model, + checker.semantic_model(), annotation, || arg.arg.to_string(), &mut diagnostics, @@ -536,7 +539,7 @@ pub(crate) fn definition( if checker.settings.rules.enabled(Rule::AnyType) { let name = &arg.arg; check_dynamically_typed( - &checker.model, + checker.semantic_model(), expr, || format!("*{name}"), &mut diagnostics, @@ -568,7 +571,7 @@ pub(crate) fn definition( if checker.settings.rules.enabled(Rule::AnyType) { let name = &arg.arg; check_dynamically_typed( - &checker.model, + checker.semantic_model(), expr, || format!("**{name}"), &mut diagnostics, @@ -593,10 +596,13 @@ pub(crate) fn definition( } // ANN101, ANN102 - if is_method && !visibility::is_staticmethod(&checker.model, cast::decorator_list(stmt)) { + if is_method + && !visibility::is_staticmethod(checker.semantic_model(), cast::decorator_list(stmt)) + { if let Some(arg) = args.posonlyargs.first().or_else(|| args.args.first()) { if arg.annotation.is_none() { - if visibility::is_classmethod(&checker.model, cast::decorator_list(stmt)) { + if visibility::is_classmethod(checker.semantic_model(), cast::decorator_list(stmt)) + { if checker.settings.rules.enabled(Rule::MissingTypeCls) { diagnostics.push(Diagnostic::new( MissingTypeCls { @@ -626,7 +632,7 @@ pub(crate) fn definition( has_typed_return = true; if checker.settings.rules.enabled(Rule::AnyType) { check_dynamically_typed( - &checker.model, + checker.semantic_model(), expr, || name.to_string(), &mut diagnostics, @@ -638,7 +644,9 @@ pub(crate) fn definition( // (explicitly or implicitly). checker.settings.flake8_annotations.suppress_none_returning && is_none_returning(body) ) { - if is_method && visibility::is_classmethod(&checker.model, cast::decorator_list(stmt)) { + if is_method + && visibility::is_classmethod(checker.semantic_model(), cast::decorator_list(stmt)) + { if checker .settings .rules @@ -652,7 +660,7 @@ pub(crate) fn definition( )); } } else if is_method - && visibility::is_staticmethod(&checker.model, cast::decorator_list(stmt)) + && visibility::is_staticmethod(checker.semantic_model(), cast::decorator_list(stmt)) { if checker .settings diff --git a/crates/ruff/src/rules/flake8_async/rules.rs b/crates/ruff/src/rules/flake8_async/rules.rs index 9622d35f35..88b0b98123 100644 --- a/crates/ruff/src/rules/flake8_async/rules.rs +++ b/crates/ruff/src/rules/flake8_async/rules.rs @@ -66,15 +66,17 @@ const BLOCKING_HTTP_CALLS: &[&[&str]] = &[ /// ASYNC100 pub(crate) fn blocking_http_call(checker: &mut Checker, expr: &Expr) { - if in_async_function(&checker.model) { + if in_async_function(checker.semantic_model()) { if let Expr::Call(ast::ExprCall { func, .. }) = expr { - if let Some(call_path) = checker.model.resolve_call_path(func) { - if BLOCKING_HTTP_CALLS.contains(&call_path.as_slice()) { - checker.diagnostics.push(Diagnostic::new( - BlockingHttpCallInAsyncFunction, - func.range(), - )); - } + let call_path = checker.semantic_model().resolve_call_path(func); + let is_blocking = + call_path.map_or(false, |path| BLOCKING_HTTP_CALLS.contains(&path.as_slice())); + + if is_blocking { + checker.diagnostics.push(Diagnostic::new( + BlockingHttpCallInAsyncFunction, + func.range(), + )); } } } @@ -133,15 +135,20 @@ const OPEN_SLEEP_OR_SUBPROCESS_CALL: &[&[&str]] = &[ /// ASYNC101 pub(crate) fn open_sleep_or_subprocess_call(checker: &mut Checker, expr: &Expr) { - if in_async_function(&checker.model) { + if in_async_function(checker.semantic_model()) { if let Expr::Call(ast::ExprCall { func, .. }) = expr { - if let Some(call_path) = checker.model.resolve_call_path(func) { - if OPEN_SLEEP_OR_SUBPROCESS_CALL.contains(&call_path.as_slice()) { - checker.diagnostics.push(Diagnostic::new( - OpenSleepOrSubprocessInAsyncFunction, - func.range(), - )); - } + let is_open_sleep_or_subprocess_call = checker + .semantic_model() + .resolve_call_path(func) + .map_or(false, |path| { + OPEN_SLEEP_OR_SUBPROCESS_CALL.contains(&path.as_slice()) + }); + + if is_open_sleep_or_subprocess_call { + checker.diagnostics.push(Diagnostic::new( + OpenSleepOrSubprocessInAsyncFunction, + func.range(), + )); } } } @@ -197,14 +204,17 @@ const UNSAFE_OS_METHODS: &[&[&str]] = &[ /// ASYNC102 pub(crate) fn blocking_os_call(checker: &mut Checker, expr: &Expr) { - if in_async_function(&checker.model) { + if in_async_function(checker.semantic_model()) { if let Expr::Call(ast::ExprCall { func, .. }) = expr { - if let Some(call_path) = checker.model.resolve_call_path(func) { - if UNSAFE_OS_METHODS.contains(&call_path.as_slice()) { - checker - .diagnostics - .push(Diagnostic::new(BlockingOsCallInAsyncFunction, func.range())); - } + let is_unsafe_os_method = checker + .semantic_model() + .resolve_call_path(func) + .map_or(false, |path| UNSAFE_OS_METHODS.contains(&path.as_slice())); + + if is_unsafe_os_method { + checker + .diagnostics + .push(Diagnostic::new(BlockingOsCallInAsyncFunction, func.range())); } } } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs b/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs index 2b5463dcae..7bcf81dff6 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/bad_file_permissions.rs @@ -108,7 +108,7 @@ pub(crate) fn bad_file_permissions( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["os", "chmod"]) { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs index 1b7cabb0ba..4595dce6c7 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hardcoded_sql_expression.rs @@ -60,7 +60,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio op: Operator::Add | Operator::Mod, .. }) => { - let Some(parent) = checker.model.expr_parent() else { + let Some(parent) = checker.semantic_model().expr_parent() else { if any_over_expr(expr, &has_string_literal) { return Some(checker.generator().expr(expr)); } diff --git a/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs b/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs index 9edb3fb423..6948f6323b 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/hashlib_insecure_hash_functions.rs @@ -48,16 +48,21 @@ pub(crate) fn hashlib_insecure_hash_functions( args: &[Expr], keywords: &[Keyword], ) { - if let Some(hashlib_call) = checker.model.resolve_call_path(func).and_then(|call_path| { - if call_path.as_slice() == ["hashlib", "new"] { - Some(HashlibCall::New) - } else { - WEAK_HASHES - .iter() - .find(|hash| call_path.as_slice() == ["hashlib", hash]) - .map(|hash| HashlibCall::WeakHash(hash)) - } - }) { + if let Some(hashlib_call) = + checker + .semantic_model() + .resolve_call_path(func) + .and_then(|call_path| { + if call_path.as_slice() == ["hashlib", "new"] { + Some(HashlibCall::New) + } else { + WEAK_HASHES + .iter() + .find(|hash| call_path.as_slice() == ["hashlib", hash]) + .map(|hash| HashlibCall::WeakHash(hash)) + } + }) + { match hashlib_call { HashlibCall::New => { let call_args = SimpleCallArgs::new(args, keywords); diff --git a/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs b/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs index 43a1c41ed8..06a2e77081 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/jinja2_autoescape_false.rs @@ -37,7 +37,7 @@ pub(crate) fn jinja2_autoescape_false( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["jinja2", "Environment"] diff --git a/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs b/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs index d2a6c408c3..6fc645bb88 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/logging_config_insecure_listen.rs @@ -24,7 +24,7 @@ pub(crate) fn logging_config_insecure_listen( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["logging", "config", "listen"] diff --git a/crates/ruff/src/rules/flake8_bandit/rules/paramiko_calls.rs b/crates/ruff/src/rules/flake8_bandit/rules/paramiko_calls.rs index 28520da8d6..e340a09ca4 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/paramiko_calls.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/paramiko_calls.rs @@ -18,7 +18,7 @@ impl Violation for ParamikoCall { /// S601 pub(crate) fn paramiko_call(checker: &mut Checker, func: &Expr) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["paramiko", "exec_command"] diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs index 4fab850708..fe45fb6e76 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_with_no_cert_validation.rs @@ -43,17 +43,21 @@ pub(crate) fn request_with_no_cert_validation( args: &[Expr], keywords: &[Keyword], ) { - if let Some(target) = checker.model.resolve_call_path(func).and_then(|call_path| { - if call_path.len() == 2 { - if call_path[0] == "requests" && REQUESTS_HTTP_VERBS.contains(&call_path[1]) { - return Some("requests"); + if let Some(target) = checker + .semantic_model() + .resolve_call_path(func) + .and_then(|call_path| { + if call_path.len() == 2 { + if call_path[0] == "requests" && REQUESTS_HTTP_VERBS.contains(&call_path[1]) { + return Some("requests"); + } + if call_path[0] == "httpx" && HTTPX_METHODS.contains(&call_path[1]) { + return Some("httpx"); + } } - if call_path[0] == "httpx" && HTTPX_METHODS.contains(&call_path[1]) { - return Some("httpx"); - } - } - None - }) { + None + }) + { let call_args = SimpleCallArgs::new(args, keywords); if let Some(verify_arg) = call_args.keyword_argument("verify") { if let Expr::Constant(ast::ExprConstant { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs index dff91da386..b08edbd4fa 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/request_without_timeout.rs @@ -34,7 +34,7 @@ pub(crate) fn request_without_timeout( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { HTTP_VERBS diff --git a/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs b/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs index a4d12ba1e6..d8cd1993d7 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/shell_injection.rs @@ -184,11 +184,11 @@ pub(crate) fn shell_injection( args: &[Expr], keywords: &[Keyword], ) { - let call_kind = get_call_kind(func, &checker.model); + let call_kind = get_call_kind(func, checker.semantic_model()); if matches!(call_kind, Some(CallKind::Subprocess)) { if let Some(arg) = args.first() { - match find_shell_keyword(&checker.model, keywords) { + match find_shell_keyword(checker.semantic_model(), keywords) { // S602 Some(ShellKeyword { truthiness: Truthiness::Truthy, @@ -241,7 +241,7 @@ pub(crate) fn shell_injection( } else if let Some(ShellKeyword { truthiness: Truthiness::Truthy, keyword, - }) = find_shell_keyword(&checker.model, keywords) + }) = find_shell_keyword(checker.semantic_model(), keywords) { // S604 if checker diff --git a/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs b/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs index dc3897459c..60fc3b33dd 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/snmp_insecure_version.rs @@ -25,7 +25,7 @@ pub(crate) fn snmp_insecure_version( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["pysnmp", "hlapi", "CommunityData"] diff --git a/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs b/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs index 03ab93e936..313c32a187 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/snmp_weak_cryptography.rs @@ -27,7 +27,7 @@ pub(crate) fn snmp_weak_cryptography( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["pysnmp", "hlapi", "UsmUserData"] diff --git a/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs b/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs index b139a4f80e..3042c3568f 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/suspicious_function_call.rs @@ -470,7 +470,7 @@ pub(crate) fn suspicious_function_call(checker: &mut Checker, expr: &Expr) { return; }; - let Some(reason) = checker.model.resolve_call_path(func).and_then(|call_path| { + let Some(reason) = checker.semantic_model().resolve_call_path(func).and_then(|call_path| { for module in SUSPICIOUS_MEMBERS { for member in module.members { if call_path.as_slice() == *member { diff --git a/crates/ruff/src/rules/flake8_bandit/rules/try_except_continue.rs b/crates/ruff/src/rules/flake8_bandit/rules/try_except_continue.rs index 924e227c13..a64c33bc39 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/try_except_continue.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/try_except_continue.rs @@ -27,7 +27,7 @@ pub(crate) fn try_except_continue( ) { if body.len() == 1 && body[0].is_continue_stmt() - && (check_typed_exception || is_untyped_exception(type_, &checker.model)) + && (check_typed_exception || is_untyped_exception(type_, checker.semantic_model())) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bandit/rules/try_except_pass.rs b/crates/ruff/src/rules/flake8_bandit/rules/try_except_pass.rs index a104d27cdf..c740399349 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/try_except_pass.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/try_except_pass.rs @@ -27,7 +27,7 @@ pub(crate) fn try_except_pass( ) { if body.len() == 1 && body[0].is_pass_stmt() - && (check_typed_exception || is_untyped_exception(type_, &checker.model)) + && (check_typed_exception || is_untyped_exception(type_, checker.semantic_model())) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs b/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs index 34b90467be..e5225eb0d4 100644 --- a/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs +++ b/crates/ruff/src/rules/flake8_bandit/rules/unsafe_yaml_load.rs @@ -38,14 +38,14 @@ pub(crate) fn unsafe_yaml_load( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["yaml", "load"]) { let call_args = SimpleCallArgs::new(args, keywords); if let Some(loader_arg) = call_args.argument("Loader", 1) { if !checker - .model + .semantic_model() .resolve_call_path(loader_arg) .map_or(false, |call_path| { call_path.as_slice() == ["yaml", "SafeLoader"] diff --git a/crates/ruff/src/rules/flake8_blind_except/rules.rs b/crates/ruff/src/rules/flake8_blind_except/rules.rs index a561ac1475..ef4f52524e 100644 --- a/crates/ruff/src/rules/flake8_blind_except/rules.rs +++ b/crates/ruff/src/rules/flake8_blind_except/rules.rs @@ -34,7 +34,7 @@ pub(crate) fn blind_except( return; }; for exception in ["BaseException", "Exception"] { - if id == exception && checker.model.is_builtin(exception) { + if id == exception && checker.semantic_model().is_builtin(exception) { // If the exception is re-raised, don't flag an error. if body.iter().any(|stmt| { if let Stmt::Raise(ast::StmtRaise { exc, .. }) = stmt { @@ -58,7 +58,7 @@ pub(crate) fn blind_except( if body.iter().any(|stmt| { if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt { if let Expr::Call(ast::ExprCall { func, keywords, .. }) = value.as_ref() { - if logging::is_logger_candidate(func, &checker.model) { + if logging::is_logger_candidate(func, checker.semantic_model()) { if let Some(attribute) = func.as_attribute_expr() { let attr = attribute.attr.as_str(); if attr == "exception" { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs b/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs index 305685722b..f0980ed813 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs @@ -79,7 +79,7 @@ pub(crate) fn abstract_base_class( if bases.len() + keywords.len() != 1 { return; } - if !is_abc_class(&checker.model, bases, keywords) { + if !is_abc_class(checker.semantic_model(), bases, keywords) { return; } @@ -108,7 +108,7 @@ pub(crate) fn abstract_base_class( continue; }; - let has_abstract_decorator = is_abstract(&checker.model, decorator_list); + let has_abstract_decorator = is_abstract(checker.semantic_model(), decorator_list); has_abstract_method |= has_abstract_decorator; if !checker @@ -121,7 +121,7 @@ pub(crate) fn abstract_base_class( if !has_abstract_decorator && is_empty_body(body) - && !is_overload(&checker.model, decorator_list) + && !is_overload(checker.semantic_model(), decorator_list) { checker.diagnostics.push(Diagnostic::new( EmptyMethodWithoutAbstractDecorator { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs b/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs index 7eca579ab6..be7a22f54e 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/assert_raises_exception.rs @@ -66,7 +66,7 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: } if !checker - .model + .semantic_model() .resolve_call_path(args.first().unwrap()) .map_or(false, |call_path| call_path.as_slice() == ["", "Exception"]) { @@ -78,7 +78,7 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: { AssertionKind::AssertRaises } else if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["pytest", "raises"] diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs b/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs index 6da3d29736..4c2032ec8f 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/cached_instance_method.rs @@ -28,7 +28,7 @@ fn is_cache_func(model: &SemanticModel, expr: &Expr) -> bool { /// B019 pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[Expr]) { - if !matches!(checker.model.scope().kind, ScopeKind::Class(_)) { + if !matches!(checker.semantic_model().scope().kind, ScopeKind::Class(_)) { return; } for decorator in decorator_list { @@ -42,7 +42,7 @@ pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[Ex } for decorator in decorator_list { if is_cache_func( - &checker.model, + checker.semantic_model(), match decorator { Expr::Call(ast::ExprCall { func, .. }) => func, _ => decorator, diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/function_call_argument_default.rs b/crates/ruff/src/rules/flake8_bugbear/rules/function_call_argument_default.rs index ebb78dc9b8..0d013ec7d3 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/function_call_argument_default.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/function_call_argument_default.rs @@ -149,7 +149,8 @@ pub(crate) fn function_call_argument_default(checker: &mut Checker, arguments: & .map(|target| from_qualified_name(target)) .collect(); let diagnostics = { - let mut visitor = ArgumentDefaultVisitor::new(&checker.model, extend_immutable_calls); + let mut visitor = + ArgumentDefaultVisitor::new(checker.semantic_model(), extend_immutable_calls); for expr in arguments .defaults .iter() diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs b/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs index 3b8f0cdab1..19698f8120 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/mutable_argument_default.rs @@ -64,11 +64,10 @@ pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Argume .zip(arguments.defaults.iter().rev()), ) { - if is_mutable_expr(&checker.model, default) - && !arg - .annotation - .as_ref() - .map_or(false, |expr| is_immutable_annotation(&checker.model, expr)) + if is_mutable_expr(checker.semantic_model(), default) + && !arg.annotation.as_ref().map_or(false, |expr| { + is_immutable_annotation(checker.semantic_model(), expr) + }) { checker .diagnostics diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs b/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs index 6616abe659..a7d20c2801 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/no_explicit_stacklevel.rs @@ -45,7 +45,7 @@ pub(crate) fn no_explicit_stacklevel( keywords: &[Keyword], ) { if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["warnings", "warn"] diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs b/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs index c949d23de9..618af80195 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/reuse_of_groupby_generator.rs @@ -342,7 +342,7 @@ pub(crate) fn reuse_of_groupby_generator( }; // Check if the function call is `itertools.groupby` if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["itertools", "groupby"] diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs b/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs index 8a320aa122..d51201a94d 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/setattr_with_constant.rs @@ -75,7 +75,7 @@ pub(crate) fn setattr_with_constant( if let Stmt::Expr(ast::StmtExpr { value: child, range: _, - }) = &checker.model.stmt() + }) = checker.semantic_model().stmt() { if expr == child.as_ref() { let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range()); diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs b/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs index 9f13b25a87..cdb4de65f5 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/unused_loop_control_variable.rs @@ -129,7 +129,7 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr, // Avoid fixing any variables that _may_ be used, but undetectably so. let certainty = Certainty::from(!helpers::uses_magic_variable_access(body, |id| { - checker.model.is_builtin(id) + checker.semantic_model().is_builtin(id) })); // Attempt to rename the variable by prepending an underscore, but avoid @@ -153,11 +153,11 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr, if let Some(rename) = rename { if certainty.into() && checker.patch(diagnostic.kind.rule()) { // Find the `BindingKind::LoopVar` corresponding to the name. - let scope = checker.model.scope(); + let scope = checker.semantic_model().scope(); let binding = scope.bindings_for_name(name).find_map(|index| { - let binding = &checker.model.bindings[*index]; + let binding = &checker.semantic_model().bindings[*index]; binding.source.and_then(|source| { - (Some(source) == checker.model.stmt_id).then_some(binding) + (Some(source) == checker.semantic_model().stmt_id).then_some(binding) }) }); if let Some(binding) = binding { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs b/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs index 4bd6de3a69..456d47af04 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/useless_contextlib_suppress.rs @@ -27,7 +27,7 @@ pub(crate) fn useless_contextlib_suppress( ) { if args.is_empty() && checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["contextlib", "suppress"] diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs b/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs index 44f8b1b107..00376dc8b0 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/useless_expression.rs @@ -53,7 +53,7 @@ pub(crate) fn useless_expression(checker: &mut Checker, value: &Expr) { } // Ignore statements that have side effects. - if contains_effect(value, |id| checker.model.is_builtin(id)) { + if contains_effect(value, |id| checker.semantic_model().is_builtin(id)) { // Flag attributes as useless expressions, even if they're attached to calls or other // expressions. if matches!(value, Expr::Attribute(_)) { diff --git a/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs b/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs index d7b02e6581..e1314239e0 100644 --- a/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs +++ b/crates/ruff/src/rules/flake8_bugbear/rules/zip_without_explicit_strict.rs @@ -24,7 +24,7 @@ pub(crate) fn zip_without_explicit_strict( ) { if let Expr::Name(ast::ExprName { id, .. }) = func { if id == "zip" - && checker.model.is_builtin("zip") + && checker.semantic_model().is_builtin("zip") && !kwargs .iter() .any(|keyword| keyword.arg.as_ref().map_or(false, |name| name == "strict")) diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs index f647d227c0..f94fb7e0bf 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_call_around_sorted.rs @@ -75,7 +75,7 @@ pub(crate) fn unnecessary_call_around_sorted( if inner != "sorted" { return; } - if !checker.model.is_builtin(inner) || !checker.model.is_builtin(outer) { + if !checker.semantic_model().is_builtin(inner) || !checker.semantic_model().is_builtin(outer) { return; } let mut diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs index 0d049983c0..e559d50bb3 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_collection_call.rs @@ -79,7 +79,7 @@ pub(crate) fn unnecessary_collection_call( } _ => return, }; - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; } let mut diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs index d3459ee274..498e86edc4 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs @@ -56,7 +56,7 @@ fn add_diagnostic(checker: &mut Checker, expr: &Expr) { Expr::DictComp(_) => "dict", _ => return, }; - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; } let mut diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs index 4a55a0600d..c3aac344dc 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_comprehension_any_all.rs @@ -76,7 +76,7 @@ pub(crate) fn unnecessary_comprehension_any_all( if is_async_generator(elt) { return; } - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; } let mut diagnostic = Diagnostic::new(UnnecessaryComprehensionAnyAll, args[0].range()); diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs index 0c7bcea021..96cec22cf0 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_double_cast_or_process.rs @@ -90,7 +90,7 @@ pub(crate) fn unnecessary_double_cast_or_process( let Some(inner) = helpers::expr_name(func) else { return; }; - if !checker.model.is_builtin(inner) || !checker.model.is_builtin(outer) { + if !checker.semantic_model().is_builtin(inner) || !checker.semantic_model().is_builtin(outer) { return; } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs index bf44696dd7..4cdd85512d 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_list.rs @@ -52,7 +52,7 @@ pub(crate) fn unnecessary_generator_list( let Some(argument) = helpers::exactly_one_argument_with_matching_function("list", func, args, keywords) else { return; }; - if !checker.model.is_builtin("list") { + if !checker.semantic_model().is_builtin("list") { return; } if let Expr::GeneratorExp(_) = argument { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs index 2633b1f786..7f7cf83be2 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_generator_set.rs @@ -53,7 +53,7 @@ pub(crate) fn unnecessary_generator_set( let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else { return; }; - if !checker.model.is_builtin("set") { + if !checker.semantic_model().is_builtin("set") { return; } if let Expr::GeneratorExp(_) = argument { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs index ad6d08fff6..597253875b 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_call.rs @@ -48,7 +48,7 @@ pub(crate) fn unnecessary_list_call( let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else { return; }; - if !checker.model.is_builtin("list") { + if !checker.semantic_model().is_builtin("list") { return; } if !argument.is_list_comp_expr() { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs index 6e4b62b1bf..9c6f87873b 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_dict.rs @@ -50,7 +50,7 @@ pub(crate) fn unnecessary_list_comprehension_dict( let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else { return; }; - if !checker.model.is_builtin("dict") { + if !checker.semantic_model().is_builtin("dict") { return; } let Expr::ListComp(ast::ExprListComp { elt, .. }) = argument else { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs index 06c2300936..b6dc24823c 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_list_comprehension_set.rs @@ -50,7 +50,7 @@ pub(crate) fn unnecessary_list_comprehension_set( let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else { return; }; - if !checker.model.is_builtin("set") { + if !checker.semantic_model().is_builtin("set") { return; } if argument.is_list_comp_expr() { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs index b539f72696..5ba588870b 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_dict.rs @@ -57,7 +57,7 @@ pub(crate) fn unnecessary_literal_dict( let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else { return; }; - if !checker.model.is_builtin("dict") { + if !checker.semantic_model().is_builtin("dict") { return; } let (kind, elts) = match argument { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs index 65090e6513..86c126dd5a 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_set.rs @@ -58,7 +58,7 @@ pub(crate) fn unnecessary_literal_set( let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else { return; }; - if !checker.model.is_builtin("set") { + if !checker.semantic_model().is_builtin("set") { return; } let kind = match argument { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs index c34819eee3..cc9ba2d5ce 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_dict_call.rs @@ -76,7 +76,7 @@ pub(crate) fn unnecessary_literal_within_dict_call( let Some(argument) = helpers::first_argument_with_matching_function("dict", func, args) else { return; }; - if !checker.model.is_builtin("dict") { + if !checker.semantic_model().is_builtin("dict") { return; } let argument_kind = match argument { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs index 95d9699dce..d1c240d55f 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_list_call.rs @@ -79,7 +79,7 @@ pub(crate) fn unnecessary_literal_within_list_call( let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else { return; }; - if !checker.model.is_builtin("list") { + if !checker.semantic_model().is_builtin("list") { return; } let argument_kind = match argument { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs index 12ad9a6174..cd61c1943f 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_literal_within_tuple_call.rs @@ -80,7 +80,7 @@ pub(crate) fn unnecessary_literal_within_tuple_call( let Some(argument) = helpers::first_argument_with_matching_function("tuple", func, args) else { return; }; - if !checker.model.is_builtin("tuple") { + if !checker.semantic_model().is_builtin("tuple") { return; } let argument_kind = match argument { diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs index 8b9a708f69..086a3137a4 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_map.rs @@ -88,7 +88,7 @@ pub(crate) fn unnecessary_map( }; match id { "map" => { - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; } @@ -119,7 +119,7 @@ pub(crate) fn unnecessary_map( } } "list" | "set" => { - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; } @@ -149,7 +149,7 @@ pub(crate) fn unnecessary_map( } } "dict" => { - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; } diff --git a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs index 819a9797b0..8659025978 100644 --- a/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs +++ b/crates/ruff/src/rules/flake8_comprehensions/rules/unnecessary_subscript_reversal.rs @@ -58,7 +58,7 @@ pub(crate) fn unnecessary_subscript_reversal( if !(id == "set" || id == "sorted" || id == "reversed") { return; } - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; } let Expr::Subscript(ast::ExprSubscript { slice, .. }) = first_arg else { diff --git a/crates/ruff/src/rules/flake8_datetimez/rules.rs b/crates/ruff/src/rules/flake8_datetimez/rules.rs index 04a177a181..2a7393ff65 100644 --- a/crates/ruff/src/rules/flake8_datetimez/rules.rs +++ b/crates/ruff/src/rules/flake8_datetimez/rules.rs @@ -125,7 +125,7 @@ pub(crate) fn call_datetime_without_tzinfo( location: TextRange, ) { if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "datetime"] @@ -158,7 +158,7 @@ pub(crate) fn call_datetime_without_tzinfo( /// Use `datetime.datetime.now(tz=)` instead. pub(crate) fn call_datetime_today(checker: &mut Checker, func: &Expr, location: TextRange) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "datetime", "today"] @@ -180,7 +180,7 @@ pub(crate) fn call_datetime_today(checker: &mut Checker, func: &Expr, location: /// current time in UTC is by calling `datetime.now(timezone.utc)`. pub(crate) fn call_datetime_utcnow(checker: &mut Checker, func: &Expr, location: TextRange) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "datetime", "utcnow"] @@ -207,7 +207,7 @@ pub(crate) fn call_datetime_utcfromtimestamp( location: TextRange, ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "datetime", "utcfromtimestamp"] @@ -228,7 +228,7 @@ pub(crate) fn call_datetime_now_without_tzinfo( location: TextRange, ) { if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "datetime", "now"] @@ -270,7 +270,7 @@ pub(crate) fn call_datetime_fromtimestamp( location: TextRange, ) { if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "datetime", "fromtimestamp"] @@ -311,7 +311,7 @@ pub(crate) fn call_datetime_strptime_without_zone( location: TextRange, ) { if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "datetime", "strptime"] @@ -332,7 +332,7 @@ pub(crate) fn call_datetime_strptime_without_zone( } }; - let (Some(grandparent), Some(parent)) = (checker.model.expr_grandparent(), checker.model.expr_parent()) else { + let (Some(grandparent), Some(parent)) = (checker.semantic_model().expr_grandparent(), checker.semantic_model().expr_parent()) else { checker.diagnostics.push(Diagnostic::new( CallDatetimeStrptimeWithoutZone, location, @@ -370,7 +370,7 @@ pub(crate) fn call_datetime_strptime_without_zone( /// Use `datetime.datetime.now(tz=).date()` instead. pub(crate) fn call_date_today(checker: &mut Checker, func: &Expr, location: TextRange) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "date", "today"] @@ -390,7 +390,7 @@ pub(crate) fn call_date_today(checker: &mut Checker, func: &Expr, location: Text /// Use `datetime.datetime.fromtimestamp(, tz=).date()` instead. pub(crate) fn call_date_fromtimestamp(checker: &mut Checker, func: &Expr, location: TextRange) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "date", "fromtimestamp"] diff --git a/crates/ruff/src/rules/flake8_debugger/rules.rs b/crates/ruff/src/rules/flake8_debugger/rules.rs index 6258033775..0dfdc9ce83 100644 --- a/crates/ruff/src/rules/flake8_debugger/rules.rs +++ b/crates/ruff/src/rules/flake8_debugger/rules.rs @@ -43,11 +43,15 @@ const DEBUGGERS: &[&[&str]] = &[ /// Checks for the presence of a debugger call. pub(crate) fn debugger_call(checker: &mut Checker, expr: &Expr, func: &Expr) { - if let Some(target) = checker.model.resolve_call_path(func).and_then(|call_path| { - DEBUGGERS - .iter() - .find(|target| call_path.as_slice() == **target) - }) { + if let Some(target) = checker + .semantic_model() + .resolve_call_path(func) + .and_then(|call_path| { + DEBUGGERS + .iter() + .find(|target| call_path.as_slice() == **target) + }) + { checker.diagnostics.push(Diagnostic::new( Debugger { using_type: DebuggerUsingType::Call(format_call_path(target)), diff --git a/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs b/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs index cd24d27af9..da019f071a 100644 --- a/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs +++ b/crates/ruff/src/rules/flake8_django/rules/all_with_model_form.rs @@ -52,7 +52,10 @@ pub(crate) fn all_with_model_form( bases: &[Expr], body: &[Stmt], ) -> Option { - if !bases.iter().any(|base| is_model_form(&checker.model, base)) { + if !bases + .iter() + .any(|base| is_model_form(checker.semantic_model(), base)) + { return None; } for element in body.iter() { diff --git a/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs b/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs index 6b107756aa..af229a6a32 100644 --- a/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs +++ b/crates/ruff/src/rules/flake8_django/rules/exclude_with_model_form.rs @@ -50,7 +50,10 @@ pub(crate) fn exclude_with_model_form( bases: &[Expr], body: &[Stmt], ) -> Option { - if !bases.iter().any(|base| is_model_form(&checker.model, base)) { + if !bases + .iter() + .any(|base| is_model_form(checker.semantic_model(), base)) + { return None; } for element in body.iter() { diff --git a/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs b/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs index cdbabecb59..469ff81eb6 100644 --- a/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs +++ b/crates/ruff/src/rules/flake8_django/rules/locals_in_render_function.rs @@ -51,7 +51,7 @@ pub(crate) fn locals_in_render_function( keywords: &[Keyword], ) { if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["django", "shortcuts", "render"] @@ -61,7 +61,7 @@ pub(crate) fn locals_in_render_function( } let locals = if args.len() >= 3 { - if !is_locals_call(&checker.model, &args[2]) { + if !is_locals_call(checker.semantic_model(), &args[2]) { return; } &args[2] @@ -69,7 +69,7 @@ pub(crate) fn locals_in_render_function( .iter() .find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "context")) { - if !is_locals_call(&checker.model, &keyword.value) { + if !is_locals_call(checker.semantic_model(), &keyword.value) { return; } &keyword.value diff --git a/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs b/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs index ec7f79ff47..5e07cbfa53 100644 --- a/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs +++ b/crates/ruff/src/rules/flake8_django/rules/model_without_dunder_str.rs @@ -56,7 +56,7 @@ pub(crate) fn model_without_dunder_str( body: &[Stmt], class_location: &Stmt, ) -> Option { - if !checker_applies(&checker.model, bases, body) { + if !checker_applies(checker.semantic_model(), bases, body) { return None; } if !has_dunder_method(body) { diff --git a/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs b/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs index 2a10a8059b..d8ccedb65b 100644 --- a/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs +++ b/crates/ruff/src/rules/flake8_django/rules/nullable_model_string_field.rs @@ -84,7 +84,7 @@ fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a st return None; }; - let Some(valid_field_name) = helpers::get_model_field_name(&checker.model, func) else { + let Some(valid_field_name) = helpers::get_model_field_name(checker.semantic_model(), func) else { return None; }; diff --git a/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs b/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs index fcddec99d0..857ebc96ee 100644 --- a/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs +++ b/crates/ruff/src/rules/flake8_django/rules/unordered_body_content_in_model.rs @@ -145,13 +145,13 @@ pub(crate) fn unordered_body_content_in_model( ) { if !bases .iter() - .any(|base| helpers::is_model(&checker.model, base)) + .any(|base| helpers::is_model(checker.semantic_model(), base)) { return; } let mut elements_type_found = Vec::new(); for element in body.iter() { - let Some(current_element_type) = get_element_type(&checker.model, element) else { + let Some(current_element_type) = get_element_type(checker.semantic_model(), element) else { continue; }; let Some(&element_type) = elements_type_found diff --git a/crates/ruff/src/rules/flake8_errmsg/rules.rs b/crates/ruff/src/rules/flake8_errmsg/rules.rs index d81365423e..fde1dc228f 100644 --- a/crates/ruff/src/rules/flake8_errmsg/rules.rs +++ b/crates/ruff/src/rules/flake8_errmsg/rules.rs @@ -233,7 +233,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr if string.len() > checker.settings.flake8_errmsg.max_string_length { let indentation = whitespace::indentation(checker.locator, stmt) .and_then(|indentation| { - if checker.model.find_binding("msg").is_none() { + if checker.semantic_model().find_binding("msg").is_none() { Some(indentation) } else { None @@ -261,7 +261,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr if checker.settings.rules.enabled(Rule::FStringInException) { let indentation = whitespace::indentation(checker.locator, stmt).and_then( |indentation| { - if checker.model.find_binding("msg").is_none() { + if checker.semantic_model().find_binding("msg").is_none() { Some(indentation) } else { None @@ -292,7 +292,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr if attr == "format" && value.is_constant_expr() { let indentation = whitespace::indentation(checker.locator, stmt) .and_then(|indentation| { - if checker.model.find_binding("msg").is_none() { + if checker.semantic_model().find_binding("msg").is_none() { Some(indentation) } else { None diff --git a/crates/ruff/src/rules/flake8_future_annotations/rules.rs b/crates/ruff/src/rules/flake8_future_annotations/rules.rs index 5d79780229..28aebb8074 100644 --- a/crates/ruff/src/rules/flake8_future_annotations/rules.rs +++ b/crates/ruff/src/rules/flake8_future_annotations/rules.rs @@ -67,11 +67,14 @@ impl Violation for MissingFutureAnnotationsImport { /// FA100 pub(crate) fn missing_future_annotations(checker: &mut Checker, expr: &Expr) { - if let Some(binding) = checker.model.resolve_call_path(expr) { + let name = checker + .semantic_model() + .resolve_call_path(expr) + .map(|binding| format_call_path(&binding)); + + if let Some(name) = name { checker.diagnostics.push(Diagnostic::new( - MissingFutureAnnotationsImport { - name: format_call_path(&binding), - }, + MissingFutureAnnotationsImport { name }, expr.range(), )); } diff --git a/crates/ruff/src/rules/flake8_logging_format/rules.rs b/crates/ruff/src/rules/flake8_logging_format/rules.rs index 05d7db16f4..f315d4d7f6 100644 --- a/crates/ruff/src/rules/flake8_logging_format/rules.rs +++ b/crates/ruff/src/rules/flake8_logging_format/rules.rs @@ -106,7 +106,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) { } Expr::Call(ast::ExprCall { func, keywords, .. }) => { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["", "dict"]) { @@ -151,7 +151,7 @@ pub(crate) fn logging_call( args: &[Expr], keywords: &[Keyword], ) { - if !logging::is_logger_candidate(func, &checker.model) { + if !logging::is_logger_candidate(func, checker.semantic_model()) { return; } @@ -198,7 +198,7 @@ pub(crate) fn logging_call( .rules .enabled(Rule::LoggingRedundantExcInfo) { - if !checker.model.in_exception_handler() { + if !checker.semantic_model().in_exception_handler() { return; } if let Some(exc_info) = find_keyword(keywords, "exc_info") { @@ -212,7 +212,7 @@ pub(crate) fn logging_call( }) ) || if let Expr::Call(ast::ExprCall { func, .. }) = &exc_info.value { checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["sys", "exc_info"] diff --git a/crates/ruff/src/rules/flake8_pie/rules.rs b/crates/ruff/src/rules/flake8_pie/rules.rs index 82d28ad37d..282bfa6d17 100644 --- a/crates/ruff/src/rules/flake8_pie/rules.rs +++ b/crates/ruff/src/rules/flake8_pie/rules.rs @@ -417,7 +417,7 @@ pub(crate) fn non_unique_enums<'a, 'b>( if !bases.iter().any(|expr| { checker - .model + .semantic_model() .resolve_call_path(expr) .map_or(false, |call_path| call_path.as_slice() == ["enum", "Enum"]) }) { @@ -432,7 +432,7 @@ pub(crate) fn non_unique_enums<'a, 'b>( if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["enum", "auto"]) { diff --git a/crates/ruff/src/rules/flake8_print/rules/print_call.rs b/crates/ruff/src/rules/flake8_print/rules/print_call.rs index ce11b9e589..2acbfb390a 100644 --- a/crates/ruff/src/rules/flake8_print/rules/print_call.rs +++ b/crates/ruff/src/rules/flake8_print/rules/print_call.rs @@ -78,7 +78,7 @@ impl Violation for PPrint { /// T201, T203 pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { let diagnostic = { - let call_path = checker.model.resolve_call_path(func); + let call_path = checker.semantic_model().resolve_call_path(func); if call_path .as_ref() .map_or(false, |call_path| *call_path.as_slice() == ["", "print"]) @@ -91,7 +91,7 @@ pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword { if !is_const_none(&keyword.value) { if checker - .model + .semantic_model() .resolve_call_path(&keyword.value) .map_or(true, |call_path| { call_path.as_slice() != ["sys", "stdout"] diff --git a/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs b/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs index 482da48776..8d923d1cfa 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/bad_version_info_comparison.rs @@ -69,7 +69,7 @@ pub(crate) fn bad_version_info_comparison( }; if !checker - .model + .semantic_model() .resolve_call_path(left) .map_or(false, |call_path| { call_path.as_slice() == ["sys", "version_info"] diff --git a/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs b/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs index e1b2699f47..e6c561191e 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/prefix_type_params.rs @@ -70,12 +70,12 @@ pub(crate) fn prefix_type_params(checker: &mut Checker, value: &Expr, targets: & }; if let Expr::Call(ast::ExprCall { func, .. }) = value { - let Some(kind) = checker.model.resolve_call_path(func).and_then(|call_path| { - if checker.model.match_typing_call_path(&call_path, "ParamSpec") { + let Some(kind) = checker.semantic_model().resolve_call_path(func).and_then(|call_path| { + if checker.semantic_model().match_typing_call_path(&call_path, "ParamSpec") { Some(VarKind::ParamSpec) - } else if checker.model.match_typing_call_path(&call_path, "TypeVar") { + } else if checker.semantic_model().match_typing_call_path(&call_path, "TypeVar") { Some(VarKind::TypeVar) - } else if checker.model.match_typing_call_path(&call_path, "TypeVarTuple") { + } else if checker.semantic_model().match_typing_call_path(&call_path, "TypeVarTuple") { Some(VarKind::TypeVarTuple) } else { None diff --git a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs index e9e5103a10..14fbcb861d 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/simple_defaults.rs @@ -330,7 +330,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum default, true, checker.locator, - &checker.model, + checker.semantic_model(), ) { let mut diagnostic = Diagnostic::new(TypedArgumentDefaultInStub, default.range()); @@ -362,7 +362,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum default, true, checker.locator, - &checker.model, + checker.semantic_model(), ) { let mut diagnostic = Diagnostic::new(TypedArgumentDefaultInStub, default.range()); @@ -397,7 +397,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments) default, true, checker.locator, - &checker.model, + checker.semantic_model(), ) { let mut diagnostic = Diagnostic::new(ArgumentDefaultInStub, default.range()); @@ -429,7 +429,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments) default, true, checker.locator, - &checker.model, + checker.semantic_model(), ) { let mut diagnostic = Diagnostic::new(ArgumentDefaultInStub, default.range()); @@ -459,16 +459,21 @@ pub(crate) fn assignment_default_in_stub(checker: &mut Checker, targets: &[Expr] if !target.is_name_expr() { return; } - if is_special_assignment(&checker.model, target) { + if is_special_assignment(checker.semantic_model(), target) { return; } - if is_type_var_like_call(&checker.model, value) { + if is_type_var_like_call(checker.semantic_model(), value) { return; } if is_valid_default_value_without_annotation(value) { return; } - if is_valid_default_value_with_annotation(value, true, checker.locator, &checker.model) { + if is_valid_default_value_with_annotation( + value, + true, + checker.locator, + checker.semantic_model(), + ) { return; } @@ -490,16 +495,24 @@ pub(crate) fn annotated_assignment_default_in_stub( value: &Expr, annotation: &Expr, ) { - if checker.model.match_typing_expr(annotation, "TypeAlias") { + if checker + .semantic_model() + .match_typing_expr(annotation, "TypeAlias") + { return; } - if is_special_assignment(&checker.model, target) { + if is_special_assignment(checker.semantic_model(), target) { return; } - if is_type_var_like_call(&checker.model, value) { + if is_type_var_like_call(checker.semantic_model(), value) { return; } - if is_valid_default_value_with_annotation(value, true, checker.locator, &checker.model) { + if is_valid_default_value_with_annotation( + value, + true, + checker.locator, + checker.semantic_model(), + ) { return; } @@ -527,21 +540,26 @@ pub(crate) fn unannotated_assignment_in_stub( let Expr::Name(ast::ExprName { id, .. }) = target else { return; }; - if is_special_assignment(&checker.model, target) { + if is_special_assignment(checker.semantic_model(), target) { return; } - if is_type_var_like_call(&checker.model, value) { + if is_type_var_like_call(checker.semantic_model(), value) { return; } if is_valid_default_value_without_annotation(value) { return; } - if !is_valid_default_value_with_annotation(value, true, checker.locator, &checker.model) { + if !is_valid_default_value_with_annotation( + value, + true, + checker.locator, + checker.semantic_model(), + ) { return; } - if let ScopeKind::Class(ClassDef { bases, .. }) = &checker.model.scope().kind { - if is_enum(&checker.model, bases) { + if let ScopeKind::Class(ClassDef { bases, .. }) = checker.semantic_model().scope().kind { + if is_enum(checker.semantic_model(), bases) { return; } } diff --git a/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs b/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs index 3515073867..a1ad340a61 100644 --- a/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs +++ b/crates/ruff/src/rules/flake8_pyi/rules/unrecognized_platform.rs @@ -103,7 +103,7 @@ pub(crate) fn unrecognized_platform( let diagnostic_unrecognized_platform_check = Diagnostic::new(UnrecognizedPlatformCheck, expr.range()); if !checker - .model + .semantic_model() .resolve_call_path(left) .map_or(false, |call_path| { call_path.as_slice() == ["sys", "platform"] diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs index 3b20cd73d8..fecf968fcf 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs @@ -185,9 +185,9 @@ pub(crate) fn unittest_assertion( if let Ok(unittest_assert) = UnittestAssert::try_from(attr.as_str()) { // We're converting an expression to a statement, so avoid applying the fix if // the assertion is part of a larger expression. - let fixable = checker.model.stmt().is_expr_stmt() - && checker.model.expr_parent().is_none() - && !checker.model.scope().kind.is_lambda() + let fixable = checker.semantic_model().stmt().is_expr_stmt() + && checker.semantic_model().expr_parent().is_none() + && !checker.semantic_model().scope().kind.is_lambda() && !has_comments_in(expr.range(), checker.locator); let mut diagnostic = Diagnostic::new( PytestUnittestAssertion { @@ -215,7 +215,7 @@ pub(crate) fn unittest_assertion( /// PT015 pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) { - if Truthiness::from_expr(test, |id| checker.model.is_builtin(id)).is_falsey() { + if Truthiness::from_expr(test, |id| checker.semantic_model().is_builtin(id)).is_falsey() { checker .diagnostics .push(Diagnostic::new(PytestAssertAlwaysFalse, stmt.range())); diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs index d4ce8c6518..6faa0915f4 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/fail.rs @@ -19,7 +19,7 @@ impl Violation for PytestFailWithoutMessage { } pub(crate) fn fail_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) { - if is_pytest_fail(&checker.model, func) { + if is_pytest_fail(checker.semantic_model(), func) { let call_args = SimpleCallArgs::new(args, keywords); let msg = call_args.argument("msg", 0); diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs index 22e5725d43..6ae34d1774 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/fixture.rs @@ -457,7 +457,7 @@ fn check_test_function_args(checker: &mut Checker, args: &Arguments) { /// PT020 fn check_fixture_decorator_name(checker: &mut Checker, decorator: &Expr) { - if is_pytest_yield_fixture(&checker.model, decorator) { + if is_pytest_yield_fixture(checker.semantic_model(), decorator) { checker.diagnostics.push(Diagnostic::new( PytestDeprecatedYieldFixture, decorator.range(), @@ -533,7 +533,7 @@ pub(crate) fn fixture( decorators: &[Expr], body: &[Stmt], ) { - let decorator = get_fixture_decorator(&checker.model, decorators); + let decorator = get_fixture_decorator(checker.semantic_model(), decorators); if let Some(decorator) = decorator { if checker .settings @@ -572,7 +572,7 @@ pub(crate) fn fixture( .settings .rules .enabled(Rule::PytestUselessYieldFixture)) - && !is_abstract(&checker.model, decorators) + && !is_abstract(checker.semantic_model(), decorators) { check_fixture_returns(checker, stmt, name, body); } diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs index dfda3bc625..3eb593409e 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/parametrize.rs @@ -419,7 +419,7 @@ fn handle_value_rows( pub(crate) fn parametrize(checker: &mut Checker, decorators: &[Expr]) { for decorator in decorators { - if is_pytest_parametrize(&checker.model, decorator) { + if is_pytest_parametrize(checker.semantic_model(), decorator) { if let Expr::Call(ast::ExprCall { args, .. }) = decorator { if checker .settings diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs index 11fe6c56dc..becd76c6fe 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/raises.rs @@ -64,7 +64,7 @@ const fn is_non_trivial_with_body(body: &[Stmt]) -> bool { } pub(crate) fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) { - if is_pytest_raises(func, &checker.model) { + if is_pytest_raises(func, checker.semantic_model()) { if checker .settings .rules @@ -104,7 +104,7 @@ pub(crate) fn complex_raises( let mut is_too_complex = false; let raises_called = items.iter().any(|item| match &item.context_expr { - Expr::Call(ast::ExprCall { func, .. }) => is_pytest_raises(func, &checker.model), + Expr::Call(ast::ExprCall { func, .. }) => is_pytest_raises(func, checker.semantic_model()), _ => false, }); @@ -145,7 +145,7 @@ pub(crate) fn complex_raises( /// PT011 fn exception_needs_match(checker: &mut Checker, exception: &Expr) { if let Some(call_path) = checker - .model + .semantic_model() .resolve_call_path(exception) .and_then(|call_path| { let is_broad_exception = checker diff --git a/crates/ruff/src/rules/flake8_return/rules.rs b/crates/ruff/src/rules/flake8_return/rules.rs index a2094e74db..45fd185dbe 100644 --- a/crates/ruff/src/rules/flake8_return/rules.rs +++ b/crates/ruff/src/rules/flake8_return/rules.rs @@ -484,7 +484,7 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) { if matches!( value.as_ref(), Expr::Call(ast::ExprCall { func, .. }) - if is_noreturn_func(&checker.model, func) + if is_noreturn_func(checker.semantic_model(), func) ) => {} _ => { let mut diagnostic = Diagnostic::new(ImplicitReturn, stmt.range()); diff --git a/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs b/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs index 10117e1393..76dde4f57f 100644 --- a/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs +++ b/crates/ruff/src/rules/flake8_self/rules/private_member_access.rs @@ -94,7 +94,7 @@ pub(crate) fn private_member_access(checker: &mut Checker, expr: &Expr) { // Ignore accesses on class members from _within_ the class. if checker - .model + .semantic_model() .scopes .iter() .rev() @@ -104,14 +104,14 @@ pub(crate) fn private_member_access(checker: &mut Checker, expr: &Expr) { }) .map_or(false, |class_def| { if call_path.as_slice() == [class_def.name] { - checker.model.find_binding(class_def.name).map_or( - false, - |binding| { + checker + .semantic_model() + .find_binding(class_def.name) + .map_or(false, |binding| { // TODO(charlie): Could the name ever be bound to a // _different_ class here? binding.kind.is_class_definition() - }, - ) + }) } else { false } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs index 44b8f4480e..2b032172c7 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_bool_op.rs @@ -271,7 +271,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { if func_name != "isinstance" { continue; } - if !checker.model.is_builtin("isinstance") { + if !checker.semantic_model().is_builtin("isinstance") { continue; } @@ -293,7 +293,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) { } else { unreachable!("Indices should only contain `isinstance` calls") }; - let fixable = !contains_effect(target, |id| checker.model.is_builtin(id)); + let fixable = !contains_effect(target, |id| checker.semantic_model().is_builtin(id)); let mut diagnostic = Diagnostic::new( DuplicateIsinstanceCall { name: if let Expr::Name(ast::ExprName { id, .. }) = target { @@ -425,7 +425,7 @@ pub(crate) fn compare_with_tuple(checker: &mut Checker, expr: &Expr) { // Avoid rewriting (e.g.) `a == "foo" or a == f()`. if comparators .iter() - .any(|expr| contains_effect(expr, |id| checker.model.is_builtin(id))) + .any(|expr| contains_effect(expr, |id| checker.semantic_model().is_builtin(id))) { continue; } @@ -516,7 +516,7 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) { return; } - if contains_effect(expr, |id| checker.model.is_builtin(id)) { + if contains_effect(expr, |id| checker.semantic_model().is_builtin(id)) { return; } @@ -571,7 +571,7 @@ pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) { return; } - if contains_effect(expr, |id| checker.model.is_builtin(id)) { + if contains_effect(expr, |id| checker.semantic_model().is_builtin(id)) { return; } @@ -640,14 +640,15 @@ fn is_short_circuit( for (index, (value, next_value)) in values.iter().tuple_windows().enumerate() { // Keep track of the location of the furthest-right, truthy or falsey expression. - let value_truthiness = Truthiness::from_expr(value, |id| checker.model.is_builtin(id)); + let value_truthiness = + Truthiness::from_expr(value, |id| checker.semantic_model().is_builtin(id)); let next_value_truthiness = - Truthiness::from_expr(next_value, |id| checker.model.is_builtin(id)); + Truthiness::from_expr(next_value, |id| checker.semantic_model().is_builtin(id)); // Keep track of the location of the furthest-right, non-effectful expression. if value_truthiness.is_unknown() - && (!checker.model.in_boolean_test() - || contains_effect(value, |id| checker.model.is_builtin(id))) + && (!checker.semantic_model().in_boolean_test() + || contains_effect(value, |id| checker.semantic_model().is_builtin(id))) { location = next_value.start(); continue; @@ -667,7 +668,7 @@ fn is_short_circuit( value, TextRange::new(location, expr.end()), short_circuit_truthiness, - checker.model.in_boolean_test(), + checker.semantic_model().in_boolean_test(), checker, )); break; @@ -685,7 +686,7 @@ fn is_short_circuit( next_value, TextRange::new(location, expr.end()), short_circuit_truthiness, - checker.model.in_boolean_test(), + checker.semantic_model().in_boolean_test(), checker, )); break; diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs index 56e347ecbe..83006f6f8d 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_expr.rs @@ -87,7 +87,7 @@ pub(crate) fn use_capital_environment_variables(checker: &mut Checker, expr: &Ex return; }; if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["os", "environ", "get"] diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs index 43cdf718b4..63f4ae67fa 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_if.rs @@ -351,7 +351,7 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) { let fixable = matches!(if_return, Bool::True) && matches!(else_return, Bool::False) && !has_comments(stmt, checker.locator) - && (test.is_compare_expr() || checker.model.is_builtin("bool")); + && (test.is_compare_expr() || checker.semantic_model().is_builtin("bool")); let mut diagnostic = Diagnostic::new(NeedlessBool { condition }, stmt.range()); if fixable && checker.patch(diagnostic.kind.rule()) { @@ -447,13 +447,13 @@ pub(crate) fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: O } // Avoid suggesting ternary for `if sys.version_info >= ...`-style checks. - if contains_call_path(&checker.model, test, &["sys", "version_info"]) { + if contains_call_path(checker.semantic_model(), test, &["sys", "version_info"]) { return; } // Avoid suggesting ternary for `if sys.platform.startswith("...")`-style // checks. - if contains_call_path(&checker.model, test, &["sys", "platform"]) { + if contains_call_path(checker.semantic_model(), test, &["sys", "platform"]) { return; } @@ -648,7 +648,7 @@ pub(crate) fn manual_dict_lookup( return; }; if value.as_ref().map_or(false, |value| { - contains_effect(value, |id| checker.model.is_builtin(id)) + contains_effect(value, |id| checker.semantic_model().is_builtin(id)) }) { return; } @@ -721,7 +721,7 @@ pub(crate) fn manual_dict_lookup( return; }; if value.as_ref().map_or(false, |value| { - contains_effect(value, |id| checker.model.is_builtin(id)) + contains_effect(value, |id| checker.semantic_model().is_builtin(id)) }) { return; }; @@ -804,7 +804,7 @@ pub(crate) fn use_dict_get_with_default( } // Check that the default value is not "complex". - if contains_effect(default_value, |id| checker.model.is_builtin(id)) { + if contains_effect(default_value, |id| checker.semantic_model().is_builtin(id)) { return; } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs index 7e62cb8477..cbbac3b6a9 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_ifexp.rs @@ -107,7 +107,7 @@ pub(crate) fn explicit_true_false_in_ifexpr( checker.generator().expr(&test.clone()), expr.range(), ))); - } else if checker.model.is_builtin("bool") { + } else if checker.semantic_model().is_builtin("bool") { let node = ast::ExprName { id: "bool".into(), ctx: ExprContext::Load, diff --git a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs index ba647bfb1f..95073b5574 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/ast_unary_op.rs @@ -93,12 +93,12 @@ pub(crate) fn negation_with_equal_op( if !matches!(&ops[..], [Cmpop::Eq]) { return; } - if is_exception_check(checker.model.stmt()) { + if is_exception_check(checker.semantic_model().stmt()) { return; } // Avoid flagging issues in dunder implementations. - if let ScopeKind::Function(def) = &checker.model.scope().kind { + if let ScopeKind::Function(def) = &checker.semantic_model().scope().kind { if DUNDER_METHODS.contains(&def.name) { return; } @@ -143,12 +143,12 @@ pub(crate) fn negation_with_not_equal_op( if !matches!(&ops[..], [Cmpop::NotEq]) { return; } - if is_exception_check(checker.model.stmt()) { + if is_exception_check(checker.semantic_model().stmt()) { return; } // Avoid flagging issues in dunder implementations. - if let ScopeKind::Function(def) = &checker.model.scope().kind { + if let ScopeKind::Function(def) = &checker.semantic_model().scope().kind { if DUNDER_METHODS.contains(&def.name) { return; } @@ -196,13 +196,13 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: Unaryop, o expr.range(), ); if checker.patch(diagnostic.kind.rule()) { - if checker.model.in_boolean_test() { + if checker.semantic_model().in_boolean_test() { #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( checker.generator().expr(operand), expr.range(), ))); - } else if checker.model.is_builtin("bool") { + } else if checker.semantic_model().is_builtin("bool") { let node = ast::ExprName { id: "bool".into(), ctx: ExprContext::Load, diff --git a/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs b/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs index 99f632fd41..8d10ddb424 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/open_file_with_context_handler.rs @@ -108,23 +108,23 @@ fn match_exit_stack(model: &SemanticModel) -> bool { /// SIM115 pub(crate) fn open_file_with_context_handler(checker: &mut Checker, func: &Expr) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["", "open"]) { - if checker.model.is_builtin("open") { + if checker.semantic_model().is_builtin("open") { // Ex) `with open("foo.txt") as f: ...` - if matches!(checker.model.stmt(), Stmt::With(_)) { + if matches!(checker.semantic_model().stmt(), Stmt::With(_)) { return; } // Ex) `with contextlib.ExitStack() as exit_stack: ...` - if match_exit_stack(&checker.model) { + if match_exit_stack(checker.semantic_model()) { return; } // Ex) `with contextlib.AsyncExitStack() as exit_stack: ...` - if match_async_exit_stack(&checker.model) { + if match_async_exit_stack(checker.semantic_model()) { return; } diff --git a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs index cc6ec382e8..bc32ddabc1 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs @@ -237,7 +237,9 @@ pub(crate) fn convert_for_loop_to_any_all( }, TextRange::new(stmt.start(), loop_info.terminal), ); - if checker.patch(diagnostic.kind.rule()) && checker.model.is_builtin("any") { + if checker.patch(diagnostic.kind.rule()) + && checker.semantic_model().is_builtin("any") + { #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::replacement( contents, @@ -327,7 +329,9 @@ pub(crate) fn convert_for_loop_to_any_all( }, TextRange::new(stmt.start(), loop_info.terminal), ); - if checker.patch(diagnostic.kind.rule()) && checker.model.is_builtin("all") { + if checker.patch(diagnostic.kind.rule()) + && checker.semantic_model().is_builtin("all") + { #[allow(deprecated)] diagnostic.set_fix(Fix::unspecified(Edit::replacement( contents, diff --git a/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs b/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs index b4d5350bd8..f968f7990b 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/suppressible_exception.rs @@ -93,7 +93,7 @@ pub(crate) fn suppressible_exception( "contextlib", "suppress", stmt.start(), - &checker.model, + checker.semantic_model(), &checker.importer, checker.locator, )?; diff --git a/crates/ruff/src/rules/flake8_tidy_imports/banned_api.rs b/crates/ruff/src/rules/flake8_tidy_imports/banned_api.rs index 78f7837fed..04343bd8ab 100644 --- a/crates/ruff/src/rules/flake8_tidy_imports/banned_api.rs +++ b/crates/ruff/src/rules/flake8_tidy_imports/banned_api.rs @@ -96,11 +96,16 @@ where /// TID251 pub(crate) fn banned_attribute_access(checker: &mut Checker, expr: &Expr) { let banned_api = &checker.settings.flake8_tidy_imports.banned_api; - if let Some((banned_path, ban)) = checker.model.resolve_call_path(expr).and_then(|call_path| { - banned_api - .iter() - .find(|(banned_path, ..)| call_path == from_qualified_name(banned_path)) - }) { + if let Some((banned_path, ban)) = + checker + .semantic_model() + .resolve_call_path(expr) + .and_then(|call_path| { + banned_api + .iter() + .find(|(banned_path, ..)| call_path == from_qualified_name(banned_path)) + }) + { checker.diagnostics.push(Diagnostic::new( BannedApi { name: banned_path.to_string(), diff --git a/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs b/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs index 42d16eecad..cc8b29bb7d 100644 --- a/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs +++ b/crates/ruff/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs @@ -60,7 +60,7 @@ pub(crate) fn empty_type_checking_block<'a, 'b>( // Delete the entire type-checking block. if checker.patch(diagnostic.kind.rule()) { - let parent = checker.model.stmts.parent(stmt); + let parent = checker.semantic_model().stmts.parent(stmt); let deleted: Vec<&Stmt> = checker.deletions.iter().map(Into::into).collect(); match delete_stmt( stmt, diff --git a/crates/ruff/src/rules/flake8_unused_arguments/rules.rs b/crates/ruff/src/rules/flake8_unused_arguments/rules.rs index d46421c8ad..344cc8f342 100644 --- a/crates/ruff/src/rules/flake8_unused_arguments/rules.rs +++ b/crates/ruff/src/rules/flake8_unused_arguments/rules.rs @@ -289,7 +289,7 @@ pub(crate) fn unused_arguments( .. }) => { match function_type::classify( - &checker.model, + checker.semantic_model(), parent, name, decorator_list, @@ -301,7 +301,7 @@ pub(crate) fn unused_arguments( .settings .rules .enabled(Argumentable::Function.rule_code()) - && !visibility::is_overload(&checker.model, decorator_list) + && !visibility::is_overload(checker.semantic_model(), decorator_list) { function( Argumentable::Function, @@ -328,9 +328,9 @@ pub(crate) fn unused_arguments( || visibility::is_init(name) || visibility::is_new(name) || visibility::is_call(name)) - && !visibility::is_abstract(&checker.model, decorator_list) - && !visibility::is_override(&checker.model, decorator_list) - && !visibility::is_overload(&checker.model, decorator_list) + && !visibility::is_abstract(checker.semantic_model(), decorator_list) + && !visibility::is_override(checker.semantic_model(), decorator_list) + && !visibility::is_overload(checker.semantic_model(), decorator_list) { method( Argumentable::Method, @@ -357,9 +357,9 @@ pub(crate) fn unused_arguments( || visibility::is_init(name) || visibility::is_new(name) || visibility::is_call(name)) - && !visibility::is_abstract(&checker.model, decorator_list) - && !visibility::is_override(&checker.model, decorator_list) - && !visibility::is_overload(&checker.model, decorator_list) + && !visibility::is_abstract(checker.semantic_model(), decorator_list) + && !visibility::is_override(checker.semantic_model(), decorator_list) + && !visibility::is_overload(checker.semantic_model(), decorator_list) { method( Argumentable::ClassMethod, @@ -386,9 +386,9 @@ pub(crate) fn unused_arguments( || visibility::is_init(name) || visibility::is_new(name) || visibility::is_call(name)) - && !visibility::is_abstract(&checker.model, decorator_list) - && !visibility::is_override(&checker.model, decorator_list) - && !visibility::is_overload(&checker.model, decorator_list) + && !visibility::is_abstract(checker.semantic_model(), decorator_list) + && !visibility::is_override(checker.semantic_model(), decorator_list) + && !visibility::is_overload(checker.semantic_model(), decorator_list) { function( Argumentable::StaticMethod, diff --git a/crates/ruff/src/rules/flake8_use_pathlib/helpers.rs b/crates/ruff/src/rules/flake8_use_pathlib/helpers.rs index 08dcc457ee..8bcc1073b1 100644 --- a/crates/ruff/src/rules/flake8_use_pathlib/helpers.rs +++ b/crates/ruff/src/rules/flake8_use_pathlib/helpers.rs @@ -15,7 +15,7 @@ use crate::settings::types::PythonVersion; pub(crate) fn replaceable_by_pathlib(checker: &mut Checker, expr: &Expr) { if let Some(diagnostic_kind) = checker - .model + .semantic_model() .resolve_call_path(expr) .and_then(|call_path| match call_path.as_slice() { ["os", "path", "abspath"] => Some(OsPathAbspath.into()), diff --git a/crates/ruff/src/rules/numpy/rules/deprecated_type_alias.rs b/crates/ruff/src/rules/numpy/rules/deprecated_type_alias.rs index 1ecd42c7e6..834400e5eb 100644 --- a/crates/ruff/src/rules/numpy/rules/deprecated_type_alias.rs +++ b/crates/ruff/src/rules/numpy/rules/deprecated_type_alias.rs @@ -48,21 +48,26 @@ impl AlwaysAutofixableViolation for NumpyDeprecatedTypeAlias { /// NPY001 pub(crate) fn deprecated_type_alias(checker: &mut Checker, expr: &Expr) { - if let Some(type_name) = checker.model.resolve_call_path(expr).and_then(|call_path| { - if call_path.as_slice() == ["numpy", "bool"] - || call_path.as_slice() == ["numpy", "int"] - || call_path.as_slice() == ["numpy", "float"] - || call_path.as_slice() == ["numpy", "complex"] - || call_path.as_slice() == ["numpy", "object"] - || call_path.as_slice() == ["numpy", "str"] - || call_path.as_slice() == ["numpy", "long"] - || call_path.as_slice() == ["numpy", "unicode"] - { - Some(call_path[1]) - } else { - None - } - }) { + if let Some(type_name) = + checker + .semantic_model() + .resolve_call_path(expr) + .and_then(|call_path| { + if call_path.as_slice() == ["numpy", "bool"] + || call_path.as_slice() == ["numpy", "int"] + || call_path.as_slice() == ["numpy", "float"] + || call_path.as_slice() == ["numpy", "complex"] + || call_path.as_slice() == ["numpy", "object"] + || call_path.as_slice() == ["numpy", "str"] + || call_path.as_slice() == ["numpy", "long"] + || call_path.as_slice() == ["numpy", "unicode"] + { + Some(call_path[1]) + } else { + None + } + }) + { let mut diagnostic = Diagnostic::new( NumpyDeprecatedTypeAlias { type_name: type_name.to_string(), diff --git a/crates/ruff/src/rules/numpy/rules/numpy_legacy_random.rs b/crates/ruff/src/rules/numpy/rules/numpy_legacy_random.rs index c78ad8b201..0e52c39176 100644 --- a/crates/ruff/src/rules/numpy/rules/numpy_legacy_random.rs +++ b/crates/ruff/src/rules/numpy/rules/numpy_legacy_random.rs @@ -58,9 +58,13 @@ impl Violation for NumpyLegacyRandom { /// NPY002 pub(crate) fn numpy_legacy_random(checker: &mut Checker, expr: &Expr) { - if let Some(method_name) = checker.model.resolve_call_path(expr).and_then(|call_path| { - // seeding state - if call_path.as_slice() == ["numpy", "random", "seed"] + if let Some(method_name) = + checker + .semantic_model() + .resolve_call_path(expr) + .and_then(|call_path| { + // seeding state + if call_path.as_slice() == ["numpy", "random", "seed"] || call_path.as_slice() == ["numpy", "random", "get_state"] || call_path.as_slice() == ["numpy", "random", "set_state"] // simple random data @@ -111,12 +115,13 @@ pub(crate) fn numpy_legacy_random(checker: &mut Checker, expr: &Expr) { || call_path.as_slice() == ["numpy", "random", "wald"] || call_path.as_slice() == ["numpy", "random", "weibull"] || call_path.as_slice() == ["numpy", "random", "zipf"] - { - Some(call_path[2]) - } else { - None - } - }) { + { + Some(call_path[2]) + } else { + None + } + }) + { checker.diagnostics.push(Diagnostic::new( NumpyLegacyRandom { method_name: method_name.to_string(), diff --git a/crates/ruff/src/rules/pandas_vet/rules/attr.rs b/crates/ruff/src/rules/pandas_vet/rules/attr.rs index f47a15926e..ccdb5616b1 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/attr.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/attr.rs @@ -26,7 +26,7 @@ pub(crate) fn attr(checker: &mut Checker, attr: &str, value: &Expr, attr_expr: & }; // Avoid flagging on function calls (e.g., `df.values()`). - if let Some(parent) = checker.model.expr_parent() { + if let Some(parent) = checker.semantic_model().expr_parent() { if matches!(parent, Expr::Call(_)) { return; } @@ -35,7 +35,7 @@ pub(crate) fn attr(checker: &mut Checker, attr: &str, value: &Expr, attr_expr: & // Avoid flagging on non-DataFrames (e.g., `{"a": 1}.values`), and on irrelevant bindings // (like imports). if !matches!( - test_expression(value, &checker.model), + test_expression(value, checker.semantic_model()), Resolution::RelevantLocal ) { return; diff --git a/crates/ruff/src/rules/pandas_vet/rules/call.rs b/crates/ruff/src/rules/pandas_vet/rules/call.rs index 28ef3bcec0..ecea41b6f8 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/call.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/call.rs @@ -80,7 +80,7 @@ pub(crate) fn call(checker: &mut Checker, func: &Expr) { // Ignore irrelevant bindings (like imports). if !matches!( - test_expression(value, &checker.model), + test_expression(value, checker.semantic_model()), Resolution::RelevantLocal | Resolution::PandasModule ) { return; diff --git a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs index e0ab23bef8..bbb0c3e9a0 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs @@ -60,19 +60,22 @@ pub(crate) fn inplace_argument( let mut is_checkable = false; let mut is_pandas = false; - if let Some(call_path) = checker.model.resolve_call_path(func) { + if let Some(call_path) = checker.semantic_model().resolve_call_path(func) { is_checkable = true; let module = call_path[0]; - is_pandas = checker.model.find_binding(module).map_or(false, |binding| { - matches!( - binding.kind, - BindingKind::Importation(Importation { - full_name: "pandas", - .. - }) - ) - }); + is_pandas = checker + .semantic_model() + .find_binding(module) + .map_or(false, |binding| { + matches!( + binding.kind, + BindingKind::Importation(Importation { + full_name: "pandas", + .. + }) + ) + }); } for keyword in keywords.iter().rev() { @@ -99,9 +102,9 @@ pub(crate) fn inplace_argument( // but we don't currently restore expression stacks when parsing deferred nodes, // and so the parent is lost. let fixable = !seen_star - && checker.model.stmt().is_expr_stmt() - && checker.model.expr_parent().is_none() - && !checker.model.scope().kind.is_lambda(); + && checker.semantic_model().stmt().is_expr_stmt() + && checker.semantic_model().expr_parent().is_none() + && !checker.semantic_model().scope().kind.is_lambda(); let mut diagnostic = Diagnostic::new(PandasUseOfInplaceArgument, keyword.range()); if fixable && checker.patch(diagnostic.kind.rule()) { if let Some(fix) = convert_inplace_argument_to_assignment( diff --git a/crates/ruff/src/rules/pandas_vet/rules/subscript.rs b/crates/ruff/src/rules/pandas_vet/rules/subscript.rs index 394dfde43a..96430e0151 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/subscript.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/subscript.rs @@ -54,7 +54,7 @@ pub(crate) fn subscript(checker: &mut Checker, value: &Expr, expr: &Expr) { // Avoid flagging on non-DataFrames (e.g., `{"a": 1}.at[0]`), and on irrelevant bindings // (like imports). if !matches!( - test_expression(value, &checker.model), + test_expression(value, checker.semantic_model()), Resolution::RelevantLocal ) { return; diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs index 9d5709ba95..df5e7c64bc 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_class_method.rs @@ -64,7 +64,7 @@ pub(crate) fn invalid_first_argument_name_for_class_method( ) -> Option { if !matches!( function_type::classify( - &checker.model, + checker.semantic_model(), scope, name, decorator_list, diff --git a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs index b206a396f1..c0e0cb3895 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/invalid_first_argument_name_for_method.rs @@ -61,7 +61,7 @@ pub(crate) fn invalid_first_argument_name_for_method( ) -> Option { if !matches!( function_type::classify( - &checker.model, + checker.semantic_model(), scope, name, decorator_list, diff --git a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs index bd471058f5..2cb0793789 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_class_scope.rs @@ -67,8 +67,8 @@ pub(crate) fn mixed_case_variable_in_class_scope( return; } if helpers::is_mixed_case(name) - && !helpers::is_named_tuple_assignment(&checker.model, stmt) - && !helpers::is_typed_dict_class(&checker.model, bases) + && !helpers::is_named_tuple_assignment(checker.semantic_model(), stmt) + && !helpers::is_typed_dict_class(checker.semantic_model(), bases) { checker.diagnostics.push(Diagnostic::new( MixedCaseVariableInClassScope { diff --git a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs index 0b14ea5d93..b0312c50d6 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/mixed_case_variable_in_global_scope.rs @@ -75,7 +75,9 @@ pub(crate) fn mixed_case_variable_in_global_scope( { return; } - if helpers::is_mixed_case(name) && !helpers::is_named_tuple_assignment(&checker.model, stmt) { + if helpers::is_mixed_case(name) + && !helpers::is_named_tuple_assignment(checker.semantic_model(), stmt) + { checker.diagnostics.push(Diagnostic::new( MixedCaseVariableInGlobalScope { name: name.to_string(), diff --git a/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs b/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs index ea774aa24d..ed7648fb34 100644 --- a/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs +++ b/crates/ruff/src/rules/pep8_naming/rules/non_lowercase_variable_in_function.rs @@ -66,9 +66,9 @@ pub(crate) fn non_lowercase_variable_in_function( } if name.to_lowercase() != name - && !helpers::is_named_tuple_assignment(&checker.model, stmt) - && !helpers::is_typed_dict_assignment(&checker.model, stmt) - && !helpers::is_type_var_assignment(&checker.model, stmt) + && !helpers::is_named_tuple_assignment(checker.semantic_model(), stmt) + && !helpers::is_typed_dict_assignment(checker.semantic_model(), stmt) + && !helpers::is_type_var_assignment(checker.semantic_model(), stmt) { checker.diagnostics.push(Diagnostic::new( NonLowercaseVariableInFunction { diff --git a/crates/ruff/src/rules/pycodestyle/rules/imports.rs b/crates/ruff/src/rules/pycodestyle/rules/imports.rs index 15ce7e5658..b5b724329e 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/imports.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/imports.rs @@ -88,7 +88,8 @@ pub(crate) fn module_import_not_at_top_of_file( stmt: &Stmt, locator: &Locator, ) { - if checker.model.seen_import_boundary() && locator.is_at_start_of_line(stmt.start()) { + if checker.semantic_model().seen_import_boundary() && locator.is_at_start_of_line(stmt.start()) + { checker .diagnostics .push(Diagnostic::new(ModuleImportNotAtTopOfFile, stmt.range())); diff --git a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs index af96e9c7c3..32b28683a3 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/lambda_assignment.rs @@ -72,7 +72,7 @@ pub(crate) fn lambda_assignment( // package like dataclasses, which wouldn't consider the // rewritten function definition to be equivalent. // See https://github.com/charliermarsh/ruff/issues/3046 - let fixable = !matches!(checker.model.scope().kind, ScopeKind::Class(_)); + let fixable = !matches!(checker.semantic_model().scope().kind, ScopeKind::Class(_)); let mut diagnostic = Diagnostic::new( LambdaAssignment { @@ -90,7 +90,7 @@ pub(crate) fn lambda_assignment( let indentation = &leading_space(first_line); let mut indented = String::new(); for (idx, line) in function( - &checker.model, + checker.semantic_model(), id, args, body, diff --git a/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs b/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs index b49b65b5d9..7cec3e0cb4 100644 --- a/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs +++ b/crates/ruff/src/rules/pycodestyle/rules/type_comparison.rs @@ -52,7 +52,7 @@ pub(crate) fn type_comparison( Expr::Call(ast::ExprCall { func, args, .. }) => { if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { // Ex) `type(False)` - if id == "type" && checker.model.is_builtin("type") { + if id == "type" && checker.semantic_model().is_builtin("type") { if let Some(arg) = args.first() { // Allow comparison for types which are not obvious. if !matches!( @@ -76,12 +76,12 @@ pub(crate) fn type_comparison( if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { // Ex) `types.NoneType` if id == "types" - && checker - .model - .resolve_call_path(value) - .map_or(false, |call_path| { + && checker.semantic_model().resolve_call_path(value).map_or( + false, + |call_path| { call_path.first().map_or(false, |module| *module == "types") - }) + }, + ) { checker .diagnostics diff --git a/crates/ruff/src/rules/pydocstyle/rules/if_needed.rs b/crates/ruff/src/rules/pydocstyle/rules/if_needed.rs index 43211c6fae..1ef2016d5a 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/if_needed.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/if_needed.rs @@ -27,7 +27,7 @@ pub(crate) fn if_needed(checker: &mut Checker, docstring: &Docstring) { }) = docstring.definition else { return; }; - if !is_overload(&checker.model, cast::decorator_list(stmt)) { + if !is_overload(checker.semantic_model(), cast::decorator_list(stmt)) { return; } checker.diagnostics.push(Diagnostic::new( diff --git a/crates/ruff/src/rules/pydocstyle/rules/non_imperative_mood.rs b/crates/ruff/src/rules/pydocstyle/rules/non_imperative_mood.rs index f3be352592..a3df27817f 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/non_imperative_mood.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/non_imperative_mood.rs @@ -41,7 +41,7 @@ pub(crate) fn non_imperative_mood( if is_test(cast::name(stmt)) || is_property( - &checker.model, + checker.semantic_model(), cast::decorator_list(stmt), &property_decorators, ) diff --git a/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs b/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs index 2382a53a2e..57eb53200a 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/not_missing.rs @@ -174,7 +174,7 @@ pub(crate) fn not_missing( stmt, .. }) => { - if is_overload(&checker.model, cast::decorator_list(stmt)) { + if is_overload(checker.semantic_model(), cast::decorator_list(stmt)) { true } else { if checker @@ -195,8 +195,8 @@ pub(crate) fn not_missing( stmt, .. }) => { - if is_overload(&checker.model, cast::decorator_list(stmt)) - || is_override(&checker.model, cast::decorator_list(stmt)) + if is_overload(checker.semantic_model(), cast::decorator_list(stmt)) + || is_override(checker.semantic_model(), cast::decorator_list(stmt)) { true } else if is_init(cast::name(stmt)) { diff --git a/crates/ruff/src/rules/pydocstyle/rules/sections.rs b/crates/ruff/src/rules/pydocstyle/rules/sections.rs index 1a2a93661d..3fce7319c8 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/sections.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/sections.rs @@ -760,7 +760,7 @@ fn missing_args(checker: &mut Checker, docstring: &Docstring, docstrings_args: & // If this is a non-static method, skip `cls` or `self`. usize::from( docstring.definition.is_method() - && !is_staticmethod(&checker.model, cast::decorator_list(stmt)), + && !is_staticmethod(checker.semantic_model(), cast::decorator_list(stmt)), ), ) { diff --git a/crates/ruff/src/rules/pyflakes/rules/invalid_print_syntax.rs b/crates/ruff/src/rules/pyflakes/rules/invalid_print_syntax.rs index 4cbe42829b..96c9996971 100644 --- a/crates/ruff/src/rules/pyflakes/rules/invalid_print_syntax.rs +++ b/crates/ruff/src/rules/pyflakes/rules/invalid_print_syntax.rs @@ -23,7 +23,7 @@ pub(crate) fn invalid_print_syntax(checker: &mut Checker, left: &Expr) { if id != "print" { return; } - if !checker.model.is_builtin("print") { + if !checker.semantic_model().is_builtin("print") { return; }; checker diff --git a/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs b/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs index 83021cfc5c..d88d08df0f 100644 --- a/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs +++ b/crates/ruff/src/rules/pyflakes/rules/return_outside_function.rs @@ -18,7 +18,7 @@ impl Violation for ReturnOutsideFunction { pub(crate) fn return_outside_function(checker: &mut Checker, stmt: &Stmt) { if matches!( - checker.model.scope().kind, + checker.semantic_model().scope().kind, ScopeKind::Class(_) | ScopeKind::Module ) { checker diff --git a/crates/ruff/src/rules/pyflakes/rules/undefined_local.rs b/crates/ruff/src/rules/pyflakes/rules/undefined_local.rs index 1984c11257..61aa84640f 100644 --- a/crates/ruff/src/rules/pyflakes/rules/undefined_local.rs +++ b/crates/ruff/src/rules/pyflakes/rules/undefined_local.rs @@ -21,7 +21,7 @@ impl Violation for UndefinedLocal { /// F823 pub(crate) fn undefined_local(checker: &mut Checker, name: &str) { // If the name hasn't already been defined in the current scope... - let current = checker.model.scope(); + let current = checker.semantic_model().scope(); if !current.kind.is_function() || current.defines(name) { return; } @@ -31,26 +31,39 @@ pub(crate) fn undefined_local(checker: &mut Checker, name: &str) { }; // For every function and module scope above us... - for scope in checker.model.scopes.ancestors(parent) { - if !(scope.kind.is_function() || scope.kind.is_module()) { - continue; - } + let local_access = checker + .semantic_model() + .scopes + .ancestors(parent) + .find_map(|scope| { + if !(scope.kind.is_function() || scope.kind.is_module()) { + return None; + } - // If the name was defined in that scope... - if let Some(binding) = scope.get(name).map(|index| &checker.model.bindings[*index]) { - // And has already been accessed in the current scope... - if let Some((scope_id, location)) = binding.runtime_usage { - if scope_id == checker.model.scope_id { - // Then it's probably an error. - checker.diagnostics.push(Diagnostic::new( - UndefinedLocal { - name: name.to_string(), - }, - location, - )); - return; + // If the name was defined in that scope... + if let Some(binding) = scope + .get(name) + .map(|index| &checker.semantic_model().bindings[*index]) + { + // And has already been accessed in the current scope... + if let Some((scope_id, location)) = binding.runtime_usage { + if scope_id == checker.semantic_model().scope_id { + // Then it's probably an error. + + return Some(location); + } } } - } + + None + }); + + if let Some(location) = local_access { + checker.diagnostics.push(Diagnostic::new( + UndefinedLocal { + name: name.to_string(), + }, + location, + )); } } diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_annotation.rs b/crates/ruff/src/rules/pyflakes/rules/unused_annotation.rs index 1be79d398b..64d446bff8 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_annotation.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_annotation.rs @@ -19,21 +19,31 @@ impl Violation for UnusedAnnotation { /// F842 pub(crate) fn unused_annotation(checker: &mut Checker, scope: ScopeId) { - let scope = &checker.model.scopes[scope]; - for (name, binding) in scope + let scope = &checker.semantic_model().scopes[scope]; + + let bindings: Vec<_> = scope .bindings() - .map(|(name, index)| (name, &checker.model.bindings[*index])) - { - if !binding.used() - && binding.kind.is_annotation() - && !checker.settings.dummy_variable_rgx.is_match(name) - { - checker.diagnostics.push(Diagnostic::new( - UnusedAnnotation { - name: (*name).to_string(), - }, - binding.range, - )); - } + .filter_map(|(name, index)| { + let name = *name; + let binding = &checker.semantic_model().bindings[*index]; + + if !binding.used() + && binding.kind.is_annotation() + && !checker.settings.dummy_variable_rgx.is_match(name) + { + Some((name.to_string(), binding.range)) + } else { + None + } + }) + .collect(); + + for (name, range) in bindings { + checker.diagnostics.push(Diagnostic::new( + UnusedAnnotation { + name: (*name).to_string(), + }, + range, + )); } } diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs index d8ed8d5a82..5e8922793e 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_variable.rs @@ -204,7 +204,7 @@ fn remove_unused_variable( if let Some(target) = targets.iter().find(|target| range == target.range()) { if target.is_name_expr() { return if targets.len() > 1 - || contains_effect(value, |id| checker.model.is_builtin(id)) + || contains_effect(value, |id| checker.semantic_model().is_builtin(id)) { // If the expression is complex (`x = foo()`), remove the assignment, // but preserve the right-hand side. @@ -219,7 +219,7 @@ fn remove_unused_variable( )) } else { // If (e.g.) assigning to a constant (`x = 1`), delete the entire statement. - let parent = checker.model.stmts.parent(stmt); + let parent = checker.semantic_model().stmts.parent(stmt); let deleted: Vec<&Stmt> = checker.deletions.iter().map(Into::into).collect(); match delete_stmt( stmt, @@ -249,7 +249,7 @@ fn remove_unused_variable( }) = stmt { if target.is_name_expr() { - return if contains_effect(value, |id| checker.model.is_builtin(id)) { + return if contains_effect(value, |id| checker.semantic_model().is_builtin(id)) { // If the expression is complex (`x = foo()`), remove the assignment, // but preserve the right-hand side. #[allow(deprecated)] @@ -262,7 +262,7 @@ fn remove_unused_variable( )) } else { // If assigning to a constant (`x = 1`), delete the entire statement. - let parent = checker.model.stmts.parent(stmt); + let parent = checker.semantic_model().stmts.parent(stmt); let deleted: Vec<&Stmt> = checker.deletions.iter().map(Into::into).collect(); match delete_stmt( stmt, @@ -313,42 +313,45 @@ fn remove_unused_variable( /// F841 pub(crate) fn unused_variable(checker: &mut Checker, scope: ScopeId) { - let scope = &checker.model.scopes[scope]; + let scope = &checker.semantic_model().scopes[scope]; if scope.uses_locals && matches!(scope.kind, ScopeKind::Function(..)) { return; } - for (name, binding) in scope + let bindings: Vec<_> = scope .bindings() - .map(|(name, index)| (name, &checker.model.bindings[*index])) - { - if !binding.used() - && (binding.kind.is_assignment() || binding.kind.is_named_expr_assignment()) - && !checker.settings.dummy_variable_rgx.is_match(name) - && name != &"__tracebackhide__" - && name != &"__traceback_info__" - && name != &"__traceback_supplement__" - && name != &"__debuggerskip__" - { - let mut diagnostic = Diagnostic::new( - UnusedVariable { - name: (*name).to_string(), - }, - binding.range, - ); - if checker.patch(diagnostic.kind.rule()) { - if let Some(source) = binding.source { - let stmt = checker.model.stmts[source]; - if let Some((kind, fix)) = remove_unused_variable(stmt, binding.range, checker) - { - if matches!(kind, DeletionKind::Whole) { - checker.deletions.insert(RefEquality(stmt)); - } - diagnostic.set_fix(fix); + .map(|(name, index)| (*name, &checker.semantic_model().bindings[*index])) + .filter_map(|(name, binding)| { + if !binding.used() + && (binding.kind.is_assignment() || binding.kind.is_named_expr_assignment()) + && !checker.settings.dummy_variable_rgx.is_match(name) + && name != "__tracebackhide__" + && name != "__traceback_info__" + && name != "__traceback_supplement__" + && name != "__debuggerskip__" + { + return Some((name.to_string(), binding.range, binding.source)); + } + + None + }) + .collect(); + + for (name, range, source) in bindings { + let mut diagnostic = Diagnostic::new(UnusedVariable { name }, range); + + if checker.patch(diagnostic.kind.rule()) { + if let Some(source) = source { + let stmt = checker.semantic_model().stmts[source]; + if let Some((kind, fix)) = remove_unused_variable(stmt, range, checker) { + if matches!(kind, DeletionKind::Whole) { + checker.deletions.insert(RefEquality(stmt)); } + diagnostic.set_fix(fix); } } - checker.diagnostics.push(diagnostic); } + + checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs b/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs index 25660a8523..879118b829 100644 --- a/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs +++ b/crates/ruff/src/rules/pyflakes/rules/yield_outside_function.rs @@ -40,7 +40,7 @@ impl Violation for YieldOutsideFunction { pub(crate) fn yield_outside_function(checker: &mut Checker, expr: &Expr) { if matches!( - checker.model.scope().kind, + checker.semantic_model().scope().kind, ScopeKind::Class(_) | ScopeKind::Module ) { let keyword = match expr { diff --git a/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs b/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs index 64413ea282..ba941d1d85 100644 --- a/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs +++ b/crates/ruff/src/rules/pygrep_hooks/rules/deprecated_log_warn.rs @@ -44,7 +44,7 @@ impl Violation for DeprecatedLogWarn { /// PGH002 pub(crate) fn deprecated_log_warn(checker: &mut Checker, func: &Expr) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["logging", "warn"] diff --git a/crates/ruff/src/rules/pygrep_hooks/rules/no_eval.rs b/crates/ruff/src/rules/pygrep_hooks/rules/no_eval.rs index d4d34f007a..40b224a22c 100644 --- a/crates/ruff/src/rules/pygrep_hooks/rules/no_eval.rs +++ b/crates/ruff/src/rules/pygrep_hooks/rules/no_eval.rs @@ -46,7 +46,7 @@ pub(crate) fn no_eval(checker: &mut Checker, func: &Expr) { if id != "eval" { return; } - if !checker.model.is_builtin("eval") { + if !checker.semantic_model().is_builtin("eval") { return; } checker diff --git a/crates/ruff/src/rules/pylint/rules/await_outside_async.rs b/crates/ruff/src/rules/pylint/rules/await_outside_async.rs index 4c88b51137..30d1605f84 100644 --- a/crates/ruff/src/rules/pylint/rules/await_outside_async.rs +++ b/crates/ruff/src/rules/pylint/rules/await_outside_async.rs @@ -46,7 +46,7 @@ impl Violation for AwaitOutsideAsync { /// PLE1142 pub(crate) fn await_outside_async(checker: &mut Checker, expr: &Expr) { if !checker - .model + .semantic_model() .scopes() .find_map(|scope| { if let ScopeKind::Function(FunctionDef { async_, .. }) = &scope.kind { diff --git a/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs b/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs index 9e79b90e72..8cde351c82 100644 --- a/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs +++ b/crates/ruff/src/rules/pylint/rules/compare_to_empty_string.rs @@ -98,7 +98,7 @@ pub(crate) fn compare_to_empty_string( ) { // Omit string comparison rules within subscripts. This is mostly commonly used within // DataFrame and np.ndarray indexing. - for parent in checker.model.expr_ancestors() { + for parent in checker.semantic_model().expr_ancestors() { if matches!(parent, Expr::Subscript(_)) { return; } diff --git a/crates/ruff/src/rules/pylint/rules/global_statement.rs b/crates/ruff/src/rules/pylint/rules/global_statement.rs index 4841af9376..976b52a61e 100644 --- a/crates/ruff/src/rules/pylint/rules/global_statement.rs +++ b/crates/ruff/src/rules/pylint/rules/global_statement.rs @@ -55,11 +55,11 @@ impl Violation for GlobalStatement { /// PLW0603 pub(crate) fn global_statement(checker: &mut Checker, name: &str) { - let scope = checker.model.scope(); + let scope = checker.semantic_model().scope(); if let Some(index) = scope.get(name) { - let binding = &checker.model.bindings[*index]; + let binding = &checker.semantic_model().bindings[*index]; if binding.kind.is_global() { - let source = checker.model.stmts[binding + let source = checker.semantic_model().stmts[binding .source .expect("`global` bindings should always have a `source`")]; let diagnostic = Diagnostic::new( diff --git a/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs b/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs index db1aa68d86..a70ae406d6 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_envvar_default.rs @@ -84,7 +84,7 @@ pub(crate) fn invalid_envvar_default( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["os", "getenv"]) { diff --git a/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs b/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs index 41dd47a6a6..2377de8466 100644 --- a/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs +++ b/crates/ruff/src/rules/pylint/rules/invalid_envvar_value.rs @@ -81,7 +81,7 @@ pub(crate) fn invalid_envvar_value( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["os", "getenv"]) { diff --git a/crates/ruff/src/rules/pylint/rules/load_before_global_declaration.rs b/crates/ruff/src/rules/pylint/rules/load_before_global_declaration.rs index 1778dee2ef..e205f55a5b 100644 --- a/crates/ruff/src/rules/pylint/rules/load_before_global_declaration.rs +++ b/crates/ruff/src/rules/pylint/rules/load_before_global_declaration.rs @@ -55,7 +55,7 @@ impl Violation for LoadBeforeGlobalDeclaration { } /// PLE0118 pub(crate) fn load_before_global_declaration(checker: &mut Checker, name: &str, expr: &Expr) { - let globals = match &checker.model.scope().kind { + let globals = match &checker.semantic_model().scope().kind { ScopeKind::Class(class_def) => &class_def.globals, ScopeKind::Function(function_def) => &function_def.globals, _ => return, diff --git a/crates/ruff/src/rules/pylint/rules/logging.rs b/crates/ruff/src/rules/pylint/rules/logging.rs index 102f5f55f4..3e8bac9556 100644 --- a/crates/ruff/src/rules/pylint/rules/logging.rs +++ b/crates/ruff/src/rules/pylint/rules/logging.rs @@ -102,7 +102,7 @@ pub(crate) fn logging_call( return; } - if !logging::is_logger_candidate(func, &checker.model) { + if !logging::is_logger_candidate(func, checker.semantic_model()) { return; } diff --git a/crates/ruff/src/rules/pylint/rules/nested_min_max.rs b/crates/ruff/src/rules/pylint/rules/nested_min_max.rs index dde8dcd30b..a35f588b43 100644 --- a/crates/ruff/src/rules/pylint/rules/nested_min_max.rs +++ b/crates/ruff/src/rules/pylint/rules/nested_min_max.rs @@ -128,7 +128,7 @@ pub(crate) fn nested_min_max( args: &[Expr], keywords: &[Keyword], ) { - let Some(min_max) = MinMax::try_from_call(func, keywords, &checker.model) else { + let Some(min_max) = MinMax::try_from_call(func, keywords, checker.semantic_model()) else { return; }; @@ -136,14 +136,15 @@ pub(crate) fn nested_min_max( let Expr::Call(ast::ExprCall { func, keywords, ..} )= arg else { return false; }; - MinMax::try_from_call(func.as_ref(), keywords.as_ref(), &checker.model) == Some(min_max) + MinMax::try_from_call(func.as_ref(), keywords.as_ref(), checker.semantic_model()) + == Some(min_max) }) { let fixable = !has_comments(expr, checker.locator); let mut diagnostic = Diagnostic::new(NestedMinMax { func: min_max }, expr.range()); if fixable && checker.patch(diagnostic.kind.rule()) { let flattened_expr = Expr::Call(ast::ExprCall { func: Box::new(func.clone()), - args: collect_nested_args(&checker.model, min_max, args), + args: collect_nested_args(checker.semantic_model(), min_max, args), keywords: keywords.to_owned(), range: TextRange::default(), }); diff --git a/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs b/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs index f91fc56211..79b06331a4 100644 --- a/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs +++ b/crates/ruff/src/rules/pylint/rules/property_with_parameters.rs @@ -59,7 +59,7 @@ pub(crate) fn property_with_parameters( { return; } - if checker.model.is_builtin("property") + if checker.semantic_model().is_builtin("property") && args .args .iter() diff --git a/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs b/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs index 373c282ae3..8964206d1c 100644 --- a/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs +++ b/crates/ruff/src/rules/pylint/rules/redefined_loop_name.rs @@ -138,16 +138,13 @@ struct ExprWithInnerBindingKind<'a> { binding_kind: InnerBindingKind, } -struct InnerForWithAssignTargetsVisitor<'a> { - context: &'a SemanticModel<'a>, +struct InnerForWithAssignTargetsVisitor<'a, 'b> { + context: &'a SemanticModel<'b>, dummy_variable_rgx: &'a Regex, assignment_targets: Vec>, } -impl<'a, 'b> StatementVisitor<'b> for InnerForWithAssignTargetsVisitor<'a> -where - 'b: 'a, -{ +impl<'a, 'b> StatementVisitor<'b> for InnerForWithAssignTargetsVisitor<'a, 'b> { fn visit_stmt(&mut self, stmt: &'b Stmt) { // Collect target expressions. match stmt { @@ -348,7 +345,7 @@ pub(crate) fn redefined_loop_name<'a, 'b>(checker: &'a mut Checker<'b>, node: &N }) .collect(); let mut visitor = InnerForWithAssignTargetsVisitor { - context: &checker.model, + context: checker.semantic_model(), dummy_variable_rgx: &checker.settings.dummy_variable_rgx, assignment_targets: vec![], }; @@ -368,7 +365,7 @@ pub(crate) fn redefined_loop_name<'a, 'b>(checker: &'a mut Checker<'b>, node: &N }) .collect(); let mut visitor = InnerForWithAssignTargetsVisitor { - context: &checker.model, + context: checker.semantic_model(), dummy_variable_rgx: &checker.settings.dummy_variable_rgx, assignment_targets: vec![], }; @@ -384,13 +381,15 @@ pub(crate) fn redefined_loop_name<'a, 'b>(checker: &'a mut Checker<'b>, node: &N Node::Expr(_) => panic!("redefined_loop_name called on Node that is not a Statement"), }; + let mut diagnostics = Vec::new(); + for outer_assignment_target in &outer_assignment_targets { for inner_assignment_target in &inner_assignment_targets { // Compare the targets structurally. if ComparableExpr::from(outer_assignment_target.expr) .eq(&(ComparableExpr::from(inner_assignment_target.expr))) { - checker.diagnostics.push(Diagnostic::new( + diagnostics.push(Diagnostic::new( RedefinedLoopName { name: checker.generator().expr(outer_assignment_target.expr), outer_kind: outer_assignment_target.binding_kind, @@ -401,4 +400,6 @@ pub(crate) fn redefined_loop_name<'a, 'b>(checker: &'a mut Checker<'b>, node: &N } } } + + checker.diagnostics.extend(diagnostics); } diff --git a/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs b/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs index bced6188c7..002d31a071 100644 --- a/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs +++ b/crates/ruff/src/rules/pylint/rules/repeated_isinstance_calls.rs @@ -58,7 +58,7 @@ pub(crate) fn repeated_isinstance_calls( op: Boolop, values: &[Expr], ) { - if !matches!(op, Boolop::Or) || !checker.model.is_builtin("isinstance") { + if !matches!(op, Boolop::Or) || !checker.semantic_model().is_builtin("isinstance") { return; } diff --git a/crates/ruff/src/rules/pylint/rules/return_in_init.rs b/crates/ruff/src/rules/pylint/rules/return_in_init.rs index 3ab08833f9..0bd7cd7758 100644 --- a/crates/ruff/src/rules/pylint/rules/return_in_init.rs +++ b/crates/ruff/src/rules/pylint/rules/return_in_init.rs @@ -62,7 +62,7 @@ pub(crate) fn return_in_init(checker: &mut Checker, stmt: &Stmt) { } } - if in_dunder_init(&checker.model, checker.settings) { + if in_dunder_init(checker.semantic_model(), checker.settings) { checker .diagnostics .push(Diagnostic::new(ReturnInInit, stmt.range())); diff --git a/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs b/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs index a1f4670711..e40e5bd428 100644 --- a/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs +++ b/crates/ruff/src/rules/pylint/rules/sys_exit_alias.rs @@ -65,7 +65,7 @@ pub(crate) fn sys_exit_alias(checker: &mut Checker, func: &Expr) { if id != name { continue; } - if !checker.model.is_builtin(name) { + if !checker.semantic_model().is_builtin(name) { continue; } let mut diagnostic = Diagnostic::new( @@ -80,7 +80,7 @@ pub(crate) fn sys_exit_alias(checker: &mut Checker, func: &Expr) { "sys", "exit", func.start(), - &checker.model, + checker.semantic_model(), &checker.importer, checker.locator, )?; diff --git a/crates/ruff/src/rules/pylint/rules/unexpected_special_method_signature.rs b/crates/ruff/src/rules/pylint/rules/unexpected_special_method_signature.rs index 18d82d9093..94b8cdbf0a 100644 --- a/crates/ruff/src/rules/pylint/rules/unexpected_special_method_signature.rs +++ b/crates/ruff/src/rules/pylint/rules/unexpected_special_method_signature.rs @@ -145,7 +145,7 @@ pub(crate) fn unexpected_special_method_signature( args: &Arguments, locator: &Locator, ) { - if !checker.model.scope().kind.is_class() { + if !checker.semantic_model().scope().kind.is_class() { return; } @@ -163,7 +163,7 @@ pub(crate) fn unexpected_special_method_signature( let optional_params = args.defaults.len(); let mandatory_params = actual_params - optional_params; - let Some(expected_params) = ExpectedParams::from_method(name, is_staticmethod(&checker.model, decorator_list)) else { + let Some(expected_params) = ExpectedParams::from_method(name, is_staticmethod(checker.semantic_model(), decorator_list)) else { return; }; diff --git a/crates/ruff/src/rules/pylint/rules/yield_in_init.rs b/crates/ruff/src/rules/pylint/rules/yield_in_init.rs index d81d7a929e..9ee87e70a7 100644 --- a/crates/ruff/src/rules/pylint/rules/yield_in_init.rs +++ b/crates/ruff/src/rules/pylint/rules/yield_in_init.rs @@ -39,7 +39,7 @@ impl Violation for YieldInInit { /// PLE0100 pub(crate) fn yield_in_init(checker: &mut Checker, expr: &Expr) { - if in_dunder_init(&checker.model, checker.settings) { + if in_dunder_init(checker.semantic_model(), checker.settings) { checker .diagnostics .push(Diagnostic::new(YieldInInit, expr.range())); diff --git a/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs b/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs index d15629c816..f5f386492b 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/convert_named_tuple_functional_to_class.rs @@ -184,7 +184,7 @@ pub(crate) fn convert_named_tuple_functional_to_class( value: &Expr, ) { let Some((typename, args, keywords, base_class)) = - match_named_tuple_assign(&checker.model, targets, value) else + match_named_tuple_assign(checker.semantic_model(), targets, value) else { return; }; diff --git a/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs b/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs index 6af560dcf9..3e51f00c6c 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/convert_typed_dict_functional_to_class.rs @@ -240,7 +240,7 @@ pub(crate) fn convert_typed_dict_functional_to_class( value: &Expr, ) { let Some((class_name, args, keywords, base_class)) = - match_typed_dict_assign(&checker.model, targets, value) else + match_typed_dict_assign(checker.semantic_model(), targets, value) else { return; }; diff --git a/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs index b89ded1e4d..16aa05a145 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/datetime_utc_alias.rs @@ -28,7 +28,7 @@ impl Violation for DatetimeTimezoneUTC { /// UP017 pub(crate) fn datetime_utc_alias(checker: &mut Checker, expr: &Expr) { if checker - .model + .semantic_model() .resolve_call_path(expr) .map_or(false, |call_path| { call_path.as_slice() == ["datetime", "timezone", "utc"] diff --git a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs index 41733866b7..4c2fa62c3a 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_with_maxsize_none.rs @@ -38,7 +38,7 @@ pub(crate) fn lru_cache_with_maxsize_none(checker: &mut Checker, decorator_list: if args.is_empty() && keywords.len() == 1 && checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["functools", "lru_cache"] @@ -69,7 +69,7 @@ pub(crate) fn lru_cache_with_maxsize_none(checker: &mut Checker, decorator_list: "functools", "cache", expr.start(), - &checker.model, + checker.semantic_model(), &checker.importer, checker.locator, )?; diff --git a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs index 66e6ead4a7..f276d8f8e5 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/lru_cache_without_parameters.rs @@ -37,7 +37,7 @@ pub(crate) fn lru_cache_without_parameters(checker: &mut Checker, decorator_list if args.is_empty() && keywords.is_empty() && checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["functools", "lru_cache"] diff --git a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs index 6580a2be11..5c5172791b 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/native_literals.rs @@ -56,7 +56,7 @@ pub(crate) fn native_literals( return; } - if (id == "str" || id == "bytes") && checker.model.is_builtin(id) { + if (id == "str" || id == "bytes") && checker.semantic_model().is_builtin(id) { let Some(arg) = args.get(0) else { let mut diagnostic = Diagnostic::new(NativeLiterals{literal_type:if id == "str" { LiteralType::Str diff --git a/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs index ffae0d601b..b51c115271 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/open_alias.rs @@ -25,12 +25,12 @@ impl Violation for OpenAlias { /// UP020 pub(crate) fn open_alias(checker: &mut Checker, expr: &Expr, func: &Expr) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["io", "open"]) { let fixable = checker - .model + .semantic_model() .find_binding("open") .map_or(true, |binding| binding.kind.is_builtin()); let mut diagnostic = Diagnostic::new(OpenAlias, expr.range()); diff --git a/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs index d767b5fe75..82a3da68ba 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/os_error_alias.rs @@ -93,7 +93,10 @@ fn tuple_diagnostic(checker: &mut Checker, target: &Expr, aliases: &[&Expr]) { .collect(); // If `OSError` itself isn't already in the tuple, add it. - if elts.iter().all(|elt| !is_os_error(&checker.model, elt)) { + if elts + .iter() + .all(|elt| !is_os_error(checker.semantic_model(), elt)) + { let node = ast::ExprName { id: "OSError".into(), ctx: ExprContext::Load, @@ -133,7 +136,7 @@ pub(crate) fn os_error_alias_handlers(checker: &mut Checker, handlers: &[Excepth }; match expr.as_ref() { Expr::Name(_) | Expr::Attribute(_) => { - if is_alias(&checker.model, expr) { + if is_alias(checker.semantic_model(), expr) { atom_diagnostic(checker, expr); } } @@ -141,7 +144,7 @@ pub(crate) fn os_error_alias_handlers(checker: &mut Checker, handlers: &[Excepth // List of aliases to replace with `OSError`. let mut aliases: Vec<&Expr> = vec![]; for elt in elts { - if is_alias(&checker.model, elt) { + if is_alias(checker.semantic_model(), elt) { aliases.push(elt); } } @@ -156,7 +159,7 @@ pub(crate) fn os_error_alias_handlers(checker: &mut Checker, handlers: &[Excepth /// UP024 pub(crate) fn os_error_alias_call(checker: &mut Checker, func: &Expr) { - if is_alias(&checker.model, func) { + if is_alias(checker.semantic_model(), func) { atom_diagnostic(checker, func); } } @@ -164,7 +167,7 @@ pub(crate) fn os_error_alias_call(checker: &mut Checker, func: &Expr) { /// UP024 pub(crate) fn os_error_alias_raise(checker: &mut Checker, expr: &Expr) { if matches!(expr, Expr::Name(_) | Expr::Attribute(_)) { - if is_alias(&checker.model, expr) { + if is_alias(checker.semantic_model(), expr) { atom_diagnostic(checker, expr); } } diff --git a/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs b/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs index 0e31033952..cbeaa40f29 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/outdated_version_block.rs @@ -164,8 +164,8 @@ fn fix_py2_block( // of its parent, so avoid passing in the parent at all. Otherwise, // `delete_stmt` will erroneously include a `pass`. let deleted: Vec<&Stmt> = checker.deletions.iter().map(Into::into).collect(); - let defined_by = checker.model.stmt(); - let defined_in = checker.model.stmt_parent(); + let defined_by = checker.semantic_model().stmt(); + let defined_in = checker.semantic_model().stmt_parent(); return match delete_stmt( defined_by, if block.starter == Tok::If { @@ -323,7 +323,7 @@ pub(crate) fn outdated_version_block( }; if !checker - .model + .semantic_model() .resolve_call_path(left) .map_or(false, |call_path| { call_path.as_slice() == ["sys", "version_info"] diff --git a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs index 69c0772636..9dabf61d24 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/redundant_open_modes.rs @@ -173,7 +173,7 @@ fn create_remove_param_fix(locator: &Locator, expr: &Expr, mode_param: &Expr) -> /// UP015 pub(crate) fn redundant_open_modes(checker: &mut Checker, expr: &Expr) { // If `open` has been rebound, skip this check entirely. - if !checker.model.is_builtin(OPEN_FUNC_NAME) { + if !checker.semantic_model().is_builtin(OPEN_FUNC_NAME) { return; } let (mode_param, keywords): (Option<&Expr>, Vec) = match_open(expr); diff --git a/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs b/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs index 34d72db948..91f943b0ad 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/replace_stdout_stderr.rs @@ -61,7 +61,7 @@ pub(crate) fn replace_stdout_stderr( keywords: &[Keyword], ) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["subprocess", "run"] @@ -77,13 +77,13 @@ pub(crate) fn replace_stdout_stderr( // Verify that they're both set to `subprocess.PIPE`. if !checker - .model + .semantic_model() .resolve_call_path(&stdout.value) .map_or(false, |call_path| { call_path.as_slice() == ["subprocess", "PIPE"] }) || !checker - .model + .semantic_model() .resolve_call_path(&stderr.value) .map_or(false, |call_path| { call_path.as_slice() == ["subprocess", "PIPE"] diff --git a/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs b/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs index 9f11ce0009..23c0e49de0 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/replace_universal_newlines.rs @@ -25,7 +25,7 @@ impl AlwaysAutofixableViolation for ReplaceUniversalNewlines { /// UP021 pub(crate) fn replace_universal_newlines(checker: &mut Checker, func: &Expr, kwargs: &[Keyword]) { if checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| { call_path.as_slice() == ["subprocess", "run"] diff --git a/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs b/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs index 4f634ff949..c175297910 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/super_call_with_parameters.rs @@ -43,14 +43,14 @@ pub(crate) fn super_call_with_parameters( if !is_super_call_with_arguments(func, args) { return; } - let scope = checker.model.scope(); + let scope = checker.semantic_model().scope(); // Check: are we in a Function scope? if !matches!(scope.kind, ScopeKind::Function(_)) { return; } - let mut parents = checker.model.parents(); + let mut parents = checker.semantic_model().parents(); // For a `super` invocation to be unnecessary, the first argument needs to match // the enclosing class, and the second argument needs to match the first @@ -97,6 +97,7 @@ pub(crate) fn super_call_with_parameters( return; } + drop(parents); let mut diagnostic = Diagnostic::new(SuperCallWithParameters, expr.range()); if checker.patch(diagnostic.kind.rule()) { if let Some(edit) = fixes::remove_super_arguments(checker.locator, checker.stylist, expr) { diff --git a/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs b/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs index 4d148877de..7f2c9a5964 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/type_of_primitive.rs @@ -32,7 +32,7 @@ pub(crate) fn type_of_primitive(checker: &mut Checker, expr: &Expr, func: &Expr, return; } if !checker - .model + .semantic_model() .resolve_call_path(func) .map_or(false, |call_path| call_path.as_slice() == ["", "type"]) { diff --git a/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs b/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs index c38161e68f..5b1a867cca 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/typing_text_str_alias.rs @@ -23,7 +23,7 @@ impl AlwaysAutofixableViolation for TypingTextStrAlias { /// UP019 pub(crate) fn typing_text_str_alias(checker: &mut Checker, expr: &Expr) { if checker - .model + .semantic_model() .resolve_call_path(expr) .map_or(false, |call_path| { call_path.as_slice() == ["typing", "Text"] diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs index 4ee3401243..4c7415de11 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_builtin_import.rs @@ -106,8 +106,8 @@ pub(crate) fn unnecessary_builtin_import( if checker.patch(diagnostic.kind.rule()) { let deleted: Vec<&Stmt> = checker.deletions.iter().map(Into::into).collect(); - let defined_by = checker.model.stmt(); - let defined_in = checker.model.stmt_parent(); + let defined_by = checker.semantic_model().stmt(); + let defined_in = checker.semantic_model().stmt_parent(); let unused_imports: Vec = unused_imports .iter() .map(|alias| format!("{module}.{}", alias.name)) diff --git a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs index 2028375c3f..e9da4149d0 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/unnecessary_future_import.rs @@ -86,8 +86,8 @@ pub(crate) fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, name if checker.patch(diagnostic.kind.rule()) { let deleted: Vec<&Stmt> = checker.deletions.iter().map(Into::into).collect(); - let defined_by = checker.model.stmt(); - let defined_in = checker.model.stmt_parent(); + let defined_by = checker.semantic_model().stmt(); + let defined_in = checker.semantic_model().stmt_parent(); let unused_imports: Vec = unused_imports .iter() .map(|alias| format!("__future__.{}", alias.name)) diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs index 27a04c5975..ca6a5ceaf4 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs @@ -46,12 +46,12 @@ pub(crate) fn use_pep585_annotation( }, expr.range(), ); - let fixable = !checker.model.in_complex_string_type_definition(); + let fixable = !checker.semantic_model().in_complex_string_type_definition(); if fixable && checker.patch(diagnostic.kind.rule()) { match replacement { ModuleMember::BuiltIn(name) => { // Built-in type, like `list`. - if checker.model.is_builtin(name) { + if checker.semantic_model().is_builtin(name) { diagnostic.set_fix(Fix::automatic(Edit::range_replacement( (*name).to_string(), expr.range(), @@ -65,7 +65,7 @@ pub(crate) fn use_pep585_annotation( module, member, expr.start(), - &checker.model, + checker.semantic_model(), &checker.importer, checker.locator, )?; diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs index e464262811..789e89b685 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_annotation.rs @@ -58,8 +58,8 @@ pub(crate) fn use_pep604_annotation( operator: Pep604Operator, ) { // Avoid fixing forward references, or types not in an annotation. - let fixable = - checker.model.in_type_definition() && !checker.model.in_complex_string_type_definition(); + let fixable = checker.semantic_model().in_type_definition() + && !checker.semantic_model().in_complex_string_type_definition(); match operator { Pep604Operator::Optional => { let mut diagnostic = Diagnostic::new(NonPEP604Annotation, expr.range()); diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs index 66d1b24c31..d0f8baaf92 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep604_isinstance.rs @@ -74,7 +74,7 @@ pub(crate) fn use_pep604_isinstance( let Some(kind) = CallKind::from_name(id) else { return; }; - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; }; if let Some(types) = args.get(1) { diff --git a/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs b/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs index 10f738bd2a..9cf7e04057 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/useless_metaclass_type.rs @@ -56,8 +56,8 @@ pub(crate) fn useless_metaclass_type( }; if checker.patch(diagnostic.kind.rule()) { let deleted: Vec<&Stmt> = checker.deletions.iter().map(Into::into).collect(); - let defined_by = checker.model.stmt(); - let defined_in = checker.model.stmt_parent(); + let defined_by = checker.semantic_model().stmt(); + let defined_in = checker.semantic_model().stmt_parent(); match actions::delete_stmt( defined_by, defined_in, diff --git a/crates/ruff/src/rules/pyupgrade/rules/useless_object_inheritance.rs b/crates/ruff/src/rules/pyupgrade/rules/useless_object_inheritance.rs index 5b48caeffa..4ae6d1f3dd 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/useless_object_inheritance.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/useless_object_inheritance.rs @@ -62,8 +62,12 @@ pub(crate) fn useless_object_inheritance( bases: &[Expr], keywords: &[Keyword], ) { - if let Some(mut diagnostic) = rule(name, bases, checker.model.scope(), &checker.model.bindings) - { + if let Some(mut diagnostic) = rule( + name, + bases, + checker.semantic_model().scope(), + &checker.semantic_model().bindings, + ) { if checker.patch(diagnostic.kind.rule()) { let expr_range = diagnostic.range(); #[allow(deprecated)] diff --git a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs index ca7fefab4c..e281e791b1 100644 --- a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs +++ b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs @@ -131,7 +131,7 @@ pub(crate) fn explicit_f_string_type_conversion( return; }; - if !checker.model.is_builtin(id) { + if !checker.semantic_model().is_builtin(id) { return; } diff --git a/crates/ruff/src/rules/ruff/rules/mutable_defaults_in_dataclass_fields.rs b/crates/ruff/src/rules/ruff/rules/mutable_defaults_in_dataclass_fields.rs index 69fa2875e4..b1c72ecdf8 100644 --- a/crates/ruff/src/rules/ruff/rules/mutable_defaults_in_dataclass_fields.rs +++ b/crates/ruff/src/rules/ruff/rules/mutable_defaults_in_dataclass_fields.rs @@ -195,12 +195,12 @@ pub(crate) fn function_call_in_dataclass_defaults(checker: &mut Checker, body: & .. }) = statement { - if is_class_var_annotation(&checker.model, annotation) { + if is_class_var_annotation(checker.semantic_model(), annotation) { continue; } if let Expr::Call(ast::ExprCall { func, .. }) = expr.as_ref() { - if !is_immutable_func(&checker.model, func, &extend_immutable_calls) - && !is_allowed_dataclass_function(&checker.model, func) + if !is_immutable_func(checker.semantic_model(), func, &extend_immutable_calls) + && !is_allowed_dataclass_function(checker.semantic_model(), func) { checker.diagnostics.push(Diagnostic::new( FunctionCallInDataclassDefaultArgument { @@ -223,8 +223,8 @@ pub(crate) fn mutable_dataclass_default(checker: &mut Checker, body: &[Stmt]) { value: Some(value), .. }) => { - if !is_class_var_annotation(&checker.model, annotation) - && !is_immutable_annotation(&checker.model, annotation) + if !is_class_var_annotation(checker.semantic_model(), annotation) + && !is_immutable_annotation(checker.semantic_model(), annotation) && is_mutable_expr(value) { checker diff --git a/crates/ruff/src/rules/ruff/rules/pairwise_over_zipped.rs b/crates/ruff/src/rules/ruff/rules/pairwise_over_zipped.rs index 84d719ea70..99c2286a75 100644 --- a/crates/ruff/src/rules/ruff/rules/pairwise_over_zipped.rs +++ b/crates/ruff/src/rules/ruff/rules/pairwise_over_zipped.rs @@ -99,7 +99,7 @@ pub(crate) fn pairwise_over_zipped(checker: &mut Checker, func: &Expr, args: &[E } // Require the function to be the builtin `zip`. - if !(id == "zip" && checker.model.is_builtin(id)) { + if !(id == "zip" && checker.semantic_model().is_builtin(id)) { return; } diff --git a/crates/ruff/src/rules/tryceratops/helpers.rs b/crates/ruff/src/rules/tryceratops/helpers.rs index 7e94ca4c9a..b0a1cdb992 100644 --- a/crates/ruff/src/rules/tryceratops/helpers.rs +++ b/crates/ruff/src/rules/tryceratops/helpers.rs @@ -6,13 +6,13 @@ use ruff_python_semantic::analyze::logging; use ruff_python_semantic::model::SemanticModel; /// Collect `logging`-like calls from an AST. -pub(crate) struct LoggerCandidateVisitor<'a> { - context: &'a SemanticModel<'a>, - pub(crate) calls: Vec<(&'a Expr, &'a Expr)>, +pub(crate) struct LoggerCandidateVisitor<'a, 'b> { + context: &'a SemanticModel<'b>, + pub(crate) calls: Vec<(&'b Expr, &'b Expr)>, } -impl<'a> LoggerCandidateVisitor<'a> { - pub(crate) fn new(context: &'a SemanticModel<'a>) -> Self { +impl<'a, 'b> LoggerCandidateVisitor<'a, 'b> { + pub(crate) fn new(context: &'a SemanticModel<'b>) -> Self { LoggerCandidateVisitor { context, calls: Vec::new(), @@ -20,10 +20,7 @@ impl<'a> LoggerCandidateVisitor<'a> { } } -impl<'a, 'b> Visitor<'b> for LoggerCandidateVisitor<'a> -where - 'b: 'a, -{ +impl<'a, 'b> Visitor<'b> for LoggerCandidateVisitor<'a, 'b> { fn visit_expr(&mut self, expr: &'b Expr) { if let Expr::Call(ast::ExprCall { func, .. }) = expr { if logging::is_logger_candidate(func, self.context) { diff --git a/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs b/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs index 5f7f693ed4..ed27a6f10d 100644 --- a/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs +++ b/crates/ruff/src/rules/tryceratops/rules/error_instead_of_exception.rs @@ -57,7 +57,7 @@ pub(crate) fn error_instead_of_exception(checker: &mut Checker, handlers: &[Exce for handler in handlers { let Excepthandler::ExceptHandler(ast::ExcepthandlerExceptHandler { body, .. }) = handler; let calls = { - let mut visitor = LoggerCandidateVisitor::new(&checker.model); + let mut visitor = LoggerCandidateVisitor::new(checker.semantic_model()); visitor.visit_body(body); visitor.calls }; diff --git a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs index d81f1a0142..46024b2db3 100644 --- a/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs +++ b/crates/ruff/src/rules/tryceratops/rules/raise_vanilla_class.rs @@ -63,7 +63,7 @@ impl Violation for RaiseVanillaClass { /// TRY002 pub(crate) fn raise_vanilla_class(checker: &mut Checker, expr: &Expr) { if checker - .model + .semantic_model() .resolve_call_path(if let Expr::Call(ast::ExprCall { func, .. }) = expr { func } else { diff --git a/crates/ruff/src/rules/tryceratops/rules/try_consider_else.rs b/crates/ruff/src/rules/tryceratops/rules/try_consider_else.rs index 700fd168b1..91e7624f94 100644 --- a/crates/ruff/src/rules/tryceratops/rules/try_consider_else.rs +++ b/crates/ruff/src/rules/tryceratops/rules/try_consider_else.rs @@ -66,7 +66,7 @@ pub(crate) fn try_consider_else( if let Some(stmt) = body.last() { if let Stmt::Return(ast::StmtReturn { value, range: _ }) = stmt { if let Some(value) = value { - if contains_effect(value, |id| checker.model.is_builtin(id)) { + if contains_effect(value, |id| checker.semantic_model().is_builtin(id)) { return; } } diff --git a/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs b/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs index afe3e6408e..f87d7b010a 100644 --- a/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs +++ b/crates/ruff/src/rules/tryceratops/rules/type_check_without_type_error.rs @@ -77,7 +77,7 @@ fn has_control_flow(stmt: &Stmt) -> bool { /// Returns `true` if an [`Expr`] is a call to check types. fn check_type_check_call(checker: &mut Checker, call: &Expr) -> bool { checker - .model + .semantic_model() .resolve_call_path(call) .map_or(false, |call_path| { call_path.as_slice() == ["", "isinstance"] @@ -101,7 +101,7 @@ fn check_type_check_test(checker: &mut Checker, test: &Expr) -> bool { /// Returns `true` if `exc` is a reference to a builtin exception. fn is_builtin_exception(checker: &mut Checker, exc: &Expr) -> bool { return checker - .model + .semantic_model() .resolve_call_path(exc) .map_or(false, |call_path| { [ diff --git a/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs b/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs index 411242b5e2..46d4d7465e 100644 --- a/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs +++ b/crates/ruff/src/rules/tryceratops/rules/verbose_log_message.rs @@ -74,7 +74,7 @@ pub(crate) fn verbose_log_message(checker: &mut Checker, handlers: &[Excepthandl // Find all calls to `logging.exception`. let calls = { - let mut visitor = LoggerCandidateVisitor::new(&checker.model); + let mut visitor = LoggerCandidateVisitor::new(checker.semantic_model()); visitor.visit_body(body); visitor.calls }; diff --git a/crates/ruff_python_semantic/src/model.rs b/crates/ruff_python_semantic/src/model.rs index 7c94dc642a..99bdc070eb 100644 --- a/crates/ruff_python_semantic/src/model.rs +++ b/crates/ruff_python_semantic/src/model.rs @@ -261,10 +261,7 @@ impl<'a> SemanticModel<'a> { /// ``` /// /// ...then `resolve_call_path(${python_version})` will resolve to `sys.version_info`. - pub fn resolve_call_path<'b>(&'a self, value: &'b Expr) -> Option> - where - 'b: 'a, - { + pub fn resolve_call_path(&'a self, value: &'a Expr) -> Option> { let Some(call_path) = collect_call_path(value) else { return None; };