Rename Checker::model to semantic_model (#4573)

This commit is contained in:
Micha Reiser 2023-05-22 15:14:30 +02:00 committed by GitHub
parent 063431cb0f
commit cbe344f4d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
158 changed files with 1009 additions and 827 deletions

File diff suppressed because it is too large Load diff

View file

@ -122,7 +122,7 @@ fn is_sys(model: &SemanticModel, expr: &Expr, target: &str) -> bool {
/// YTT101, YTT102, YTT301, YTT303 /// YTT101, YTT102, YTT301, YTT303
pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) { 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 { match slice {
Expr::Slice(ast::ExprSlice { Expr::Slice(ast::ExprSlice {
lower: None, 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]) { pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &[Expr]) {
match left { match left {
Expr::Subscript(ast::ExprSubscript { value, slice, .. }) 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 { if let Expr::Constant(ast::ExprConstant {
value: Constant::Int(i), 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, .. }) 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 ( if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], [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 ( if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE], [Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
[Expr::Constant(ast::ExprConstant { [Expr::Constant(ast::ExprConstant {
@ -272,7 +272,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
/// YTT202 /// YTT202
pub(crate) fn name_or_attribute(checker: &mut Checker, expr: &Expr) { pub(crate) fn name_or_attribute(checker: &mut Checker, expr: &Expr) {
if checker if checker
.model .semantic_model()
.resolve_call_path(expr) .resolve_call_path(expr)
.map_or(false, |call_path| call_path.as_slice() == ["six", "PY3"]) .map_or(false, |call_path| call_path.as_slice() == ["six", "PY3"])
{ {

View file

@ -480,7 +480,7 @@ pub(crate) fn definition(
// unless configured to suppress ANN* for declarations that are fully untyped. // unless configured to suppress ANN* for declarations that are fully untyped.
let mut diagnostics = Vec::new(); 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 // ANN001, ANN401
for arg in args for arg in args
@ -492,7 +492,10 @@ pub(crate) fn definition(
// If this is a non-static method, skip `cls` or `self`. // If this is a non-static method, skip `cls` or `self`.
usize::from( usize::from(
is_method 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; has_any_typed_arg = true;
if checker.settings.rules.enabled(Rule::AnyType) { if checker.settings.rules.enabled(Rule::AnyType) {
check_dynamically_typed( check_dynamically_typed(
&checker.model, checker.semantic_model(),
annotation, annotation,
|| arg.arg.to_string(), || arg.arg.to_string(),
&mut diagnostics, &mut diagnostics,
@ -536,7 +539,7 @@ pub(crate) fn definition(
if checker.settings.rules.enabled(Rule::AnyType) { if checker.settings.rules.enabled(Rule::AnyType) {
let name = &arg.arg; let name = &arg.arg;
check_dynamically_typed( check_dynamically_typed(
&checker.model, checker.semantic_model(),
expr, expr,
|| format!("*{name}"), || format!("*{name}"),
&mut diagnostics, &mut diagnostics,
@ -568,7 +571,7 @@ pub(crate) fn definition(
if checker.settings.rules.enabled(Rule::AnyType) { if checker.settings.rules.enabled(Rule::AnyType) {
let name = &arg.arg; let name = &arg.arg;
check_dynamically_typed( check_dynamically_typed(
&checker.model, checker.semantic_model(),
expr, expr,
|| format!("**{name}"), || format!("**{name}"),
&mut diagnostics, &mut diagnostics,
@ -593,10 +596,13 @@ pub(crate) fn definition(
} }
// ANN101, ANN102 // 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 let Some(arg) = args.posonlyargs.first().or_else(|| args.args.first()) {
if arg.annotation.is_none() { 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) { if checker.settings.rules.enabled(Rule::MissingTypeCls) {
diagnostics.push(Diagnostic::new( diagnostics.push(Diagnostic::new(
MissingTypeCls { MissingTypeCls {
@ -626,7 +632,7 @@ pub(crate) fn definition(
has_typed_return = true; has_typed_return = true;
if checker.settings.rules.enabled(Rule::AnyType) { if checker.settings.rules.enabled(Rule::AnyType) {
check_dynamically_typed( check_dynamically_typed(
&checker.model, checker.semantic_model(),
expr, expr,
|| name.to_string(), || name.to_string(),
&mut diagnostics, &mut diagnostics,
@ -638,7 +644,9 @@ pub(crate) fn definition(
// (explicitly or implicitly). // (explicitly or implicitly).
checker.settings.flake8_annotations.suppress_none_returning && is_none_returning(body) 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 if checker
.settings .settings
.rules .rules
@ -652,7 +660,7 @@ pub(crate) fn definition(
)); ));
} }
} else if is_method } 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 if checker
.settings .settings

View file

@ -66,10 +66,13 @@ const BLOCKING_HTTP_CALLS: &[&[&str]] = &[
/// ASYNC100 /// ASYNC100
pub(crate) fn blocking_http_call(checker: &mut Checker, expr: &Expr) { 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 Expr::Call(ast::ExprCall { func, .. }) = expr {
if let Some(call_path) = checker.model.resolve_call_path(func) { let call_path = checker.semantic_model().resolve_call_path(func);
if BLOCKING_HTTP_CALLS.contains(&call_path.as_slice()) { let is_blocking =
call_path.map_or(false, |path| BLOCKING_HTTP_CALLS.contains(&path.as_slice()));
if is_blocking {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
BlockingHttpCallInAsyncFunction, BlockingHttpCallInAsyncFunction,
func.range(), func.range(),
@ -77,7 +80,6 @@ pub(crate) fn blocking_http_call(checker: &mut Checker, expr: &Expr) {
} }
} }
} }
}
} }
/// ## What it does /// ## What it does
@ -133,10 +135,16 @@ const OPEN_SLEEP_OR_SUBPROCESS_CALL: &[&[&str]] = &[
/// ASYNC101 /// ASYNC101
pub(crate) fn open_sleep_or_subprocess_call(checker: &mut Checker, expr: &Expr) { 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 Expr::Call(ast::ExprCall { func, .. }) = expr {
if let Some(call_path) = checker.model.resolve_call_path(func) { let is_open_sleep_or_subprocess_call = checker
if OPEN_SLEEP_OR_SUBPROCESS_CALL.contains(&call_path.as_slice()) { .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( checker.diagnostics.push(Diagnostic::new(
OpenSleepOrSubprocessInAsyncFunction, OpenSleepOrSubprocessInAsyncFunction,
func.range(), func.range(),
@ -144,7 +152,6 @@ pub(crate) fn open_sleep_or_subprocess_call(checker: &mut Checker, expr: &Expr)
} }
} }
} }
}
} }
/// ## What it does /// ## What it does
@ -197,17 +204,20 @@ const UNSAFE_OS_METHODS: &[&[&str]] = &[
/// ASYNC102 /// ASYNC102
pub(crate) fn blocking_os_call(checker: &mut Checker, expr: &Expr) { 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 Expr::Call(ast::ExprCall { func, .. }) = expr {
if let Some(call_path) = checker.model.resolve_call_path(func) { let is_unsafe_os_method = checker
if UNSAFE_OS_METHODS.contains(&call_path.as_slice()) { .semantic_model()
.resolve_call_path(func)
.map_or(false, |path| UNSAFE_OS_METHODS.contains(&path.as_slice()));
if is_unsafe_os_method {
checker checker
.diagnostics .diagnostics
.push(Diagnostic::new(BlockingOsCallInAsyncFunction, func.range())); .push(Diagnostic::new(BlockingOsCallInAsyncFunction, func.range()));
} }
} }
} }
}
} }
/// Return `true` if the [`SemanticModel`] is inside an async function definition. /// Return `true` if the [`SemanticModel`] is inside an async function definition.

View file

@ -108,7 +108,7 @@ pub(crate) fn bad_file_permissions(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| call_path.as_slice() == ["os", "chmod"]) .map_or(false, |call_path| call_path.as_slice() == ["os", "chmod"])
{ {

View file

@ -60,7 +60,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
op: Operator::Add | Operator::Mod, 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) { if any_over_expr(expr, &has_string_literal) {
return Some(checker.generator().expr(expr)); return Some(checker.generator().expr(expr));
} }

View file

@ -48,7 +48,11 @@ pub(crate) fn hashlib_insecure_hash_functions(
args: &[Expr], args: &[Expr],
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if let Some(hashlib_call) = checker.model.resolve_call_path(func).and_then(|call_path| { if let Some(hashlib_call) =
checker
.semantic_model()
.resolve_call_path(func)
.and_then(|call_path| {
if call_path.as_slice() == ["hashlib", "new"] { if call_path.as_slice() == ["hashlib", "new"] {
Some(HashlibCall::New) Some(HashlibCall::New)
} else { } else {
@ -57,7 +61,8 @@ pub(crate) fn hashlib_insecure_hash_functions(
.find(|hash| call_path.as_slice() == ["hashlib", hash]) .find(|hash| call_path.as_slice() == ["hashlib", hash])
.map(|hash| HashlibCall::WeakHash(hash)) .map(|hash| HashlibCall::WeakHash(hash))
} }
}) { })
{
match hashlib_call { match hashlib_call {
HashlibCall::New => { HashlibCall::New => {
let call_args = SimpleCallArgs::new(args, keywords); let call_args = SimpleCallArgs::new(args, keywords);

View file

@ -37,7 +37,7 @@ pub(crate) fn jinja2_autoescape_false(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["jinja2", "Environment"] call_path.as_slice() == ["jinja2", "Environment"]

View file

@ -24,7 +24,7 @@ pub(crate) fn logging_config_insecure_listen(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["logging", "config", "listen"] call_path.as_slice() == ["logging", "config", "listen"]

View file

@ -18,7 +18,7 @@ impl Violation for ParamikoCall {
/// S601 /// S601
pub(crate) fn paramiko_call(checker: &mut Checker, func: &Expr) { pub(crate) fn paramiko_call(checker: &mut Checker, func: &Expr) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["paramiko", "exec_command"] call_path.as_slice() == ["paramiko", "exec_command"]

View file

@ -43,7 +43,10 @@ pub(crate) fn request_with_no_cert_validation(
args: &[Expr], args: &[Expr],
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if let Some(target) = checker.model.resolve_call_path(func).and_then(|call_path| { if let Some(target) = checker
.semantic_model()
.resolve_call_path(func)
.and_then(|call_path| {
if call_path.len() == 2 { if call_path.len() == 2 {
if call_path[0] == "requests" && REQUESTS_HTTP_VERBS.contains(&call_path[1]) { if call_path[0] == "requests" && REQUESTS_HTTP_VERBS.contains(&call_path[1]) {
return Some("requests"); return Some("requests");
@ -53,7 +56,8 @@ pub(crate) fn request_with_no_cert_validation(
} }
} }
None None
}) { })
{
let call_args = SimpleCallArgs::new(args, keywords); let call_args = SimpleCallArgs::new(args, keywords);
if let Some(verify_arg) = call_args.keyword_argument("verify") { if let Some(verify_arg) = call_args.keyword_argument("verify") {
if let Expr::Constant(ast::ExprConstant { if let Expr::Constant(ast::ExprConstant {

View file

@ -34,7 +34,7 @@ pub(crate) fn request_without_timeout(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
HTTP_VERBS HTTP_VERBS

View file

@ -184,11 +184,11 @@ pub(crate) fn shell_injection(
args: &[Expr], args: &[Expr],
keywords: &[Keyword], 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 matches!(call_kind, Some(CallKind::Subprocess)) {
if let Some(arg) = args.first() { if let Some(arg) = args.first() {
match find_shell_keyword(&checker.model, keywords) { match find_shell_keyword(checker.semantic_model(), keywords) {
// S602 // S602
Some(ShellKeyword { Some(ShellKeyword {
truthiness: Truthiness::Truthy, truthiness: Truthiness::Truthy,
@ -241,7 +241,7 @@ pub(crate) fn shell_injection(
} else if let Some(ShellKeyword { } else if let Some(ShellKeyword {
truthiness: Truthiness::Truthy, truthiness: Truthiness::Truthy,
keyword, keyword,
}) = find_shell_keyword(&checker.model, keywords) }) = find_shell_keyword(checker.semantic_model(), keywords)
{ {
// S604 // S604
if checker if checker

View file

@ -25,7 +25,7 @@ pub(crate) fn snmp_insecure_version(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["pysnmp", "hlapi", "CommunityData"] call_path.as_slice() == ["pysnmp", "hlapi", "CommunityData"]

View file

@ -27,7 +27,7 @@ pub(crate) fn snmp_weak_cryptography(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["pysnmp", "hlapi", "UsmUserData"] call_path.as_slice() == ["pysnmp", "hlapi", "UsmUserData"]

View file

@ -470,7 +470,7 @@ pub(crate) fn suspicious_function_call(checker: &mut Checker, expr: &Expr) {
return; 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 module in SUSPICIOUS_MEMBERS {
for member in module.members { for member in module.members {
if call_path.as_slice() == *member { if call_path.as_slice() == *member {

View file

@ -27,7 +27,7 @@ pub(crate) fn try_except_continue(
) { ) {
if body.len() == 1 if body.len() == 1
&& body[0].is_continue_stmt() && 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 checker
.diagnostics .diagnostics

View file

@ -27,7 +27,7 @@ pub(crate) fn try_except_pass(
) { ) {
if body.len() == 1 if body.len() == 1
&& body[0].is_pass_stmt() && 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 checker
.diagnostics .diagnostics

View file

@ -38,14 +38,14 @@ pub(crate) fn unsafe_yaml_load(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| call_path.as_slice() == ["yaml", "load"]) .map_or(false, |call_path| call_path.as_slice() == ["yaml", "load"])
{ {
let call_args = SimpleCallArgs::new(args, keywords); let call_args = SimpleCallArgs::new(args, keywords);
if let Some(loader_arg) = call_args.argument("Loader", 1) { if let Some(loader_arg) = call_args.argument("Loader", 1) {
if !checker if !checker
.model .semantic_model()
.resolve_call_path(loader_arg) .resolve_call_path(loader_arg)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["yaml", "SafeLoader"] call_path.as_slice() == ["yaml", "SafeLoader"]

View file

@ -34,7 +34,7 @@ pub(crate) fn blind_except(
return; return;
}; };
for exception in ["BaseException", "Exception"] { 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 the exception is re-raised, don't flag an error.
if body.iter().any(|stmt| { if body.iter().any(|stmt| {
if let Stmt::Raise(ast::StmtRaise { exc, .. }) = stmt { if let Stmt::Raise(ast::StmtRaise { exc, .. }) = stmt {
@ -58,7 +58,7 @@ pub(crate) fn blind_except(
if body.iter().any(|stmt| { if body.iter().any(|stmt| {
if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt { if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt {
if let Expr::Call(ast::ExprCall { func, keywords, .. }) = value.as_ref() { 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() { if let Some(attribute) = func.as_attribute_expr() {
let attr = attribute.attr.as_str(); let attr = attribute.attr.as_str();
if attr == "exception" { if attr == "exception" {

View file

@ -79,7 +79,7 @@ pub(crate) fn abstract_base_class(
if bases.len() + keywords.len() != 1 { if bases.len() + keywords.len() != 1 {
return; return;
} }
if !is_abc_class(&checker.model, bases, keywords) { if !is_abc_class(checker.semantic_model(), bases, keywords) {
return; return;
} }
@ -108,7 +108,7 @@ pub(crate) fn abstract_base_class(
continue; 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; has_abstract_method |= has_abstract_decorator;
if !checker if !checker
@ -121,7 +121,7 @@ pub(crate) fn abstract_base_class(
if !has_abstract_decorator if !has_abstract_decorator
&& is_empty_body(body) && is_empty_body(body)
&& !is_overload(&checker.model, decorator_list) && !is_overload(checker.semantic_model(), decorator_list)
{ {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
EmptyMethodWithoutAbstractDecorator { EmptyMethodWithoutAbstractDecorator {

View file

@ -66,7 +66,7 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items:
} }
if !checker if !checker
.model .semantic_model()
.resolve_call_path(args.first().unwrap()) .resolve_call_path(args.first().unwrap())
.map_or(false, |call_path| call_path.as_slice() == ["", "Exception"]) .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 AssertionKind::AssertRaises
} else if checker } else if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["pytest", "raises"] call_path.as_slice() == ["pytest", "raises"]

View file

@ -28,7 +28,7 @@ fn is_cache_func(model: &SemanticModel, expr: &Expr) -> bool {
/// B019 /// B019
pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[Expr]) { 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; return;
} }
for decorator in decorator_list { 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 { for decorator in decorator_list {
if is_cache_func( if is_cache_func(
&checker.model, checker.semantic_model(),
match decorator { match decorator {
Expr::Call(ast::ExprCall { func, .. }) => func, Expr::Call(ast::ExprCall { func, .. }) => func,
_ => decorator, _ => decorator,

View file

@ -149,7 +149,8 @@ pub(crate) fn function_call_argument_default(checker: &mut Checker, arguments: &
.map(|target| from_qualified_name(target)) .map(|target| from_qualified_name(target))
.collect(); .collect();
let diagnostics = { 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 for expr in arguments
.defaults .defaults
.iter() .iter()

View file

@ -64,11 +64,10 @@ pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Argume
.zip(arguments.defaults.iter().rev()), .zip(arguments.defaults.iter().rev()),
) )
{ {
if is_mutable_expr(&checker.model, default) if is_mutable_expr(checker.semantic_model(), default)
&& !arg && !arg.annotation.as_ref().map_or(false, |expr| {
.annotation is_immutable_annotation(checker.semantic_model(), expr)
.as_ref() })
.map_or(false, |expr| is_immutable_annotation(&checker.model, expr))
{ {
checker checker
.diagnostics .diagnostics

View file

@ -45,7 +45,7 @@ pub(crate) fn no_explicit_stacklevel(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if !checker if !checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["warnings", "warn"] call_path.as_slice() == ["warnings", "warn"]

View file

@ -342,7 +342,7 @@ pub(crate) fn reuse_of_groupby_generator(
}; };
// Check if the function call is `itertools.groupby` // Check if the function call is `itertools.groupby`
if !checker if !checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["itertools", "groupby"] call_path.as_slice() == ["itertools", "groupby"]

View file

@ -75,7 +75,7 @@ pub(crate) fn setattr_with_constant(
if let Stmt::Expr(ast::StmtExpr { if let Stmt::Expr(ast::StmtExpr {
value: child, value: child,
range: _, range: _,
}) = &checker.model.stmt() }) = checker.semantic_model().stmt()
{ {
if expr == child.as_ref() { if expr == child.as_ref() {
let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range()); let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range());

View file

@ -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. // Avoid fixing any variables that _may_ be used, but undetectably so.
let certainty = Certainty::from(!helpers::uses_magic_variable_access(body, |id| { 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 // 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 let Some(rename) = rename {
if certainty.into() && checker.patch(diagnostic.kind.rule()) { if certainty.into() && checker.patch(diagnostic.kind.rule()) {
// Find the `BindingKind::LoopVar` corresponding to the name. // 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 = 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| { 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 { if let Some(binding) = binding {

View file

@ -27,7 +27,7 @@ pub(crate) fn useless_contextlib_suppress(
) { ) {
if args.is_empty() if args.is_empty()
&& checker && checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["contextlib", "suppress"] call_path.as_slice() == ["contextlib", "suppress"]

View file

@ -53,7 +53,7 @@ pub(crate) fn useless_expression(checker: &mut Checker, value: &Expr) {
} }
// Ignore statements that have side effects. // 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 // Flag attributes as useless expressions, even if they're attached to calls or other
// expressions. // expressions.
if matches!(value, Expr::Attribute(_)) { if matches!(value, Expr::Attribute(_)) {

View file

@ -24,7 +24,7 @@ pub(crate) fn zip_without_explicit_strict(
) { ) {
if let Expr::Name(ast::ExprName { id, .. }) = func { if let Expr::Name(ast::ExprName { id, .. }) = func {
if id == "zip" if id == "zip"
&& checker.model.is_builtin("zip") && checker.semantic_model().is_builtin("zip")
&& !kwargs && !kwargs
.iter() .iter()
.any(|keyword| keyword.arg.as_ref().map_or(false, |name| name == "strict")) .any(|keyword| keyword.arg.as_ref().map_or(false, |name| name == "strict"))

View file

@ -75,7 +75,7 @@ pub(crate) fn unnecessary_call_around_sorted(
if inner != "sorted" { if inner != "sorted" {
return; 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; return;
} }
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(

View file

@ -79,7 +79,7 @@ pub(crate) fn unnecessary_collection_call(
} }
_ => return, _ => return,
}; };
if !checker.model.is_builtin(id) { if !checker.semantic_model().is_builtin(id) {
return; return;
} }
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(

View file

@ -56,7 +56,7 @@ fn add_diagnostic(checker: &mut Checker, expr: &Expr) {
Expr::DictComp(_) => "dict", Expr::DictComp(_) => "dict",
_ => return, _ => return,
}; };
if !checker.model.is_builtin(id) { if !checker.semantic_model().is_builtin(id) {
return; return;
} }
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(

View file

@ -76,7 +76,7 @@ pub(crate) fn unnecessary_comprehension_any_all(
if is_async_generator(elt) { if is_async_generator(elt) {
return; return;
} }
if !checker.model.is_builtin(id) { if !checker.semantic_model().is_builtin(id) {
return; return;
} }
let mut diagnostic = Diagnostic::new(UnnecessaryComprehensionAnyAll, args[0].range()); let mut diagnostic = Diagnostic::new(UnnecessaryComprehensionAnyAll, args[0].range());

View file

@ -90,7 +90,7 @@ pub(crate) fn unnecessary_double_cast_or_process(
let Some(inner) = helpers::expr_name(func) else { let Some(inner) = helpers::expr_name(func) else {
return; 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; return;
} }

View file

@ -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 { let Some(argument) = helpers::exactly_one_argument_with_matching_function("list", func, args, keywords) else {
return; return;
}; };
if !checker.model.is_builtin("list") { if !checker.semantic_model().is_builtin("list") {
return; return;
} }
if let Expr::GeneratorExp(_) = argument { if let Expr::GeneratorExp(_) = argument {

View file

@ -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 { let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
return; return;
}; };
if !checker.model.is_builtin("set") { if !checker.semantic_model().is_builtin("set") {
return; return;
} }
if let Expr::GeneratorExp(_) = argument { if let Expr::GeneratorExp(_) = argument {

View file

@ -48,7 +48,7 @@ pub(crate) fn unnecessary_list_call(
let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else { let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else {
return; return;
}; };
if !checker.model.is_builtin("list") { if !checker.semantic_model().is_builtin("list") {
return; return;
} }
if !argument.is_list_comp_expr() { if !argument.is_list_comp_expr() {

View file

@ -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 { let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
return; return;
}; };
if !checker.model.is_builtin("dict") { if !checker.semantic_model().is_builtin("dict") {
return; return;
} }
let Expr::ListComp(ast::ExprListComp { elt, .. }) = argument else { let Expr::ListComp(ast::ExprListComp { elt, .. }) = argument else {

View file

@ -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 { let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
return; return;
}; };
if !checker.model.is_builtin("set") { if !checker.semantic_model().is_builtin("set") {
return; return;
} }
if argument.is_list_comp_expr() { if argument.is_list_comp_expr() {

View file

@ -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 { let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
return; return;
}; };
if !checker.model.is_builtin("dict") { if !checker.semantic_model().is_builtin("dict") {
return; return;
} }
let (kind, elts) = match argument { let (kind, elts) = match argument {

View file

@ -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 { let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
return; return;
}; };
if !checker.model.is_builtin("set") { if !checker.semantic_model().is_builtin("set") {
return; return;
} }
let kind = match argument { let kind = match argument {

View file

@ -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 { let Some(argument) = helpers::first_argument_with_matching_function("dict", func, args) else {
return; return;
}; };
if !checker.model.is_builtin("dict") { if !checker.semantic_model().is_builtin("dict") {
return; return;
} }
let argument_kind = match argument { let argument_kind = match argument {

View file

@ -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 { let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else {
return; return;
}; };
if !checker.model.is_builtin("list") { if !checker.semantic_model().is_builtin("list") {
return; return;
} }
let argument_kind = match argument { let argument_kind = match argument {

View file

@ -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 { let Some(argument) = helpers::first_argument_with_matching_function("tuple", func, args) else {
return; return;
}; };
if !checker.model.is_builtin("tuple") { if !checker.semantic_model().is_builtin("tuple") {
return; return;
} }
let argument_kind = match argument { let argument_kind = match argument {

View file

@ -88,7 +88,7 @@ pub(crate) fn unnecessary_map(
}; };
match id { match id {
"map" => { "map" => {
if !checker.model.is_builtin(id) { if !checker.semantic_model().is_builtin(id) {
return; return;
} }
@ -119,7 +119,7 @@ pub(crate) fn unnecessary_map(
} }
} }
"list" | "set" => { "list" | "set" => {
if !checker.model.is_builtin(id) { if !checker.semantic_model().is_builtin(id) {
return; return;
} }
@ -149,7 +149,7 @@ pub(crate) fn unnecessary_map(
} }
} }
"dict" => { "dict" => {
if !checker.model.is_builtin(id) { if !checker.semantic_model().is_builtin(id) {
return; return;
} }

View file

@ -58,7 +58,7 @@ pub(crate) fn unnecessary_subscript_reversal(
if !(id == "set" || id == "sorted" || id == "reversed") { if !(id == "set" || id == "sorted" || id == "reversed") {
return; return;
} }
if !checker.model.is_builtin(id) { if !checker.semantic_model().is_builtin(id) {
return; return;
} }
let Expr::Subscript(ast::ExprSubscript { slice, .. }) = first_arg else { let Expr::Subscript(ast::ExprSubscript { slice, .. }) = first_arg else {

View file

@ -125,7 +125,7 @@ pub(crate) fn call_datetime_without_tzinfo(
location: TextRange, location: TextRange,
) { ) {
if !checker if !checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime"] call_path.as_slice() == ["datetime", "datetime"]
@ -158,7 +158,7 @@ pub(crate) fn call_datetime_without_tzinfo(
/// Use `datetime.datetime.now(tz=)` instead. /// Use `datetime.datetime.now(tz=)` instead.
pub(crate) fn call_datetime_today(checker: &mut Checker, func: &Expr, location: TextRange) { pub(crate) fn call_datetime_today(checker: &mut Checker, func: &Expr, location: TextRange) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "today"] 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)`. /// current time in UTC is by calling `datetime.now(timezone.utc)`.
pub(crate) fn call_datetime_utcnow(checker: &mut Checker, func: &Expr, location: TextRange) { pub(crate) fn call_datetime_utcnow(checker: &mut Checker, func: &Expr, location: TextRange) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "utcnow"] call_path.as_slice() == ["datetime", "datetime", "utcnow"]
@ -207,7 +207,7 @@ pub(crate) fn call_datetime_utcfromtimestamp(
location: TextRange, location: TextRange,
) { ) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "utcfromtimestamp"] call_path.as_slice() == ["datetime", "datetime", "utcfromtimestamp"]
@ -228,7 +228,7 @@ pub(crate) fn call_datetime_now_without_tzinfo(
location: TextRange, location: TextRange,
) { ) {
if !checker if !checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "now"] call_path.as_slice() == ["datetime", "datetime", "now"]
@ -270,7 +270,7 @@ pub(crate) fn call_datetime_fromtimestamp(
location: TextRange, location: TextRange,
) { ) {
if !checker if !checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "fromtimestamp"] call_path.as_slice() == ["datetime", "datetime", "fromtimestamp"]
@ -311,7 +311,7 @@ pub(crate) fn call_datetime_strptime_without_zone(
location: TextRange, location: TextRange,
) { ) {
if !checker if !checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "strptime"] 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( checker.diagnostics.push(Diagnostic::new(
CallDatetimeStrptimeWithoutZone, CallDatetimeStrptimeWithoutZone,
location, location,
@ -370,7 +370,7 @@ pub(crate) fn call_datetime_strptime_without_zone(
/// Use `datetime.datetime.now(tz=).date()` instead. /// Use `datetime.datetime.now(tz=).date()` instead.
pub(crate) fn call_date_today(checker: &mut Checker, func: &Expr, location: TextRange) { pub(crate) fn call_date_today(checker: &mut Checker, func: &Expr, location: TextRange) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "date", "today"] 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. /// Use `datetime.datetime.fromtimestamp(, tz=).date()` instead.
pub(crate) fn call_date_fromtimestamp(checker: &mut Checker, func: &Expr, location: TextRange) { pub(crate) fn call_date_fromtimestamp(checker: &mut Checker, func: &Expr, location: TextRange) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "date", "fromtimestamp"] call_path.as_slice() == ["datetime", "date", "fromtimestamp"]

View file

@ -43,11 +43,15 @@ const DEBUGGERS: &[&[&str]] = &[
/// Checks for the presence of a debugger call. /// Checks for the presence of a debugger call.
pub(crate) fn debugger_call(checker: &mut Checker, expr: &Expr, func: &Expr) { 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| { if let Some(target) = checker
.semantic_model()
.resolve_call_path(func)
.and_then(|call_path| {
DEBUGGERS DEBUGGERS
.iter() .iter()
.find(|target| call_path.as_slice() == **target) .find(|target| call_path.as_slice() == **target)
}) { })
{
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
Debugger { Debugger {
using_type: DebuggerUsingType::Call(format_call_path(target)), using_type: DebuggerUsingType::Call(format_call_path(target)),

View file

@ -52,7 +52,10 @@ pub(crate) fn all_with_model_form(
bases: &[Expr], bases: &[Expr],
body: &[Stmt], body: &[Stmt],
) -> Option<Diagnostic> { ) -> Option<Diagnostic> {
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; return None;
} }
for element in body.iter() { for element in body.iter() {

View file

@ -50,7 +50,10 @@ pub(crate) fn exclude_with_model_form(
bases: &[Expr], bases: &[Expr],
body: &[Stmt], body: &[Stmt],
) -> Option<Diagnostic> { ) -> Option<Diagnostic> {
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; return None;
} }
for element in body.iter() { for element in body.iter() {

View file

@ -51,7 +51,7 @@ pub(crate) fn locals_in_render_function(
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if !checker if !checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["django", "shortcuts", "render"] call_path.as_slice() == ["django", "shortcuts", "render"]
@ -61,7 +61,7 @@ pub(crate) fn locals_in_render_function(
} }
let locals = if args.len() >= 3 { let locals = if args.len() >= 3 {
if !is_locals_call(&checker.model, &args[2]) { if !is_locals_call(checker.semantic_model(), &args[2]) {
return; return;
} }
&args[2] &args[2]
@ -69,7 +69,7 @@ pub(crate) fn locals_in_render_function(
.iter() .iter()
.find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "context")) .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; return;
} }
&keyword.value &keyword.value

View file

@ -56,7 +56,7 @@ pub(crate) fn model_without_dunder_str(
body: &[Stmt], body: &[Stmt],
class_location: &Stmt, class_location: &Stmt,
) -> Option<Diagnostic> { ) -> Option<Diagnostic> {
if !checker_applies(&checker.model, bases, body) { if !checker_applies(checker.semantic_model(), bases, body) {
return None; return None;
} }
if !has_dunder_method(body) { if !has_dunder_method(body) {

View file

@ -84,7 +84,7 @@ fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a st
return None; 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; return None;
}; };

View file

@ -145,13 +145,13 @@ pub(crate) fn unordered_body_content_in_model(
) { ) {
if !bases if !bases
.iter() .iter()
.any(|base| helpers::is_model(&checker.model, base)) .any(|base| helpers::is_model(checker.semantic_model(), base))
{ {
return; return;
} }
let mut elements_type_found = Vec::new(); let mut elements_type_found = Vec::new();
for element in body.iter() { 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; continue;
}; };
let Some(&element_type) = elements_type_found let Some(&element_type) = elements_type_found

View file

@ -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 { if string.len() > checker.settings.flake8_errmsg.max_string_length {
let indentation = whitespace::indentation(checker.locator, stmt) let indentation = whitespace::indentation(checker.locator, stmt)
.and_then(|indentation| { .and_then(|indentation| {
if checker.model.find_binding("msg").is_none() { if checker.semantic_model().find_binding("msg").is_none() {
Some(indentation) Some(indentation)
} else { } else {
None 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) { if checker.settings.rules.enabled(Rule::FStringInException) {
let indentation = whitespace::indentation(checker.locator, stmt).and_then( let indentation = whitespace::indentation(checker.locator, stmt).and_then(
|indentation| { |indentation| {
if checker.model.find_binding("msg").is_none() { if checker.semantic_model().find_binding("msg").is_none() {
Some(indentation) Some(indentation)
} else { } else {
None 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() { if attr == "format" && value.is_constant_expr() {
let indentation = whitespace::indentation(checker.locator, stmt) let indentation = whitespace::indentation(checker.locator, stmt)
.and_then(|indentation| { .and_then(|indentation| {
if checker.model.find_binding("msg").is_none() { if checker.semantic_model().find_binding("msg").is_none() {
Some(indentation) Some(indentation)
} else { } else {
None None

View file

@ -67,11 +67,14 @@ impl Violation for MissingFutureAnnotationsImport {
/// FA100 /// FA100
pub(crate) fn missing_future_annotations(checker: &mut Checker, expr: &Expr) { 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( checker.diagnostics.push(Diagnostic::new(
MissingFutureAnnotationsImport { MissingFutureAnnotationsImport { name },
name: format_call_path(&binding),
},
expr.range(), expr.range(),
)); ));
} }

View file

@ -106,7 +106,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
} }
Expr::Call(ast::ExprCall { func, keywords, .. }) => { Expr::Call(ast::ExprCall { func, keywords, .. }) => {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| call_path.as_slice() == ["", "dict"]) .map_or(false, |call_path| call_path.as_slice() == ["", "dict"])
{ {
@ -151,7 +151,7 @@ pub(crate) fn logging_call(
args: &[Expr], args: &[Expr],
keywords: &[Keyword], keywords: &[Keyword],
) { ) {
if !logging::is_logger_candidate(func, &checker.model) { if !logging::is_logger_candidate(func, checker.semantic_model()) {
return; return;
} }
@ -198,7 +198,7 @@ pub(crate) fn logging_call(
.rules .rules
.enabled(Rule::LoggingRedundantExcInfo) .enabled(Rule::LoggingRedundantExcInfo)
{ {
if !checker.model.in_exception_handler() { if !checker.semantic_model().in_exception_handler() {
return; return;
} }
if let Some(exc_info) = find_keyword(keywords, "exc_info") { 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 { ) || if let Expr::Call(ast::ExprCall { func, .. }) = &exc_info.value {
checker checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["sys", "exc_info"] call_path.as_slice() == ["sys", "exc_info"]

View file

@ -417,7 +417,7 @@ pub(crate) fn non_unique_enums<'a, 'b>(
if !bases.iter().any(|expr| { if !bases.iter().any(|expr| {
checker checker
.model .semantic_model()
.resolve_call_path(expr) .resolve_call_path(expr)
.map_or(false, |call_path| call_path.as_slice() == ["enum", "Enum"]) .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 let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| call_path.as_slice() == ["enum", "auto"]) .map_or(false, |call_path| call_path.as_slice() == ["enum", "auto"])
{ {

View file

@ -78,7 +78,7 @@ impl Violation for PPrint {
/// T201, T203 /// T201, T203
pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) { pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) {
let diagnostic = { let diagnostic = {
let call_path = checker.model.resolve_call_path(func); let call_path = checker.semantic_model().resolve_call_path(func);
if call_path if call_path
.as_ref() .as_ref()
.map_or(false, |call_path| *call_path.as_slice() == ["", "print"]) .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 !is_const_none(&keyword.value) {
if checker if checker
.model .semantic_model()
.resolve_call_path(&keyword.value) .resolve_call_path(&keyword.value)
.map_or(true, |call_path| { .map_or(true, |call_path| {
call_path.as_slice() != ["sys", "stdout"] call_path.as_slice() != ["sys", "stdout"]

View file

@ -69,7 +69,7 @@ pub(crate) fn bad_version_info_comparison(
}; };
if !checker if !checker
.model .semantic_model()
.resolve_call_path(left) .resolve_call_path(left)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["sys", "version_info"] call_path.as_slice() == ["sys", "version_info"]

View file

@ -70,12 +70,12 @@ pub(crate) fn prefix_type_params(checker: &mut Checker, value: &Expr, targets: &
}; };
if let Expr::Call(ast::ExprCall { func, .. }) = value { if let Expr::Call(ast::ExprCall { func, .. }) = value {
let Some(kind) = checker.model.resolve_call_path(func).and_then(|call_path| { let Some(kind) = checker.semantic_model().resolve_call_path(func).and_then(|call_path| {
if checker.model.match_typing_call_path(&call_path, "ParamSpec") { if checker.semantic_model().match_typing_call_path(&call_path, "ParamSpec") {
Some(VarKind::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) 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) Some(VarKind::TypeVarTuple)
} else { } else {
None None

View file

@ -330,7 +330,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum
default, default,
true, true,
checker.locator, checker.locator,
&checker.model, checker.semantic_model(),
) { ) {
let mut diagnostic = let mut diagnostic =
Diagnostic::new(TypedArgumentDefaultInStub, default.range()); Diagnostic::new(TypedArgumentDefaultInStub, default.range());
@ -362,7 +362,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum
default, default,
true, true,
checker.locator, checker.locator,
&checker.model, checker.semantic_model(),
) { ) {
let mut diagnostic = let mut diagnostic =
Diagnostic::new(TypedArgumentDefaultInStub, default.range()); Diagnostic::new(TypedArgumentDefaultInStub, default.range());
@ -397,7 +397,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments)
default, default,
true, true,
checker.locator, checker.locator,
&checker.model, checker.semantic_model(),
) { ) {
let mut diagnostic = let mut diagnostic =
Diagnostic::new(ArgumentDefaultInStub, default.range()); Diagnostic::new(ArgumentDefaultInStub, default.range());
@ -429,7 +429,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments)
default, default,
true, true,
checker.locator, checker.locator,
&checker.model, checker.semantic_model(),
) { ) {
let mut diagnostic = let mut diagnostic =
Diagnostic::new(ArgumentDefaultInStub, default.range()); 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() { if !target.is_name_expr() {
return; return;
} }
if is_special_assignment(&checker.model, target) { if is_special_assignment(checker.semantic_model(), target) {
return; return;
} }
if is_type_var_like_call(&checker.model, value) { if is_type_var_like_call(checker.semantic_model(), value) {
return; return;
} }
if is_valid_default_value_without_annotation(value) { if is_valid_default_value_without_annotation(value) {
return; 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; return;
} }
@ -490,16 +495,24 @@ pub(crate) fn annotated_assignment_default_in_stub(
value: &Expr, value: &Expr,
annotation: &Expr, annotation: &Expr,
) { ) {
if checker.model.match_typing_expr(annotation, "TypeAlias") { if checker
.semantic_model()
.match_typing_expr(annotation, "TypeAlias")
{
return; return;
} }
if is_special_assignment(&checker.model, target) { if is_special_assignment(checker.semantic_model(), target) {
return; return;
} }
if is_type_var_like_call(&checker.model, value) { if is_type_var_like_call(checker.semantic_model(), value) {
return; 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; return;
} }
@ -527,21 +540,26 @@ pub(crate) fn unannotated_assignment_in_stub(
let Expr::Name(ast::ExprName { id, .. }) = target else { let Expr::Name(ast::ExprName { id, .. }) = target else {
return; return;
}; };
if is_special_assignment(&checker.model, target) { if is_special_assignment(checker.semantic_model(), target) {
return; return;
} }
if is_type_var_like_call(&checker.model, value) { if is_type_var_like_call(checker.semantic_model(), value) {
return; return;
} }
if is_valid_default_value_without_annotation(value) { if is_valid_default_value_without_annotation(value) {
return; 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; return;
} }
if let ScopeKind::Class(ClassDef { bases, .. }) = &checker.model.scope().kind { if let ScopeKind::Class(ClassDef { bases, .. }) = checker.semantic_model().scope().kind {
if is_enum(&checker.model, bases) { if is_enum(checker.semantic_model(), bases) {
return; return;
} }
} }

View file

@ -103,7 +103,7 @@ pub(crate) fn unrecognized_platform(
let diagnostic_unrecognized_platform_check = let diagnostic_unrecognized_platform_check =
Diagnostic::new(UnrecognizedPlatformCheck, expr.range()); Diagnostic::new(UnrecognizedPlatformCheck, expr.range());
if !checker if !checker
.model .semantic_model()
.resolve_call_path(left) .resolve_call_path(left)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["sys", "platform"] call_path.as_slice() == ["sys", "platform"]

View file

@ -185,9 +185,9 @@ pub(crate) fn unittest_assertion(
if let Ok(unittest_assert) = UnittestAssert::try_from(attr.as_str()) { 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 // We're converting an expression to a statement, so avoid applying the fix if
// the assertion is part of a larger expression. // the assertion is part of a larger expression.
let fixable = checker.model.stmt().is_expr_stmt() let fixable = checker.semantic_model().stmt().is_expr_stmt()
&& checker.model.expr_parent().is_none() && checker.semantic_model().expr_parent().is_none()
&& !checker.model.scope().kind.is_lambda() && !checker.semantic_model().scope().kind.is_lambda()
&& !has_comments_in(expr.range(), checker.locator); && !has_comments_in(expr.range(), checker.locator);
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
PytestUnittestAssertion { PytestUnittestAssertion {
@ -215,7 +215,7 @@ pub(crate) fn unittest_assertion(
/// PT015 /// PT015
pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) { 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 checker
.diagnostics .diagnostics
.push(Diagnostic::new(PytestAssertAlwaysFalse, stmt.range())); .push(Diagnostic::new(PytestAssertAlwaysFalse, stmt.range()));

View file

@ -19,7 +19,7 @@ impl Violation for PytestFailWithoutMessage {
} }
pub(crate) fn fail_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) { 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 call_args = SimpleCallArgs::new(args, keywords);
let msg = call_args.argument("msg", 0); let msg = call_args.argument("msg", 0);

View file

@ -457,7 +457,7 @@ fn check_test_function_args(checker: &mut Checker, args: &Arguments) {
/// PT020 /// PT020
fn check_fixture_decorator_name(checker: &mut Checker, decorator: &Expr) { 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( checker.diagnostics.push(Diagnostic::new(
PytestDeprecatedYieldFixture, PytestDeprecatedYieldFixture,
decorator.range(), decorator.range(),
@ -533,7 +533,7 @@ pub(crate) fn fixture(
decorators: &[Expr], decorators: &[Expr],
body: &[Stmt], 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 let Some(decorator) = decorator {
if checker if checker
.settings .settings
@ -572,7 +572,7 @@ pub(crate) fn fixture(
.settings .settings
.rules .rules
.enabled(Rule::PytestUselessYieldFixture)) .enabled(Rule::PytestUselessYieldFixture))
&& !is_abstract(&checker.model, decorators) && !is_abstract(checker.semantic_model(), decorators)
{ {
check_fixture_returns(checker, stmt, name, body); check_fixture_returns(checker, stmt, name, body);
} }

View file

@ -419,7 +419,7 @@ fn handle_value_rows(
pub(crate) fn parametrize(checker: &mut Checker, decorators: &[Expr]) { pub(crate) fn parametrize(checker: &mut Checker, decorators: &[Expr]) {
for decorator in decorators { 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 let Expr::Call(ast::ExprCall { args, .. }) = decorator {
if checker if checker
.settings .settings

View file

@ -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]) { 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 if checker
.settings .settings
.rules .rules
@ -104,7 +104,7 @@ pub(crate) fn complex_raises(
let mut is_too_complex = false; let mut is_too_complex = false;
let raises_called = items.iter().any(|item| match &item.context_expr { 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, _ => false,
}); });
@ -145,7 +145,7 @@ pub(crate) fn complex_raises(
/// PT011 /// PT011
fn exception_needs_match(checker: &mut Checker, exception: &Expr) { fn exception_needs_match(checker: &mut Checker, exception: &Expr) {
if let Some(call_path) = checker if let Some(call_path) = checker
.model .semantic_model()
.resolve_call_path(exception) .resolve_call_path(exception)
.and_then(|call_path| { .and_then(|call_path| {
let is_broad_exception = checker let is_broad_exception = checker

View file

@ -484,7 +484,7 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) {
if matches!( if matches!(
value.as_ref(), value.as_ref(),
Expr::Call(ast::ExprCall { func, .. }) 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()); let mut diagnostic = Diagnostic::new(ImplicitReturn, stmt.range());

View file

@ -94,7 +94,7 @@ pub(crate) fn private_member_access(checker: &mut Checker, expr: &Expr) {
// Ignore accesses on class members from _within_ the class. // Ignore accesses on class members from _within_ the class.
if checker if checker
.model .semantic_model()
.scopes .scopes
.iter() .iter()
.rev() .rev()
@ -104,14 +104,14 @@ pub(crate) fn private_member_access(checker: &mut Checker, expr: &Expr) {
}) })
.map_or(false, |class_def| { .map_or(false, |class_def| {
if call_path.as_slice() == [class_def.name] { if call_path.as_slice() == [class_def.name] {
checker.model.find_binding(class_def.name).map_or( checker
false, .semantic_model()
|binding| { .find_binding(class_def.name)
.map_or(false, |binding| {
// TODO(charlie): Could the name ever be bound to a // TODO(charlie): Could the name ever be bound to a
// _different_ class here? // _different_ class here?
binding.kind.is_class_definition() binding.kind.is_class_definition()
}, })
)
} else { } else {
false false
} }

View file

@ -271,7 +271,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
if func_name != "isinstance" { if func_name != "isinstance" {
continue; continue;
} }
if !checker.model.is_builtin("isinstance") { if !checker.semantic_model().is_builtin("isinstance") {
continue; continue;
} }
@ -293,7 +293,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &mut Checker, expr: &Expr) {
} else { } else {
unreachable!("Indices should only contain `isinstance` calls") 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( let mut diagnostic = Diagnostic::new(
DuplicateIsinstanceCall { DuplicateIsinstanceCall {
name: if let Expr::Name(ast::ExprName { id, .. }) = target { 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()`. // Avoid rewriting (e.g.) `a == "foo" or a == f()`.
if comparators if comparators
.iter() .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; continue;
} }
@ -516,7 +516,7 @@ pub(crate) fn expr_and_not_expr(checker: &mut Checker, expr: &Expr) {
return; return;
} }
if contains_effect(expr, |id| checker.model.is_builtin(id)) { if contains_effect(expr, |id| checker.semantic_model().is_builtin(id)) {
return; return;
} }
@ -571,7 +571,7 @@ pub(crate) fn expr_or_not_expr(checker: &mut Checker, expr: &Expr) {
return; return;
} }
if contains_effect(expr, |id| checker.model.is_builtin(id)) { if contains_effect(expr, |id| checker.semantic_model().is_builtin(id)) {
return; return;
} }
@ -640,14 +640,15 @@ fn is_short_circuit(
for (index, (value, next_value)) in values.iter().tuple_windows().enumerate() { for (index, (value, next_value)) in values.iter().tuple_windows().enumerate() {
// Keep track of the location of the furthest-right, truthy or falsey expression. // 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 = 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. // Keep track of the location of the furthest-right, non-effectful expression.
if value_truthiness.is_unknown() if value_truthiness.is_unknown()
&& (!checker.model.in_boolean_test() && (!checker.semantic_model().in_boolean_test()
|| contains_effect(value, |id| checker.model.is_builtin(id))) || contains_effect(value, |id| checker.semantic_model().is_builtin(id)))
{ {
location = next_value.start(); location = next_value.start();
continue; continue;
@ -667,7 +668,7 @@ fn is_short_circuit(
value, value,
TextRange::new(location, expr.end()), TextRange::new(location, expr.end()),
short_circuit_truthiness, short_circuit_truthiness,
checker.model.in_boolean_test(), checker.semantic_model().in_boolean_test(),
checker, checker,
)); ));
break; break;
@ -685,7 +686,7 @@ fn is_short_circuit(
next_value, next_value,
TextRange::new(location, expr.end()), TextRange::new(location, expr.end()),
short_circuit_truthiness, short_circuit_truthiness,
checker.model.in_boolean_test(), checker.semantic_model().in_boolean_test(),
checker, checker,
)); ));
break; break;

View file

@ -87,7 +87,7 @@ pub(crate) fn use_capital_environment_variables(checker: &mut Checker, expr: &Ex
return; return;
}; };
if !checker if !checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
call_path.as_slice() == ["os", "environ", "get"] call_path.as_slice() == ["os", "environ", "get"]

View file

@ -351,7 +351,7 @@ pub(crate) fn needless_bool(checker: &mut Checker, stmt: &Stmt) {
let fixable = matches!(if_return, Bool::True) let fixable = matches!(if_return, Bool::True)
&& matches!(else_return, Bool::False) && matches!(else_return, Bool::False)
&& !has_comments(stmt, checker.locator) && !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()); let mut diagnostic = Diagnostic::new(NeedlessBool { condition }, stmt.range());
if fixable && checker.patch(diagnostic.kind.rule()) { 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. // 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; return;
} }
// Avoid suggesting ternary for `if sys.platform.startswith("...")`-style // Avoid suggesting ternary for `if sys.platform.startswith("...")`-style
// checks. // checks.
if contains_call_path(&checker.model, test, &["sys", "platform"]) { if contains_call_path(checker.semantic_model(), test, &["sys", "platform"]) {
return; return;
} }
@ -648,7 +648,7 @@ pub(crate) fn manual_dict_lookup(
return; return;
}; };
if value.as_ref().map_or(false, |value| { 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; return;
} }
@ -721,7 +721,7 @@ pub(crate) fn manual_dict_lookup(
return; return;
}; };
if value.as_ref().map_or(false, |value| { 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; return;
}; };
@ -804,7 +804,7 @@ pub(crate) fn use_dict_get_with_default(
} }
// Check that the default value is not "complex". // 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; return;
} }

View file

@ -107,7 +107,7 @@ pub(crate) fn explicit_true_false_in_ifexpr(
checker.generator().expr(&test.clone()), checker.generator().expr(&test.clone()),
expr.range(), expr.range(),
))); )));
} else if checker.model.is_builtin("bool") { } else if checker.semantic_model().is_builtin("bool") {
let node = ast::ExprName { let node = ast::ExprName {
id: "bool".into(), id: "bool".into(),
ctx: ExprContext::Load, ctx: ExprContext::Load,

View file

@ -93,12 +93,12 @@ pub(crate) fn negation_with_equal_op(
if !matches!(&ops[..], [Cmpop::Eq]) { if !matches!(&ops[..], [Cmpop::Eq]) {
return; return;
} }
if is_exception_check(checker.model.stmt()) { if is_exception_check(checker.semantic_model().stmt()) {
return; return;
} }
// Avoid flagging issues in dunder implementations. // 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) { if DUNDER_METHODS.contains(&def.name) {
return; return;
} }
@ -143,12 +143,12 @@ pub(crate) fn negation_with_not_equal_op(
if !matches!(&ops[..], [Cmpop::NotEq]) { if !matches!(&ops[..], [Cmpop::NotEq]) {
return; return;
} }
if is_exception_check(checker.model.stmt()) { if is_exception_check(checker.semantic_model().stmt()) {
return; return;
} }
// Avoid flagging issues in dunder implementations. // 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) { if DUNDER_METHODS.contains(&def.name) {
return; return;
} }
@ -196,13 +196,13 @@ pub(crate) fn double_negation(checker: &mut Checker, expr: &Expr, op: Unaryop, o
expr.range(), expr.range(),
); );
if checker.patch(diagnostic.kind.rule()) { if checker.patch(diagnostic.kind.rule()) {
if checker.model.in_boolean_test() { if checker.semantic_model().in_boolean_test() {
#[allow(deprecated)] #[allow(deprecated)]
diagnostic.set_fix(Fix::unspecified(Edit::range_replacement( diagnostic.set_fix(Fix::unspecified(Edit::range_replacement(
checker.generator().expr(operand), checker.generator().expr(operand),
expr.range(), expr.range(),
))); )));
} else if checker.model.is_builtin("bool") { } else if checker.semantic_model().is_builtin("bool") {
let node = ast::ExprName { let node = ast::ExprName {
id: "bool".into(), id: "bool".into(),
ctx: ExprContext::Load, ctx: ExprContext::Load,

View file

@ -108,23 +108,23 @@ fn match_exit_stack(model: &SemanticModel) -> bool {
/// SIM115 /// SIM115
pub(crate) fn open_file_with_context_handler(checker: &mut Checker, func: &Expr) { pub(crate) fn open_file_with_context_handler(checker: &mut Checker, func: &Expr) {
if checker if checker
.model .semantic_model()
.resolve_call_path(func) .resolve_call_path(func)
.map_or(false, |call_path| call_path.as_slice() == ["", "open"]) .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: ...` // Ex) `with open("foo.txt") as f: ...`
if matches!(checker.model.stmt(), Stmt::With(_)) { if matches!(checker.semantic_model().stmt(), Stmt::With(_)) {
return; return;
} }
// Ex) `with contextlib.ExitStack() as exit_stack: ...` // Ex) `with contextlib.ExitStack() as exit_stack: ...`
if match_exit_stack(&checker.model) { if match_exit_stack(checker.semantic_model()) {
return; return;
} }
// Ex) `with contextlib.AsyncExitStack() as exit_stack: ...` // Ex) `with contextlib.AsyncExitStack() as exit_stack: ...`
if match_async_exit_stack(&checker.model) { if match_async_exit_stack(checker.semantic_model()) {
return; return;
} }

View file

@ -237,7 +237,9 @@ pub(crate) fn convert_for_loop_to_any_all(
}, },
TextRange::new(stmt.start(), loop_info.terminal), 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)] #[allow(deprecated)]
diagnostic.set_fix(Fix::unspecified(Edit::replacement( diagnostic.set_fix(Fix::unspecified(Edit::replacement(
contents, contents,
@ -327,7 +329,9 @@ pub(crate) fn convert_for_loop_to_any_all(
}, },
TextRange::new(stmt.start(), loop_info.terminal), 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)] #[allow(deprecated)]
diagnostic.set_fix(Fix::unspecified(Edit::replacement( diagnostic.set_fix(Fix::unspecified(Edit::replacement(
contents, contents,

View file

@ -93,7 +93,7 @@ pub(crate) fn suppressible_exception(
"contextlib", "contextlib",
"suppress", "suppress",
stmt.start(), stmt.start(),
&checker.model, checker.semantic_model(),
&checker.importer, &checker.importer,
checker.locator, checker.locator,
)?; )?;

View file

@ -96,11 +96,16 @@ where
/// TID251 /// TID251
pub(crate) fn banned_attribute_access(checker: &mut Checker, expr: &Expr) { pub(crate) fn banned_attribute_access(checker: &mut Checker, expr: &Expr) {
let banned_api = &checker.settings.flake8_tidy_imports.banned_api; 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| { if let Some((banned_path, ban)) =
checker
.semantic_model()
.resolve_call_path(expr)
.and_then(|call_path| {
banned_api banned_api
.iter() .iter()
.find(|(banned_path, ..)| call_path == from_qualified_name(banned_path)) .find(|(banned_path, ..)| call_path == from_qualified_name(banned_path))
}) { })
{
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
BannedApi { BannedApi {
name: banned_path.to_string(), name: banned_path.to_string(),

View file

@ -60,7 +60,7 @@ pub(crate) fn empty_type_checking_block<'a, 'b>(
// Delete the entire type-checking block. // Delete the entire type-checking block.
if checker.patch(diagnostic.kind.rule()) { 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(); let deleted: Vec<&Stmt> = checker.deletions.iter().map(Into::into).collect();
match delete_stmt( match delete_stmt(
stmt, stmt,

View file

@ -289,7 +289,7 @@ pub(crate) fn unused_arguments(
.. ..
}) => { }) => {
match function_type::classify( match function_type::classify(
&checker.model, checker.semantic_model(),
parent, parent,
name, name,
decorator_list, decorator_list,
@ -301,7 +301,7 @@ pub(crate) fn unused_arguments(
.settings .settings
.rules .rules
.enabled(Argumentable::Function.rule_code()) .enabled(Argumentable::Function.rule_code())
&& !visibility::is_overload(&checker.model, decorator_list) && !visibility::is_overload(checker.semantic_model(), decorator_list)
{ {
function( function(
Argumentable::Function, Argumentable::Function,
@ -328,9 +328,9 @@ pub(crate) fn unused_arguments(
|| visibility::is_init(name) || visibility::is_init(name)
|| visibility::is_new(name) || visibility::is_new(name)
|| visibility::is_call(name)) || visibility::is_call(name))
&& !visibility::is_abstract(&checker.model, decorator_list) && !visibility::is_abstract(checker.semantic_model(), decorator_list)
&& !visibility::is_override(&checker.model, decorator_list) && !visibility::is_override(checker.semantic_model(), decorator_list)
&& !visibility::is_overload(&checker.model, decorator_list) && !visibility::is_overload(checker.semantic_model(), decorator_list)
{ {
method( method(
Argumentable::Method, Argumentable::Method,
@ -357,9 +357,9 @@ pub(crate) fn unused_arguments(
|| visibility::is_init(name) || visibility::is_init(name)
|| visibility::is_new(name) || visibility::is_new(name)
|| visibility::is_call(name)) || visibility::is_call(name))
&& !visibility::is_abstract(&checker.model, decorator_list) && !visibility::is_abstract(checker.semantic_model(), decorator_list)
&& !visibility::is_override(&checker.model, decorator_list) && !visibility::is_override(checker.semantic_model(), decorator_list)
&& !visibility::is_overload(&checker.model, decorator_list) && !visibility::is_overload(checker.semantic_model(), decorator_list)
{ {
method( method(
Argumentable::ClassMethod, Argumentable::ClassMethod,
@ -386,9 +386,9 @@ pub(crate) fn unused_arguments(
|| visibility::is_init(name) || visibility::is_init(name)
|| visibility::is_new(name) || visibility::is_new(name)
|| visibility::is_call(name)) || visibility::is_call(name))
&& !visibility::is_abstract(&checker.model, decorator_list) && !visibility::is_abstract(checker.semantic_model(), decorator_list)
&& !visibility::is_override(&checker.model, decorator_list) && !visibility::is_override(checker.semantic_model(), decorator_list)
&& !visibility::is_overload(&checker.model, decorator_list) && !visibility::is_overload(checker.semantic_model(), decorator_list)
{ {
function( function(
Argumentable::StaticMethod, Argumentable::StaticMethod,

View file

@ -15,7 +15,7 @@ use crate::settings::types::PythonVersion;
pub(crate) fn replaceable_by_pathlib(checker: &mut Checker, expr: &Expr) { pub(crate) fn replaceable_by_pathlib(checker: &mut Checker, expr: &Expr) {
if let Some(diagnostic_kind) = if let Some(diagnostic_kind) =
checker checker
.model .semantic_model()
.resolve_call_path(expr) .resolve_call_path(expr)
.and_then(|call_path| match call_path.as_slice() { .and_then(|call_path| match call_path.as_slice() {
["os", "path", "abspath"] => Some(OsPathAbspath.into()), ["os", "path", "abspath"] => Some(OsPathAbspath.into()),

View file

@ -48,7 +48,11 @@ impl AlwaysAutofixableViolation for NumpyDeprecatedTypeAlias {
/// NPY001 /// NPY001
pub(crate) fn deprecated_type_alias(checker: &mut Checker, expr: &Expr) { 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 let Some(type_name) =
checker
.semantic_model()
.resolve_call_path(expr)
.and_then(|call_path| {
if call_path.as_slice() == ["numpy", "bool"] if call_path.as_slice() == ["numpy", "bool"]
|| call_path.as_slice() == ["numpy", "int"] || call_path.as_slice() == ["numpy", "int"]
|| call_path.as_slice() == ["numpy", "float"] || call_path.as_slice() == ["numpy", "float"]
@ -62,7 +66,8 @@ pub(crate) fn deprecated_type_alias(checker: &mut Checker, expr: &Expr) {
} else { } else {
None None
} }
}) { })
{
let mut diagnostic = Diagnostic::new( let mut diagnostic = Diagnostic::new(
NumpyDeprecatedTypeAlias { NumpyDeprecatedTypeAlias {
type_name: type_name.to_string(), type_name: type_name.to_string(),

View file

@ -58,7 +58,11 @@ impl Violation for NumpyLegacyRandom {
/// NPY002 /// NPY002
pub(crate) fn numpy_legacy_random(checker: &mut Checker, expr: &Expr) { 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| { if let Some(method_name) =
checker
.semantic_model()
.resolve_call_path(expr)
.and_then(|call_path| {
// seeding state // seeding state
if call_path.as_slice() == ["numpy", "random", "seed"] if call_path.as_slice() == ["numpy", "random", "seed"]
|| call_path.as_slice() == ["numpy", "random", "get_state"] || call_path.as_slice() == ["numpy", "random", "get_state"]
@ -116,7 +120,8 @@ pub(crate) fn numpy_legacy_random(checker: &mut Checker, expr: &Expr) {
} else { } else {
None None
} }
}) { })
{
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
NumpyLegacyRandom { NumpyLegacyRandom {
method_name: method_name.to_string(), method_name: method_name.to_string(),

View file

@ -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()`). // 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(_)) { if matches!(parent, Expr::Call(_)) {
return; 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 // Avoid flagging on non-DataFrames (e.g., `{"a": 1}.values`), and on irrelevant bindings
// (like imports). // (like imports).
if !matches!( if !matches!(
test_expression(value, &checker.model), test_expression(value, checker.semantic_model()),
Resolution::RelevantLocal Resolution::RelevantLocal
) { ) {
return; return;

View file

@ -80,7 +80,7 @@ pub(crate) fn call(checker: &mut Checker, func: &Expr) {
// Ignore irrelevant bindings (like imports). // Ignore irrelevant bindings (like imports).
if !matches!( if !matches!(
test_expression(value, &checker.model), test_expression(value, checker.semantic_model()),
Resolution::RelevantLocal | Resolution::PandasModule Resolution::RelevantLocal | Resolution::PandasModule
) { ) {
return; return;

View file

@ -60,11 +60,14 @@ pub(crate) fn inplace_argument(
let mut is_checkable = false; let mut is_checkable = false;
let mut is_pandas = 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; is_checkable = true;
let module = call_path[0]; let module = call_path[0];
is_pandas = checker.model.find_binding(module).map_or(false, |binding| { is_pandas = checker
.semantic_model()
.find_binding(module)
.map_or(false, |binding| {
matches!( matches!(
binding.kind, binding.kind,
BindingKind::Importation(Importation { BindingKind::Importation(Importation {
@ -99,9 +102,9 @@ pub(crate) fn inplace_argument(
// but we don't currently restore expression stacks when parsing deferred nodes, // but we don't currently restore expression stacks when parsing deferred nodes,
// and so the parent is lost. // and so the parent is lost.
let fixable = !seen_star let fixable = !seen_star
&& checker.model.stmt().is_expr_stmt() && checker.semantic_model().stmt().is_expr_stmt()
&& checker.model.expr_parent().is_none() && checker.semantic_model().expr_parent().is_none()
&& !checker.model.scope().kind.is_lambda(); && !checker.semantic_model().scope().kind.is_lambda();
let mut diagnostic = Diagnostic::new(PandasUseOfInplaceArgument, keyword.range()); let mut diagnostic = Diagnostic::new(PandasUseOfInplaceArgument, keyword.range());
if fixable && checker.patch(diagnostic.kind.rule()) { if fixable && checker.patch(diagnostic.kind.rule()) {
if let Some(fix) = convert_inplace_argument_to_assignment( if let Some(fix) = convert_inplace_argument_to_assignment(

View file

@ -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 // Avoid flagging on non-DataFrames (e.g., `{"a": 1}.at[0]`), and on irrelevant bindings
// (like imports). // (like imports).
if !matches!( if !matches!(
test_expression(value, &checker.model), test_expression(value, checker.semantic_model()),
Resolution::RelevantLocal Resolution::RelevantLocal
) { ) {
return; return;

View file

@ -64,7 +64,7 @@ pub(crate) fn invalid_first_argument_name_for_class_method(
) -> Option<Diagnostic> { ) -> Option<Diagnostic> {
if !matches!( if !matches!(
function_type::classify( function_type::classify(
&checker.model, checker.semantic_model(),
scope, scope,
name, name,
decorator_list, decorator_list,

View file

@ -61,7 +61,7 @@ pub(crate) fn invalid_first_argument_name_for_method(
) -> Option<Diagnostic> { ) -> Option<Diagnostic> {
if !matches!( if !matches!(
function_type::classify( function_type::classify(
&checker.model, checker.semantic_model(),
scope, scope,
name, name,
decorator_list, decorator_list,

View file

@ -67,8 +67,8 @@ pub(crate) fn mixed_case_variable_in_class_scope(
return; return;
} }
if helpers::is_mixed_case(name) if helpers::is_mixed_case(name)
&& !helpers::is_named_tuple_assignment(&checker.model, stmt) && !helpers::is_named_tuple_assignment(checker.semantic_model(), stmt)
&& !helpers::is_typed_dict_class(&checker.model, bases) && !helpers::is_typed_dict_class(checker.semantic_model(), bases)
{ {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
MixedCaseVariableInClassScope { MixedCaseVariableInClassScope {

View file

@ -75,7 +75,9 @@ pub(crate) fn mixed_case_variable_in_global_scope(
{ {
return; 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( checker.diagnostics.push(Diagnostic::new(
MixedCaseVariableInGlobalScope { MixedCaseVariableInGlobalScope {
name: name.to_string(), name: name.to_string(),

View file

@ -66,9 +66,9 @@ pub(crate) fn non_lowercase_variable_in_function(
} }
if name.to_lowercase() != name if name.to_lowercase() != name
&& !helpers::is_named_tuple_assignment(&checker.model, stmt) && !helpers::is_named_tuple_assignment(checker.semantic_model(), stmt)
&& !helpers::is_typed_dict_assignment(&checker.model, stmt) && !helpers::is_typed_dict_assignment(checker.semantic_model(), stmt)
&& !helpers::is_type_var_assignment(&checker.model, stmt) && !helpers::is_type_var_assignment(checker.semantic_model(), stmt)
{ {
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
NonLowercaseVariableInFunction { NonLowercaseVariableInFunction {

View file

@ -88,7 +88,8 @@ pub(crate) fn module_import_not_at_top_of_file(
stmt: &Stmt, stmt: &Stmt,
locator: &Locator, 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 checker
.diagnostics .diagnostics
.push(Diagnostic::new(ModuleImportNotAtTopOfFile, stmt.range())); .push(Diagnostic::new(ModuleImportNotAtTopOfFile, stmt.range()));

View file

@ -72,7 +72,7 @@ pub(crate) fn lambda_assignment(
// package like dataclasses, which wouldn't consider the // package like dataclasses, which wouldn't consider the
// rewritten function definition to be equivalent. // rewritten function definition to be equivalent.
// See https://github.com/charliermarsh/ruff/issues/3046 // 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( let mut diagnostic = Diagnostic::new(
LambdaAssignment { LambdaAssignment {
@ -90,7 +90,7 @@ pub(crate) fn lambda_assignment(
let indentation = &leading_space(first_line); let indentation = &leading_space(first_line);
let mut indented = String::new(); let mut indented = String::new();
for (idx, line) in function( for (idx, line) in function(
&checker.model, checker.semantic_model(),
id, id,
args, args,
body, body,

View file

@ -52,7 +52,7 @@ pub(crate) fn type_comparison(
Expr::Call(ast::ExprCall { func, args, .. }) => { Expr::Call(ast::ExprCall { func, args, .. }) => {
if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() { if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() {
// Ex) `type(False)` // 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() { if let Some(arg) = args.first() {
// Allow comparison for types which are not obvious. // Allow comparison for types which are not obvious.
if !matches!( if !matches!(
@ -76,12 +76,12 @@ pub(crate) fn type_comparison(
if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() { if let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() {
// Ex) `types.NoneType` // Ex) `types.NoneType`
if id == "types" if id == "types"
&& checker && checker.semantic_model().resolve_call_path(value).map_or(
.model false,
.resolve_call_path(value) |call_path| {
.map_or(false, |call_path| {
call_path.first().map_or(false, |module| *module == "types") call_path.first().map_or(false, |module| *module == "types")
}) },
)
{ {
checker checker
.diagnostics .diagnostics

View file

@ -27,7 +27,7 @@ pub(crate) fn if_needed(checker: &mut Checker, docstring: &Docstring) {
}) = docstring.definition else { }) = docstring.definition else {
return; return;
}; };
if !is_overload(&checker.model, cast::decorator_list(stmt)) { if !is_overload(checker.semantic_model(), cast::decorator_list(stmt)) {
return; return;
} }
checker.diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(

Some files were not shown because too many files have changed in this diff Show more