Rename semantic_model and model usages to semantic (#5097)

## Summary

As discussed in Discord, and similar to oxc, we're going to refer to
this as `.semantic()` everywhere.

While I was auditing usages of `model: &SemanticModel`, I also changed
as many function signatures as I could find to consistently take the
model as the _last_ argument, rather than the first.
This commit is contained in:
Charlie Marsh 2023-06-14 15:01:51 -04:00 committed by GitHub
parent 65dbfd2556
commit bae183b823
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
209 changed files with 1058 additions and 1167 deletions

File diff suppressed because it is too large Load diff

View file

@ -116,7 +116,7 @@ impl<'a> Importer<'a> {
&self,
import: &StmtImports,
at: TextSize,
semantic_model: &SemanticModel,
semantic: &SemanticModel,
) -> Result<TypingImportEdit> {
// Generate the modified import statement.
let content = autofix::codemods::retain_imports(
@ -130,7 +130,7 @@ impl<'a> Importer<'a> {
let (type_checking_edit, type_checking) = self.get_or_import_symbol(
&ImportRequest::import_from("typing", "TYPE_CHECKING"),
at,
semantic_model,
semantic,
)?;
// Add the import to a `TYPE_CHECKING` block.
@ -164,11 +164,11 @@ impl<'a> Importer<'a> {
&self,
symbol: &ImportRequest,
at: TextSize,
semantic_model: &SemanticModel,
semantic: &SemanticModel,
) -> Result<(Edit, String), ResolutionError> {
match self.get_symbol(symbol, at, semantic_model) {
match self.get_symbol(symbol, at, semantic) {
Some(result) => result,
None => self.import_symbol(symbol, at, semantic_model),
None => self.import_symbol(symbol, at, semantic),
}
}
@ -177,11 +177,10 @@ impl<'a> Importer<'a> {
&self,
symbol: &ImportRequest,
at: TextSize,
semantic_model: &SemanticModel,
semantic: &SemanticModel,
) -> Option<Result<(Edit, String), ResolutionError>> {
// If the symbol is already available in the current scope, use it.
let imported_name =
semantic_model.resolve_qualified_import_name(symbol.module, symbol.member)?;
let imported_name = semantic.resolve_qualified_import_name(symbol.module, symbol.member)?;
// If the symbol source (i.e., the import statement) comes after the current location,
// abort. For example, we could be generating an edit within a function, and the import
@ -196,7 +195,7 @@ impl<'a> Importer<'a> {
// If the symbol source (i.e., the import statement) is in a typing-only context, but we're
// in a runtime context, abort.
if imported_name.context().is_typing() && semantic_model.execution_context().is_runtime() {
if imported_name.context().is_typing() && semantic.execution_context().is_runtime() {
return Some(Err(ResolutionError::IncompatibleContext));
}
@ -233,13 +232,13 @@ impl<'a> Importer<'a> {
&self,
symbol: &ImportRequest,
at: TextSize,
semantic_model: &SemanticModel,
semantic: &SemanticModel,
) -> Result<(Edit, String), ResolutionError> {
if let Some(stmt) = self.find_import_from(symbol.module, at) {
// Case 1: `from functools import lru_cache` is in scope, and we're trying to reference
// `functools.cache`; thus, we add `cache` to the import, and return `"cache"` as the
// bound name.
if semantic_model.is_available(symbol.member) {
if semantic.is_available(symbol.member) {
let Ok(import_edit) = self.add_member(stmt, symbol.member) else {
return Err(ResolutionError::InvalidEdit);
};
@ -252,7 +251,7 @@ impl<'a> Importer<'a> {
ImportStyle::Import => {
// Case 2a: No `functools` import is in scope; thus, we add `import functools`,
// and return `"functools.cache"` as the bound name.
if semantic_model.is_available(symbol.module) {
if semantic.is_available(symbol.module) {
let import_edit =
self.add_import(&AnyImport::Import(Import::module(symbol.module)), at);
Ok((
@ -270,7 +269,7 @@ impl<'a> Importer<'a> {
ImportStyle::ImportFrom => {
// Case 2b: No `functools` import is in scope; thus, we add
// `from functools import cache`, and return `"cache"` as the bound name.
if semantic_model.is_available(symbol.member) {
if semantic.is_available(symbol.member) {
let import_edit = self.add_import(
&AnyImport::ImportFrom(ImportFrom::member(
symbol.module,

View file

@ -67,7 +67,7 @@ pub(crate) fn variable_name_task_id(
// If the function doesn't come from Airflow, we can't do anything.
if !checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| matches!(call_path[0], "airflow"))
{

View file

@ -2,8 +2,8 @@ use rustpython_parser::ast::Expr;
use ruff_python_semantic::SemanticModel;
pub(super) fn is_sys(model: &SemanticModel, expr: &Expr, target: &str) -> bool {
model
pub(super) fn is_sys(expr: &Expr, target: &str, semantic: &SemanticModel) -> bool {
semantic
.resolve_call_path(expr)
.map_or(false, |call_path| call_path.as_slice() == ["sys", target])
}

View file

@ -69,7 +69,7 @@ impl Violation for SysVersionCmpStr10 {
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.semantic_model(), value, "version_info") =>
if is_sys(value, "version_info", checker.semantic()) =>
{
if let Expr::Constant(ast::ExprConstant {
value: Constant::Int(i),
@ -111,7 +111,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
}
Expr::Attribute(ast::ExprAttribute { value, attr, .. })
if is_sys(checker.semantic_model(), value, "version_info") && attr == "minor" =>
if is_sys(value, "version_info", checker.semantic()) && attr == "minor" =>
{
if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
@ -132,7 +132,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
_ => {}
}
if is_sys(checker.semantic_model(), left, "version") {
if is_sys(left, "version", checker.semantic()) {
if let (
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
[Expr::Constant(ast::ExprConstant {

View file

@ -18,7 +18,7 @@ impl Violation for SixPY3 {
/// YTT202
pub(crate) fn name_or_attribute(checker: &mut Checker, expr: &Expr) {
if checker
.semantic_model()
.semantic()
.resolve_call_path(expr)
.map_or(false, |call_path| call_path.as_slice() == ["six", "PY3"])
{

View file

@ -50,7 +50,7 @@ impl Violation for SysVersionSlice1 {
/// YTT101, YTT102, YTT301, YTT303
pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
if is_sys(checker.semantic_model(), value, "version") {
if is_sys(value, "version", checker.semantic()) {
match slice {
Expr::Slice(ast::ExprSlice {
lower: None,

View file

@ -35,14 +35,14 @@ pub(super) fn match_function_def(
}
/// Return the name of the function, if it's overloaded.
pub(crate) fn overloaded_name(model: &SemanticModel, definition: &Definition) -> Option<String> {
pub(crate) fn overloaded_name(definition: &Definition, semantic: &SemanticModel) -> Option<String> {
if let Definition::Member(Member {
kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method,
stmt,
..
}) = definition
{
if visibility::is_overload(model, cast::decorator_list(stmt)) {
if visibility::is_overload(cast::decorator_list(stmt), semantic) {
let (name, ..) = match_function_def(stmt);
Some(name.to_string())
} else {
@ -56,9 +56,9 @@ pub(crate) fn overloaded_name(model: &SemanticModel, definition: &Definition) ->
/// Return `true` if the definition is the implementation for an overloaded
/// function.
pub(crate) fn is_overload_impl(
model: &SemanticModel,
definition: &Definition,
overloaded_name: &str,
semantic: &SemanticModel,
) -> bool {
if let Definition::Member(Member {
kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method,
@ -66,7 +66,7 @@ pub(crate) fn is_overload_impl(
..
}) = definition
{
if visibility::is_overload(model, cast::decorator_list(stmt)) {
if visibility::is_overload(cast::decorator_list(stmt), semantic) {
false
} else {
let (name, ..) = match_function_def(stmt);

View file

@ -431,15 +431,15 @@ fn is_none_returning(body: &[Stmt]) -> bool {
/// ANN401
fn check_dynamically_typed<F>(
model: &SemanticModel,
annotation: &Expr,
func: F,
diagnostics: &mut Vec<Diagnostic>,
is_overridden: bool,
semantic: &SemanticModel,
) where
F: FnOnce() -> String,
{
if !is_overridden && model.match_typing_expr(annotation, "Any") {
if !is_overridden && semantic.match_typing_expr(annotation, "Any") {
diagnostics.push(Diagnostic::new(
AnyType { name: func() },
annotation.range(),
@ -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.semantic_model(), decorator_list);
let is_overridden = visibility::is_override(decorator_list, checker.semantic());
// ANN001, ANN401
for arg in args
@ -492,10 +492,7 @@ pub(crate) fn definition(
// If this is a non-static method, skip `cls` or `self`.
usize::from(
is_method
&& !visibility::is_staticmethod(
checker.semantic_model(),
cast::decorator_list(stmt),
),
&& !visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()),
),
)
{
@ -504,11 +501,11 @@ pub(crate) fn definition(
has_any_typed_arg = true;
if checker.enabled(Rule::AnyType) {
check_dynamically_typed(
checker.semantic_model(),
annotation,
|| arg.arg.to_string(),
&mut diagnostics,
is_overridden,
checker.semantic(),
);
}
} else {
@ -535,11 +532,11 @@ pub(crate) fn definition(
if checker.enabled(Rule::AnyType) {
let name = &arg.arg;
check_dynamically_typed(
checker.semantic_model(),
expr,
|| format!("*{name}"),
&mut diagnostics,
is_overridden,
checker.semantic(),
);
}
}
@ -567,11 +564,11 @@ pub(crate) fn definition(
if checker.enabled(Rule::AnyType) {
let name = &arg.arg;
check_dynamically_typed(
checker.semantic_model(),
expr,
|| format!("**{name}"),
&mut diagnostics,
is_overridden,
checker.semantic(),
);
}
}
@ -592,13 +589,10 @@ pub(crate) fn definition(
}
// ANN101, ANN102
if is_method
&& !visibility::is_staticmethod(checker.semantic_model(), cast::decorator_list(stmt))
{
if is_method && !visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()) {
if let Some(arg) = args.posonlyargs.first().or_else(|| args.args.first()) {
if arg.annotation.is_none() {
if visibility::is_classmethod(checker.semantic_model(), cast::decorator_list(stmt))
{
if visibility::is_classmethod(cast::decorator_list(stmt), checker.semantic()) {
if checker.enabled(Rule::MissingTypeCls) {
diagnostics.push(Diagnostic::new(
MissingTypeCls {
@ -628,11 +622,11 @@ pub(crate) fn definition(
has_typed_return = true;
if checker.enabled(Rule::AnyType) {
check_dynamically_typed(
checker.semantic_model(),
expr,
|| name.to_string(),
&mut diagnostics,
is_overridden,
checker.semantic(),
);
}
} else if !(
@ -640,9 +634,7 @@ 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.semantic_model(), cast::decorator_list(stmt))
{
if is_method && visibility::is_classmethod(cast::decorator_list(stmt), checker.semantic()) {
if checker.enabled(Rule::MissingReturnTypeClassMethod) {
diagnostics.push(Diagnostic::new(
MissingReturnTypeClassMethod {
@ -652,7 +644,7 @@ pub(crate) fn definition(
));
}
} else if is_method
&& visibility::is_staticmethod(checker.semantic_model(), cast::decorator_list(stmt))
&& visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic())
{
if checker.enabled(Rule::MissingReturnTypeStaticMethod) {
diagnostics.push(Diagnostic::new(

View file

@ -64,9 +64,9 @@ const BLOCKING_HTTP_CALLS: &[&[&str]] = &[
/// ASYNC100
pub(crate) fn blocking_http_call(checker: &mut Checker, expr: &Expr) {
if checker.semantic_model().in_async_context() {
if checker.semantic().in_async_context() {
if let Expr::Call(ast::ExprCall { func, .. }) = expr {
let call_path = checker.semantic_model().resolve_call_path(func);
let call_path = checker.semantic().resolve_call_path(func);
let is_blocking =
call_path.map_or(false, |path| BLOCKING_HTTP_CALLS.contains(&path.as_slice()));

View file

@ -56,10 +56,10 @@ const UNSAFE_OS_METHODS: &[&[&str]] = &[
/// ASYNC102
pub(crate) fn blocking_os_call(checker: &mut Checker, expr: &Expr) {
if checker.semantic_model().in_async_context() {
if checker.semantic().in_async_context() {
if let Expr::Call(ast::ExprCall { func, .. }) = expr {
let is_unsafe_os_method = checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |path| UNSAFE_OS_METHODS.contains(&path.as_slice()));

View file

@ -59,10 +59,10 @@ const OPEN_SLEEP_OR_SUBPROCESS_CALL: &[&[&str]] = &[
/// ASYNC101
pub(crate) fn open_sleep_or_subprocess_call(checker: &mut Checker, expr: &Expr) {
if checker.semantic_model().in_async_context() {
if checker.semantic().in_async_context() {
if let Expr::Call(ast::ExprCall { func, .. }) = expr {
let is_open_sleep_or_subprocess_call = checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |path| {
OPEN_SLEEP_OR_SUBPROCESS_CALL.contains(&path.as_slice())

View file

@ -22,17 +22,21 @@ pub(super) fn matches_password_name(string: &str) -> bool {
PASSWORD_CANDIDATE_REGEX.is_match(string)
}
pub(super) fn is_untyped_exception(type_: Option<&Expr>, model: &SemanticModel) -> bool {
pub(super) fn is_untyped_exception(type_: Option<&Expr>, semantic: &SemanticModel) -> bool {
type_.map_or(true, |type_| {
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_ {
elts.iter().any(|type_| {
model.resolve_call_path(type_).map_or(false, |call_path| {
semantic
.resolve_call_path(type_)
.map_or(false, |call_path| {
call_path.as_slice() == ["", "Exception"]
|| call_path.as_slice() == ["", "BaseException"]
})
})
} else {
model.resolve_call_path(type_).map_or(false, |call_path| {
semantic
.resolve_call_path(type_)
.map_or(false, |call_path| {
call_path.as_slice() == ["", "Exception"]
|| call_path.as_slice() == ["", "BaseException"]
})

View file

@ -108,7 +108,7 @@ pub(crate) fn bad_file_permissions(
keywords: &[Keyword],
) {
if checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.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,
..
}) => {
let Some(parent) = checker.semantic_model().expr_parent() else {
let Some(parent) = checker.semantic().expr_parent() else {
if any_over_expr(expr, &has_string_literal) {
return Some(checker.generator().expr(expr));
}

View file

@ -48,9 +48,8 @@ pub(crate) fn hashlib_insecure_hash_functions(
args: &[Expr],
keywords: &[Keyword],
) {
if let Some(hashlib_call) =
checker
.semantic_model()
if let Some(hashlib_call) = checker
.semantic()
.resolve_call_path(func)
.and_then(|call_path| {
if call_path.as_slice() == ["hashlib", "new"] {

View file

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

View file

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

View file

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

View file

@ -44,7 +44,7 @@ pub(crate) fn request_with_no_cert_validation(
keywords: &[Keyword],
) {
if let Some(target) = checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.and_then(|call_path| {
if call_path.len() == 2 {

View file

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

View file

@ -102,8 +102,8 @@ pub(crate) fn shell_injection(
args: &[Expr],
keywords: &[Keyword],
) {
let call_kind = get_call_kind(func, checker.semantic_model());
let shell_keyword = find_shell_keyword(checker.semantic_model(), keywords);
let call_kind = get_call_kind(func, checker.semantic());
let shell_keyword = find_shell_keyword(keywords, checker.semantic());
if matches!(call_kind, Some(CallKind::Subprocess)) {
if let Some(arg) = args.first() {
@ -227,8 +227,8 @@ enum CallKind {
}
/// Return the [`CallKind`] of the given function call.
fn get_call_kind(func: &Expr, model: &SemanticModel) -> Option<CallKind> {
model
fn get_call_kind(func: &Expr, semantic: &SemanticModel) -> Option<CallKind> {
semantic
.resolve_call_path(func)
.and_then(|call_path| match call_path.as_slice() {
&[module, submodule] => match module {
@ -269,14 +269,14 @@ struct ShellKeyword<'a> {
/// Return the `shell` keyword argument to the given function call, if any.
fn find_shell_keyword<'a>(
model: &SemanticModel,
keywords: &'a [Keyword],
semantic: &SemanticModel,
) -> Option<ShellKeyword<'a>> {
keywords
.iter()
.find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "shell"))
.map(|keyword| ShellKeyword {
truthiness: Truthiness::from_expr(&keyword.value, |id| model.is_builtin(id)),
truthiness: Truthiness::from_expr(&keyword.value, |id| semantic.is_builtin(id)),
keyword,
})
}

View file

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

View file

@ -27,7 +27,7 @@ pub(crate) fn snmp_weak_cryptography(
keywords: &[Keyword],
) {
if checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
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;
};
let Some(reason) = checker.semantic_model().resolve_call_path(func).and_then(|call_path| {
let Some(reason) = checker.semantic().resolve_call_path(func).and_then(|call_path| {
for module in SUSPICIOUS_MEMBERS {
for member in module.members {
if call_path.as_slice() == *member {

View file

@ -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.semantic_model()))
&& (check_typed_exception || is_untyped_exception(type_, checker.semantic()))
{
checker
.diagnostics

View file

@ -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.semantic_model()))
&& (check_typed_exception || is_untyped_exception(type_, checker.semantic()))
{
checker
.diagnostics

View file

@ -38,14 +38,14 @@ pub(crate) fn unsafe_yaml_load(
keywords: &[Keyword],
) {
if checker
.semantic_model()
.semantic()
.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
.semantic_model()
.semantic()
.resolve_call_path(loader_arg)
.map_or(false, |call_path| {
call_path.as_slice() == ["yaml", "SafeLoader"]

View file

@ -34,7 +34,7 @@ pub(crate) fn blind_except(
return;
};
for exception in ["BaseException", "Exception"] {
if id == exception && checker.semantic_model().is_builtin(exception) {
if id == exception && checker.semantic().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.semantic_model()) {
if logging::is_logger_candidate(func, checker.semantic()) {
if let Some(attribute) = func.as_attribute_expr() {
let attr = attribute.attr.as_str();
if attr == "exception" {

View file

@ -36,16 +36,16 @@ impl Violation for EmptyMethodWithoutAbstractDecorator {
}
}
fn is_abc_class(model: &SemanticModel, bases: &[Expr], keywords: &[Keyword]) -> bool {
fn is_abc_class(bases: &[Expr], keywords: &[Keyword], semantic: &SemanticModel) -> bool {
keywords.iter().any(|keyword| {
keyword.arg.as_ref().map_or(false, |arg| arg == "metaclass")
&& model
&& semantic
.resolve_call_path(&keyword.value)
.map_or(false, |call_path| {
call_path.as_slice() == ["abc", "ABCMeta"]
})
}) || bases.iter().any(|base| {
model
semantic
.resolve_call_path(base)
.map_or(false, |call_path| call_path.as_slice() == ["abc", "ABC"])
})
@ -80,7 +80,7 @@ pub(crate) fn abstract_base_class(
if bases.len() + keywords.len() != 1 {
return;
}
if !is_abc_class(checker.semantic_model(), bases, keywords) {
if !is_abc_class(bases, keywords, checker.semantic()) {
return;
}
@ -109,7 +109,7 @@ pub(crate) fn abstract_base_class(
continue;
};
let has_abstract_decorator = is_abstract(checker.semantic_model(), decorator_list);
let has_abstract_decorator = is_abstract(decorator_list, checker.semantic());
has_abstract_method |= has_abstract_decorator;
if !checker.enabled(Rule::EmptyMethodWithoutAbstractDecorator) {
@ -118,7 +118,7 @@ pub(crate) fn abstract_base_class(
if !has_abstract_decorator
&& is_empty_body(body)
&& !is_overload(checker.semantic_model(), decorator_list)
&& !is_overload(decorator_list, checker.semantic())
{
checker.diagnostics.push(Diagnostic::new(
EmptyMethodWithoutAbstractDecorator {

View file

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

View file

@ -18,8 +18,8 @@ impl Violation for CachedInstanceMethod {
}
}
fn is_cache_func(model: &SemanticModel, expr: &Expr) -> bool {
model.resolve_call_path(expr).map_or(false, |call_path| {
fn is_cache_func(expr: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(expr).map_or(false, |call_path| {
call_path.as_slice() == ["functools", "lru_cache"]
|| call_path.as_slice() == ["functools", "cache"]
})
@ -27,7 +27,7 @@ fn is_cache_func(model: &SemanticModel, expr: &Expr) -> bool {
/// B019
pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[Decorator]) {
if !checker.semantic_model().scope().kind.is_class() {
if !checker.semantic().scope().kind.is_class() {
return;
}
for decorator in decorator_list {
@ -41,11 +41,11 @@ pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[De
}
for decorator in decorator_list {
if is_cache_func(
checker.semantic_model(),
match &decorator.expression {
Expr::Call(ast::ExprCall { func, .. }) => func,
_ => &decorator.expression,
},
checker.semantic(),
) {
checker
.diagnostics

View file

@ -73,7 +73,7 @@ impl Violation for FunctionCallInDefaultArgument {
}
struct ArgumentDefaultVisitor<'a> {
model: &'a SemanticModel<'a>,
semantic: &'a SemanticModel<'a>,
extend_immutable_calls: Vec<CallPath<'a>>,
diagnostics: Vec<(DiagnosticKind, TextRange)>,
}
@ -81,7 +81,7 @@ struct ArgumentDefaultVisitor<'a> {
impl<'a> ArgumentDefaultVisitor<'a> {
fn new(model: &'a SemanticModel<'a>, extend_immutable_calls: Vec<CallPath<'a>>) -> Self {
Self {
model,
semantic: model,
extend_immutable_calls,
diagnostics: Vec::new(),
}
@ -95,8 +95,8 @@ where
fn visit_expr(&mut self, expr: &'b Expr) {
match expr {
Expr::Call(ast::ExprCall { func, .. }) => {
if !is_mutable_func(self.model, func)
&& !is_immutable_func(self.model, func, &self.extend_immutable_calls)
if !is_mutable_func(func, self.semantic)
&& !is_immutable_func(func, self.semantic, &self.extend_immutable_calls)
{
self.diagnostics.push((
FunctionCallInDefaultArgument {
@ -125,8 +125,7 @@ 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.semantic_model(), extend_immutable_calls);
let mut visitor = ArgumentDefaultVisitor::new(checker.semantic(), extend_immutable_calls);
for expr in arguments
.defaults
.iter()

View file

@ -26,15 +26,15 @@ const MUTABLE_FUNCS: &[&[&str]] = &[
&["collections", "deque"],
];
pub(crate) fn is_mutable_func(model: &SemanticModel, func: &Expr) -> bool {
model.resolve_call_path(func).map_or(false, |call_path| {
pub(crate) fn is_mutable_func(func: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(func).map_or(false, |call_path| {
MUTABLE_FUNCS
.iter()
.any(|target| call_path.as_slice() == *target)
})
}
fn is_mutable_expr(model: &SemanticModel, expr: &Expr) -> bool {
fn is_mutable_expr(expr: &Expr, semantic: &SemanticModel) -> bool {
match expr {
Expr::List(_)
| Expr::Dict(_)
@ -42,7 +42,7 @@ fn is_mutable_expr(model: &SemanticModel, expr: &Expr) -> bool {
| Expr::ListComp(_)
| Expr::DictComp(_)
| Expr::SetComp(_) => true,
Expr::Call(ast::ExprCall { func, .. }) => is_mutable_func(model, func),
Expr::Call(ast::ExprCall { func, .. }) => is_mutable_func(func, semantic),
_ => false,
}
}
@ -64,9 +64,9 @@ pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Argume
.zip(arguments.defaults.iter().rev()),
)
{
if is_mutable_expr(checker.semantic_model(), default)
if is_mutable_expr(default, checker.semantic())
&& !arg.annotation.as_ref().map_or(false, |expr| {
is_immutable_annotation(checker.semantic_model(), expr)
is_immutable_annotation(expr, checker.semantic())
})
{
checker

View file

@ -45,7 +45,7 @@ pub(crate) fn no_explicit_stacklevel(
keywords: &[Keyword],
) {
if !checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
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`
if !checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["itertools", "groupby"]

View file

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

View file

@ -20,7 +20,6 @@
use rustc_hash::FxHashMap;
use rustpython_parser::ast::{self, Expr, Ranged, Stmt};
use serde::{Deserialize, Serialize};
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
use ruff_macros::{derive_message_formats, violation};
@ -30,7 +29,7 @@ use ruff_python_ast::{helpers, visitor};
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, result_like::BoolLike)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, result_like::BoolLike)]
enum Certainty {
Certain,
Uncertain,
@ -129,7 +128,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.semantic_model().is_builtin(id)
checker.semantic().is_builtin(id)
}));
// Attempt to rename the variable by prepending an underscore, but avoid
@ -154,10 +153,10 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr,
if certainty.into() && checker.patch(diagnostic.kind.rule()) {
// Avoid fixing if the variable, or any future bindings to the variable, are
// used _after_ the loop.
let scope = checker.semantic_model().scope();
let scope = checker.semantic().scope();
if scope
.get_all(name)
.map(|binding_id| checker.semantic_model().binding(binding_id))
.map(|binding_id| checker.semantic().binding(binding_id))
.all(|binding| !binding.is_used())
{
diagnostic.set_fix(Fix::suggested(Edit::range_replacement(

View file

@ -27,7 +27,7 @@ pub(crate) fn useless_contextlib_suppress(
) {
if args.is_empty()
&& checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
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.
if contains_effect(value, |id| checker.semantic_model().is_builtin(id)) {
if contains_effect(value, |id| checker.semantic().is_builtin(id)) {
// Flag attributes as useless expressions, even if they're attached to calls or other
// expressions.
if matches!(value, Expr::Attribute(_)) {

View file

@ -27,13 +27,13 @@ pub(crate) fn zip_without_explicit_strict(
) {
if let Expr::Name(ast::ExprName { id, .. }) = func {
if id == "zip"
&& checker.semantic_model().is_builtin("zip")
&& checker.semantic().is_builtin("zip")
&& !kwargs
.iter()
.any(|keyword| keyword.arg.as_ref().map_or(false, |name| name == "strict"))
&& !args
.iter()
.any(|arg| is_infinite_iterator(arg, checker.semantic_model()))
.any(|arg| is_infinite_iterator(arg, checker.semantic()))
{
checker
.diagnostics
@ -44,14 +44,13 @@ pub(crate) fn zip_without_explicit_strict(
/// Return `true` if the [`Expr`] appears to be an infinite iterator (e.g., a call to
/// `itertools.cycle` or similar).
fn is_infinite_iterator(arg: &Expr, model: &SemanticModel) -> bool {
fn is_infinite_iterator(arg: &Expr, semantic: &SemanticModel) -> bool {
let Expr::Call(ast::ExprCall { func, args, keywords, .. }) = &arg else {
return false;
};
return model
.resolve_call_path(func)
.map_or(false, |call_path| match call_path.as_slice() {
semantic.resolve_call_path(func).map_or(false, |call_path| {
match call_path.as_slice() {
["itertools", "cycle" | "count"] => true,
["itertools", "repeat"] => {
// Ex) `itertools.repeat(1)`
@ -76,5 +75,6 @@ fn is_infinite_iterator(arg: &Expr, model: &SemanticModel) -> bool {
false
}
_ => false,
});
}
})
}

View file

@ -72,11 +72,11 @@ pub(crate) fn builtin_attribute_shadowing(
if shadows_builtin(name, &checker.settings.flake8_builtins.builtins_ignorelist) {
// Ignore shadowing within `TypedDict` definitions, since these are only accessible through
// subscripting and not through attribute access.
if class_def.bases.iter().any(|base| {
checker
.semantic_model()
.match_typing_expr(base, "TypedDict")
}) {
if class_def
.bases
.iter()
.any(|base| checker.semantic().match_typing_expr(base, "TypedDict"))
{
return;
}

View file

@ -502,7 +502,7 @@ pub(crate) fn fix_unnecessary_collection_call(
/// this method will pad the start and end of an expression as needed to
/// avoid producing invalid syntax.
fn pad_expression(content: String, range: TextRange, checker: &Checker) -> String {
if !checker.semantic_model().in_f_string() {
if !checker.semantic().in_f_string() {
return content;
}

View file

@ -75,7 +75,7 @@ pub(crate) fn unnecessary_call_around_sorted(
if inner != "sorted" {
return;
}
if !checker.semantic_model().is_builtin(inner) || !checker.semantic_model().is_builtin(outer) {
if !checker.semantic().is_builtin(inner) || !checker.semantic().is_builtin(outer) {
return;
}
let mut diagnostic = Diagnostic::new(

View file

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

View file

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

View file

@ -76,7 +76,7 @@ pub(crate) fn unnecessary_comprehension_any_all(
if is_async_generator(elt) {
return;
}
if !checker.semantic_model().is_builtin(id) {
if !checker.semantic().is_builtin(id) {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin(inner) || !checker.semantic_model().is_builtin(outer) {
if !checker.semantic().is_builtin(inner) || !checker.semantic().is_builtin(outer) {
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 {
return;
};
if !checker.semantic_model().is_builtin("list") {
if !checker.semantic().is_builtin("list") {
return;
}
if let Expr::GeneratorExp(_) = argument {

View file

@ -52,7 +52,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.semantic_model().is_builtin("set") {
if !checker.semantic().is_builtin("set") {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin("list") {
if !checker.semantic().is_builtin("list") {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin("dict") {
if !checker.semantic().is_builtin("dict") {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin("set") {
if !checker.semantic().is_builtin("set") {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin("dict") {
if !checker.semantic().is_builtin("dict") {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin("set") {
if !checker.semantic().is_builtin("set") {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin("dict") {
if !checker.semantic().is_builtin("dict") {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin("list") {
if !checker.semantic().is_builtin("list") {
return;
}
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 {
return;
};
if !checker.semantic_model().is_builtin("tuple") {
if !checker.semantic().is_builtin("tuple") {
return;
}
let argument_kind = match argument {

View file

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

View file

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

View file

@ -27,7 +27,7 @@ impl Violation for CallDateFromtimestamp {
/// Use `datetime.datetime.fromtimestamp(, tz=).date()` instead.
pub(crate) fn call_date_fromtimestamp(checker: &mut Checker, func: &Expr, location: TextRange) {
if checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "date", "fromtimestamp"]

View file

@ -27,7 +27,7 @@ impl Violation for CallDateToday {
/// Use `datetime.datetime.now(tz=).date()` instead.
pub(crate) fn call_date_today(checker: &mut Checker, func: &Expr, location: TextRange) {
if checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "date", "today"]

View file

@ -28,7 +28,7 @@ pub(crate) fn call_datetime_fromtimestamp(
location: TextRange,
) {
if !checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "fromtimestamp"]

View file

@ -26,7 +26,7 @@ pub(crate) fn call_datetime_now_without_tzinfo(
location: TextRange,
) {
if !checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "now"]

View file

@ -28,7 +28,7 @@ pub(crate) fn call_datetime_strptime_without_zone(
location: TextRange,
) {
if !checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "strptime"]
@ -49,7 +49,7 @@ pub(crate) fn call_datetime_strptime_without_zone(
}
};
let (Some(grandparent), Some(parent)) = (checker.semantic_model().expr_grandparent(), checker.semantic_model().expr_parent()) else {
let (Some(grandparent), Some(parent)) = (checker.semantic().expr_grandparent(), checker.semantic().expr_parent()) else {
checker.diagnostics.push(Diagnostic::new(
CallDatetimeStrptimeWithoutZone,
location,

View file

@ -27,7 +27,7 @@ impl Violation for CallDatetimeToday {
/// Use `datetime.datetime.now(tz=)` instead.
pub(crate) fn call_datetime_today(checker: &mut Checker, func: &Expr, location: TextRange) {
if checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "today"]

View file

@ -34,7 +34,7 @@ pub(crate) fn call_datetime_utcfromtimestamp(
location: TextRange,
) {
if checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "utcfromtimestamp"]

View file

@ -29,7 +29,7 @@ impl Violation for CallDatetimeUtcnow {
/// 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
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime", "utcnow"]

View file

@ -25,7 +25,7 @@ pub(crate) fn call_datetime_without_tzinfo(
location: TextRange,
) {
if !checker
.semantic_model()
.semantic()
.resolve_call_path(func)
.map_or(false, |call_path| {
call_path.as_slice() == ["datetime", "datetime"]

View file

@ -44,7 +44,7 @@ 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
.semantic_model()
.semantic()
.resolve_call_path(func)
.and_then(|call_path| {
DEBUGGERS

View file

@ -54,7 +54,7 @@ pub(crate) fn all_with_model_form(
) -> Option<Diagnostic> {
if !bases
.iter()
.any(|base| is_model_form(checker.semantic_model(), base))
.any(|base| is_model_form(base, checker.semantic()))
{
return None;
}

View file

@ -52,7 +52,7 @@ pub(crate) fn exclude_with_model_form(
) -> Option<Diagnostic> {
if !bases
.iter()
.any(|base| is_model_form(checker.semantic_model(), base))
.any(|base| is_model_form(base, checker.semantic()))
{
return None;
}

View file

@ -3,23 +3,23 @@ use rustpython_parser::ast::Expr;
use ruff_python_semantic::SemanticModel;
/// Return `true` if a Python class appears to be a Django model, based on its base classes.
pub(super) fn is_model(model: &SemanticModel, base: &Expr) -> bool {
model.resolve_call_path(base).map_or(false, |call_path| {
pub(super) fn is_model(base: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(base).map_or(false, |call_path| {
call_path.as_slice() == ["django", "db", "models", "Model"]
})
}
/// Return `true` if a Python class appears to be a Django model form, based on its base classes.
pub(super) fn is_model_form(model: &SemanticModel, base: &Expr) -> bool {
model.resolve_call_path(base).map_or(false, |call_path| {
pub(super) fn is_model_form(base: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(base).map_or(false, |call_path| {
call_path.as_slice() == ["django", "forms", "ModelForm"]
|| call_path.as_slice() == ["django", "forms", "models", "ModelForm"]
})
}
/// Return `true` if the expression is constructor for a Django model field.
pub(super) fn is_model_field(model: &SemanticModel, expr: &Expr) -> bool {
model.resolve_call_path(expr).map_or(false, |call_path| {
pub(super) fn is_model_field(expr: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(expr).map_or(false, |call_path| {
call_path
.as_slice()
.starts_with(&["django", "db", "models"])
@ -28,10 +28,10 @@ pub(super) fn is_model_field(model: &SemanticModel, expr: &Expr) -> bool {
/// Return the name of the field type, if the expression is constructor for a Django model field.
pub(super) fn get_model_field_name<'a>(
model: &'a SemanticModel,
expr: &'a Expr,
semantic: &'a SemanticModel,
) -> Option<&'a str> {
model.resolve_call_path(expr).and_then(|call_path| {
semantic.resolve_call_path(expr).and_then(|call_path| {
let call_path = call_path.as_slice();
if !call_path.starts_with(&["django", "db", "models"]) {
return None;

View file

@ -51,7 +51,7 @@ pub(crate) fn locals_in_render_function(
keywords: &[Keyword],
) {
if !checker
.semantic_model()
.semantic()
.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.semantic_model(), &args[2]) {
if !is_locals_call(&args[2], checker.semantic()) {
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.semantic_model(), &keyword.value) {
if !is_locals_call(&keyword.value, checker.semantic()) {
return;
}
&keyword.value
@ -83,11 +83,11 @@ pub(crate) fn locals_in_render_function(
));
}
fn is_locals_call(model: &SemanticModel, expr: &Expr) -> bool {
fn is_locals_call(expr: &Expr, semantic: &SemanticModel) -> bool {
let Expr::Call(ast::ExprCall { func, .. }) = expr else {
return false
};
model
semantic
.resolve_call_path(func)
.map_or(false, |call_path| call_path.as_slice() == ["", "locals"])
}

View file

@ -56,7 +56,7 @@ pub(crate) fn model_without_dunder_str(
body: &[Stmt],
class_location: &Stmt,
) -> Option<Diagnostic> {
if !checker_applies(checker.semantic_model(), bases, body) {
if !is_non_abstract_model(bases, body, checker.semantic()) {
return None;
}
if !has_dunder_method(body) {
@ -80,12 +80,12 @@ fn has_dunder_method(body: &[Stmt]) -> bool {
})
}
fn checker_applies(model: &SemanticModel, bases: &[Expr], body: &[Stmt]) -> bool {
fn is_non_abstract_model(bases: &[Expr], body: &[Stmt], semantic: &SemanticModel) -> bool {
for base in bases.iter() {
if is_model_abstract(body) {
continue;
}
if helpers::is_model(model, base) {
if helpers::is_model(base, semantic) {
return true;
}
}

View file

@ -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.semantic_model(), func) else {
let Some(valid_field_name) = helpers::get_model_field_name(func, checker.semantic()) else {
return None;
};

View file

@ -100,11 +100,11 @@ impl fmt::Display for ContentType {
}
}
fn get_element_type(model: &SemanticModel, element: &Stmt) -> Option<ContentType> {
fn get_element_type(element: &Stmt, semantic: &SemanticModel) -> Option<ContentType> {
match element {
Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() {
if helpers::is_model_field(model, func) {
if helpers::is_model_field(func, semantic) {
return Some(ContentType::FieldDeclaration);
}
}
@ -145,13 +145,13 @@ pub(crate) fn unordered_body_content_in_model(
) {
if !bases
.iter()
.any(|base| helpers::is_model(checker.semantic_model(), base))
.any(|base| helpers::is_model(base, checker.semantic()))
{
return;
}
let mut elements_type_found = Vec::new();
for element in body.iter() {
let Some(current_element_type) = get_element_type(checker.semantic_model(), element) else {
let Some(current_element_type) = get_element_type(element, checker.semantic()) else {
continue;
};
let Some(&element_type) = elements_type_found

View file

@ -190,7 +190,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
if let Some(indentation) =
whitespace::indentation(checker.locator, stmt)
{
if checker.semantic_model().is_available("msg") {
if checker.semantic().is_available("msg") {
diagnostic.set_fix(generate_fix(
stmt,
first,
@ -213,7 +213,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
if let Some(indentation) =
whitespace::indentation(checker.locator, stmt)
{
if checker.semantic_model().is_available("msg") {
if checker.semantic().is_available("msg") {
diagnostic.set_fix(generate_fix(
stmt,
first,
@ -240,7 +240,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
if let Some(indentation) =
whitespace::indentation(checker.locator, stmt)
{
if checker.semantic_model().is_available("msg") {
if checker.semantic().is_available("msg") {
diagnostic.set_fix(generate_fix(
stmt,
first,

View file

@ -65,7 +65,7 @@ impl Violation for FutureRewritableTypeAnnotation {
/// FA100
pub(crate) fn future_rewritable_type_annotation(checker: &mut Checker, expr: &Expr) {
let name = checker
.semantic_model()
.semantic()
.resolve_call_path(expr)
.map(|binding| format_call_path(&binding));

View file

@ -106,7 +106,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
}
Expr::Call(ast::ExprCall { func, keywords, .. }) => {
if checker
.semantic_model()
.semantic()
.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.semantic_model()) {
if !logging::is_logger_candidate(func, checker.semantic()) {
return;
}
@ -193,10 +193,10 @@ pub(crate) fn logging_call(
// G201, G202
if checker.any_enabled(&[Rule::LoggingExcInfo, Rule::LoggingRedundantExcInfo]) {
if !checker.semantic_model().in_exception_handler() {
if !checker.semantic().in_exception_handler() {
return;
}
let Some(exc_info) = logging::exc_info(keywords, checker.semantic_model()) else {
let Some(exc_info) = logging::exc_info(keywords, checker.semantic()) else {
return;
};
if let LoggingCallType::LevelCall(logging_level) = logging_call_type {

View file

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

View file

@ -69,7 +69,7 @@ pub(crate) fn reimplemented_list_builtin(checker: &mut Checker, expr: &ExprLambd
if elts.is_empty() {
let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range());
if checker.patch(diagnostic.kind.rule()) {
if checker.semantic_model().is_builtin("list") {
if checker.semantic().is_builtin("list") {
diagnostic.set_fix(Fix::automatic(Edit::range_replacement(
"list".to_string(),
expr.range(),

View file

@ -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.semantic_model().resolve_call_path(func);
let call_path = checker.semantic().resolve_call_path(func);
if call_path
.as_ref()
.map_or(false, |call_path| *call_path.as_slice() == ["", "print"])
@ -90,14 +90,13 @@ pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword
.find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "file"))
{
if !is_const_none(&keyword.value) {
if checker
.semantic_model()
.resolve_call_path(&keyword.value)
.map_or(true, |call_path| {
if checker.semantic().resolve_call_path(&keyword.value).map_or(
true,
|call_path| {
call_path.as_slice() != ["sys", "stdout"]
&& call_path.as_slice() != ["sys", "stderr"]
})
{
},
) {
return;
}
}

View file

@ -66,14 +66,11 @@ pub(crate) fn any_eq_ne_annotation(checker: &mut Checker, name: &str, args: &Arg
return;
};
if !checker.semantic_model().scope().kind.is_class() {
if !checker.semantic().scope().kind.is_class() {
return;
}
if checker
.semantic_model()
.match_typing_expr(annotation, "Any")
{
if checker.semantic().match_typing_expr(annotation, "Any") {
let mut diagnostic = Diagnostic::new(
AnyEqNeAnnotation {
method_name: name.to_string(),
@ -82,7 +79,7 @@ pub(crate) fn any_eq_ne_annotation(checker: &mut Checker, name: &str, args: &Arg
);
if checker.patch(diagnostic.kind.rule()) {
// Ex) `def __eq__(self, obj: Any): ...`
if checker.semantic_model().is_builtin("object") {
if checker.semantic().is_builtin("object") {
diagnostic.set_fix(Fix::automatic(Edit::range_replacement(
"object".to_string(),
annotation.range(),

View file

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

View file

@ -51,7 +51,7 @@ impl Violation for CollectionsNamedTuple {
/// PYI024
pub(crate) fn collections_named_tuple(checker: &mut Checker, expr: &Expr) {
if checker
.semantic_model()
.semantic()
.resolve_call_path(expr)
.map_or(false, |call_path| {
matches!(call_path.as_slice(), ["collections", "namedtuple"])

View file

@ -101,7 +101,7 @@ pub(crate) fn iter_method_return_iterable(checker: &mut Checker, definition: &De
};
if checker
.semantic_model()
.semantic()
.resolve_call_path(annotation)
.map_or(false, |call_path| {
if async_ {

View file

@ -56,10 +56,7 @@ pub(crate) fn no_return_argument_annotation(checker: &mut Checker, args: &Argume
)
.filter_map(|arg| arg.annotation.as_ref())
{
if checker
.semantic_model()
.match_typing_expr(annotation, "NoReturn")
{
if checker.semantic().match_typing_expr(annotation, "NoReturn") {
checker.diagnostics.push(Diagnostic::new(
NoReturnArgumentAnnotationInStub {
module: if checker.settings.target_version >= Py311 {

View file

@ -118,7 +118,7 @@ pub(crate) fn non_self_return_type(
args: &Arguments,
async_: bool,
) {
let ScopeKind::Class(class_def) = checker.semantic_model().scope().kind else {
let ScopeKind::Class(class_def) = checker.semantic().scope().kind else {
return;
};
@ -131,8 +131,8 @@ pub(crate) fn non_self_return_type(
};
// Skip any abstract or overloaded methods.
if is_abstract(checker.semantic_model(), decorator_list)
|| is_overload(checker.semantic_model(), decorator_list)
if is_abstract(decorator_list, checker.semantic())
|| is_overload(decorator_list, checker.semantic())
{
return;
}
@ -140,7 +140,7 @@ pub(crate) fn non_self_return_type(
if async_ {
if name == "__aenter__"
&& is_name(returns, &class_def.name)
&& !is_final(checker.semantic_model(), &class_def.decorator_list)
&& !is_final(&class_def.decorator_list, checker.semantic())
{
checker.diagnostics.push(Diagnostic::new(
NonSelfReturnType {
@ -155,7 +155,7 @@ pub(crate) fn non_self_return_type(
// In-place methods that are expected to return `Self`.
if INPLACE_BINOP_METHODS.contains(&name) {
if !is_self(returns, checker.semantic_model()) {
if !is_self(returns, checker.semantic()) {
checker.diagnostics.push(Diagnostic::new(
NonSelfReturnType {
class_name: class_def.name.to_string(),
@ -169,7 +169,7 @@ pub(crate) fn non_self_return_type(
if is_name(returns, &class_def.name) {
if matches!(name, "__enter__" | "__new__")
&& !is_final(checker.semantic_model(), &class_def.decorator_list)
&& !is_final(&class_def.decorator_list, checker.semantic())
{
checker.diagnostics.push(Diagnostic::new(
NonSelfReturnType {
@ -184,8 +184,8 @@ pub(crate) fn non_self_return_type(
match name {
"__iter__" => {
if is_iterable(returns, checker.semantic_model())
&& is_iterator(&class_def.bases, checker.semantic_model())
if is_iterable(returns, checker.semantic())
&& is_iterator(&class_def.bases, checker.semantic())
{
checker.diagnostics.push(Diagnostic::new(
NonSelfReturnType {
@ -197,8 +197,8 @@ pub(crate) fn non_self_return_type(
}
}
"__aiter__" => {
if is_async_iterable(returns, checker.semantic_model())
&& is_async_iterator(&class_def.bases, checker.semantic_model())
if is_async_iterable(returns, checker.semantic())
&& is_async_iterator(&class_def.bases, checker.semantic())
{
checker.diagnostics.push(Diagnostic::new(
NonSelfReturnType {
@ -238,14 +238,14 @@ fn is_name(expr: &Expr, name: &str) -> bool {
}
/// Return `true` if the given expression resolves to `typing.Self`.
fn is_self(expr: &Expr, model: &SemanticModel) -> bool {
model.match_typing_expr(expr, "Self")
fn is_self(expr: &Expr, semantic: &SemanticModel) -> bool {
semantic.match_typing_expr(expr, "Self")
}
/// Return `true` if the given class extends `collections.abc.Iterator`.
fn is_iterator(bases: &[Expr], model: &SemanticModel) -> bool {
fn is_iterator(bases: &[Expr], semantic: &SemanticModel) -> bool {
bases.iter().any(|expr| {
model
semantic
.resolve_call_path(map_subscript(expr))
.map_or(false, |call_path| {
matches!(
@ -257,8 +257,8 @@ fn is_iterator(bases: &[Expr], model: &SemanticModel) -> bool {
}
/// Return `true` if the given expression resolves to `collections.abc.Iterable`.
fn is_iterable(expr: &Expr, model: &SemanticModel) -> bool {
model
fn is_iterable(expr: &Expr, semantic: &SemanticModel) -> bool {
semantic
.resolve_call_path(map_subscript(expr))
.map_or(false, |call_path| {
matches!(
@ -270,9 +270,9 @@ fn is_iterable(expr: &Expr, model: &SemanticModel) -> bool {
}
/// Return `true` if the given class extends `collections.abc.AsyncIterator`.
fn is_async_iterator(bases: &[Expr], model: &SemanticModel) -> bool {
fn is_async_iterator(bases: &[Expr], semantic: &SemanticModel) -> bool {
bases.iter().any(|expr| {
model
semantic
.resolve_call_path(map_subscript(expr))
.map_or(false, |call_path| {
matches!(
@ -284,8 +284,8 @@ fn is_async_iterator(bases: &[Expr], model: &SemanticModel) -> bool {
}
/// Return `true` if the given expression resolves to `collections.abc.AsyncIterable`.
fn is_async_iterable(expr: &Expr, model: &SemanticModel) -> bool {
model
fn is_async_iterable(expr: &Expr, semantic: &SemanticModel) -> bool {
semantic
.resolve_call_path(map_subscript(expr))
.map_or(false, |call_path| {
matches!(

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 {
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") {
let Some(kind) = checker.semantic().resolve_call_path(func).and_then(|call_path| {
if checker.semantic().match_typing_call_path(&call_path, "ParamSpec") {
Some(VarKind::ParamSpec)
} else if checker.semantic_model().match_typing_call_path(&call_path, "TypeVar") {
} else if checker.semantic().match_typing_call_path(&call_path, "TypeVar") {
Some(VarKind::TypeVar)
} else if checker.semantic_model().match_typing_call_path(&call_path, "TypeVarTuple") {
} else if checker.semantic().match_typing_call_path(&call_path, "TypeVarTuple") {
Some(VarKind::TypeVarTuple)
} else {
None

View file

@ -123,7 +123,7 @@ fn is_valid_default_value_with_annotation(
default: &Expr,
allow_container: bool,
locator: &Locator,
model: &SemanticModel,
semantic: &SemanticModel,
) -> bool {
match default {
Expr::Constant(_) => {
@ -136,7 +136,7 @@ fn is_valid_default_value_with_annotation(
&& elts.len() <= 10
&& elts
.iter()
.all(|e| is_valid_default_value_with_annotation(e, false, locator, model));
.all(|e| is_valid_default_value_with_annotation(e, false, locator, semantic));
}
Expr::Dict(ast::ExprDict {
keys,
@ -147,8 +147,8 @@ fn is_valid_default_value_with_annotation(
&& keys.len() <= 10
&& keys.iter().zip(values).all(|(k, v)| {
k.as_ref().map_or(false, |k| {
is_valid_default_value_with_annotation(k, false, locator, model)
}) && is_valid_default_value_with_annotation(v, false, locator, model)
is_valid_default_value_with_annotation(k, false, locator, semantic)
}) && is_valid_default_value_with_annotation(v, false, locator, semantic)
});
}
Expr::UnaryOp(ast::ExprUnaryOp {
@ -164,12 +164,15 @@ fn is_valid_default_value_with_annotation(
}) => return true,
// Ex) `-math.inf`, `-math.pi`, etc.
Expr::Attribute(_) => {
if model.resolve_call_path(operand).map_or(false, |call_path| {
if semantic
.resolve_call_path(operand)
.map_or(false, |call_path| {
ALLOWED_MATH_ATTRIBUTES_IN_DEFAULTS.iter().any(|target| {
// reject `-math.nan`
call_path.as_slice() == *target && *target != ["math", "nan"]
})
}) {
})
{
return true;
}
}
@ -214,12 +217,15 @@ fn is_valid_default_value_with_annotation(
}
// Ex) `math.inf`, `sys.stdin`, etc.
Expr::Attribute(_) => {
if model.resolve_call_path(default).map_or(false, |call_path| {
if semantic
.resolve_call_path(default)
.map_or(false, |call_path| {
ALLOWED_MATH_ATTRIBUTES_IN_DEFAULTS
.iter()
.chain(ALLOWED_ATTRIBUTES_IN_DEFAULTS.iter())
.any(|target| call_path.as_slice() == *target)
}) {
})
{
return true;
}
}
@ -265,11 +271,11 @@ fn is_valid_default_value_without_annotation(default: &Expr) -> bool {
/// Returns `true` if an [`Expr`] appears to be `TypeVar`, `TypeVarTuple`, `NewType`, or `ParamSpec`
/// call.
fn is_type_var_like_call(model: &SemanticModel, expr: &Expr) -> bool {
fn is_type_var_like_call(expr: &Expr, semantic: &SemanticModel) -> bool {
let Expr::Call(ast::ExprCall { func, .. } )= expr else {
return false;
};
model.resolve_call_path(func).map_or(false, |call_path| {
semantic.resolve_call_path(func).map_or(false, |call_path| {
matches!(
call_path.as_slice(),
[
@ -282,11 +288,11 @@ fn is_type_var_like_call(model: &SemanticModel, expr: &Expr) -> bool {
/// Returns `true` if this is a "special" assignment which must have a value (e.g., an assignment to
/// `__all__`).
fn is_special_assignment(model: &SemanticModel, target: &Expr) -> bool {
fn is_special_assignment(target: &Expr, semantic: &SemanticModel) -> bool {
if let Expr::Name(ast::ExprName { id, .. }) = target {
match id.as_str() {
"__all__" => model.scope().kind.is_module(),
"__match_args__" | "__slots__" => model.scope().kind.is_class(),
"__all__" => semantic.scope().kind.is_module(),
"__match_args__" | "__slots__" => semantic.scope().kind.is_class(),
_ => false,
}
} else {
@ -295,9 +301,9 @@ fn is_special_assignment(model: &SemanticModel, target: &Expr) -> bool {
}
/// Returns `true` if the a class is an enum, based on its base classes.
fn is_enum(model: &SemanticModel, bases: &[Expr]) -> bool {
fn is_enum(bases: &[Expr], semantic: &SemanticModel) -> bool {
return bases.iter().any(|expr| {
model.resolve_call_path(expr).map_or(false, |call_path| {
semantic.resolve_call_path(expr).map_or(false, |call_path| {
matches!(
call_path.as_slice(),
[
@ -323,7 +329,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum
default,
true,
checker.locator,
checker.semantic_model(),
checker.semantic(),
) {
let mut diagnostic =
Diagnostic::new(TypedArgumentDefaultInStub, default.range());
@ -354,7 +360,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum
default,
true,
checker.locator,
checker.semantic_model(),
checker.semantic(),
) {
let mut diagnostic =
Diagnostic::new(TypedArgumentDefaultInStub, default.range());
@ -388,7 +394,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments)
default,
true,
checker.locator,
checker.semantic_model(),
checker.semantic(),
) {
let mut diagnostic =
Diagnostic::new(ArgumentDefaultInStub, default.range());
@ -419,7 +425,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments)
default,
true,
checker.locator,
checker.semantic_model(),
checker.semantic(),
) {
let mut diagnostic =
Diagnostic::new(ArgumentDefaultInStub, default.range());
@ -448,21 +454,16 @@ pub(crate) fn assignment_default_in_stub(checker: &mut Checker, targets: &[Expr]
if !target.is_name_expr() {
return;
}
if is_special_assignment(checker.semantic_model(), target) {
if is_special_assignment(target, checker.semantic()) {
return;
}
if is_type_var_like_call(checker.semantic_model(), value) {
if is_type_var_like_call(value, checker.semantic()) {
return;
}
if is_valid_default_value_without_annotation(value) {
return;
}
if is_valid_default_value_with_annotation(
value,
true,
checker.locator,
checker.semantic_model(),
) {
if is_valid_default_value_with_annotation(value, true, checker.locator, checker.semantic()) {
return;
}
@ -484,23 +485,18 @@ pub(crate) fn annotated_assignment_default_in_stub(
annotation: &Expr,
) {
if checker
.semantic_model()
.semantic()
.match_typing_expr(annotation, "TypeAlias")
{
return;
}
if is_special_assignment(checker.semantic_model(), target) {
if is_special_assignment(target, checker.semantic()) {
return;
}
if is_type_var_like_call(checker.semantic_model(), value) {
if is_type_var_like_call(value, checker.semantic()) {
return;
}
if is_valid_default_value_with_annotation(
value,
true,
checker.locator,
checker.semantic_model(),
) {
if is_valid_default_value_with_annotation(value, true, checker.locator, checker.semantic()) {
return;
}
@ -527,27 +523,21 @@ pub(crate) fn unannotated_assignment_in_stub(
let Expr::Name(ast::ExprName { id, .. }) = target else {
return;
};
if is_special_assignment(checker.semantic_model(), target) {
if is_special_assignment(target, checker.semantic()) {
return;
}
if is_type_var_like_call(checker.semantic_model(), value) {
if is_type_var_like_call(value, checker.semantic()) {
return;
}
if is_valid_default_value_without_annotation(value) {
return;
}
if !is_valid_default_value_with_annotation(
value,
true,
checker.locator,
checker.semantic_model(),
) {
if !is_valid_default_value_with_annotation(value, true, checker.locator, checker.semantic()) {
return;
}
if let ScopeKind::Class(ast::StmtClassDef { bases, .. }) = checker.semantic_model().scope().kind
{
if is_enum(checker.semantic_model(), bases) {
if let ScopeKind::Class(ast::StmtClassDef { bases, .. }) = checker.semantic().scope().kind {
if is_enum(bases, checker.semantic()) {
return;
}
}
@ -569,7 +559,7 @@ pub(crate) fn unassigned_special_variable_in_stub(
return;
};
if !is_special_assignment(checker.semantic_model(), target) {
if !is_special_assignment(target, checker.semantic()) {
return;
}

View file

@ -62,7 +62,7 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
return;
}
if !checker.semantic_model().scope().kind.is_class() {
if !checker.semantic().scope().kind.is_class() {
return;
}
@ -72,12 +72,12 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
return;
}
if is_abstract(checker.semantic_model(), decorator_list) {
if is_abstract(decorator_list, checker.semantic()) {
return;
}
if checker
.semantic_model()
.semantic()
.resolve_call_path(returns)
.map_or(true, |call_path| {
!matches!(call_path.as_slice(), ["" | "builtins", "str"])
@ -93,8 +93,8 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
identifier_range(stmt, checker.locator),
);
if checker.patch(diagnostic.kind.rule()) {
let stmt = checker.semantic_model().stmt();
let parent = checker.semantic_model().stmt_parent();
let stmt = checker.semantic().stmt();
let parent = checker.semantic().stmt_parent();
let edit = delete_stmt(
stmt,
parent,
@ -103,7 +103,7 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
checker.stylist,
);
diagnostic.set_fix(
Fix::automatic(edit).isolate(checker.isolation(checker.semantic_model().stmt_parent())),
Fix::automatic(edit).isolate(checker.isolation(checker.semantic().stmt_parent())),
);
}
checker.diagnostics.push(diagnostic);

View file

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

View file

@ -194,9 +194,9 @@ pub(crate) fn unittest_assertion(
if checker.patch(diagnostic.kind.rule()) {
// We're converting an expression to a statement, so avoid applying the fix if
// the assertion is part of a larger expression.
if checker.semantic_model().stmt().is_expr_stmt()
&& checker.semantic_model().expr_parent().is_none()
&& !checker.semantic_model().scope().kind.is_lambda()
if checker.semantic().stmt().is_expr_stmt()
&& checker.semantic().expr_parent().is_none()
&& !checker.semantic().scope().kind.is_lambda()
&& !has_comments_in(expr.range(), checker.locator)
{
if let Ok(stmt) = unittest_assert.generate_assert(args, keywords) {
@ -219,7 +219,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.semantic_model().is_builtin(id)).is_falsey() {
if Truthiness::from_expr(test, |id| checker.semantic().is_builtin(id)).is_falsey() {
checker
.diagnostics
.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]) {
if is_pytest_fail(checker.semantic_model(), func) {
if is_pytest_fail(func, checker.semantic()) {
let call_args = SimpleCallArgs::new(args, keywords);
// Allow either `pytest.fail(reason="...")` (introduced in pytest 7.0) or

View file

@ -245,11 +245,11 @@ where
}
fn get_fixture_decorator<'a>(
model: &SemanticModel,
decorators: &'a [Decorator],
semantic: &SemanticModel,
) -> Option<&'a Decorator> {
decorators.iter().find(|decorator| {
is_pytest_fixture(model, decorator) || is_pytest_yield_fixture(model, decorator)
is_pytest_fixture(decorator, semantic) || is_pytest_yield_fixture(decorator, semantic)
})
}
@ -436,7 +436,7 @@ fn check_test_function_args(checker: &mut Checker, args: &Arguments) {
/// PT020
fn check_fixture_decorator_name(checker: &mut Checker, decorator: &Decorator) {
if is_pytest_yield_fixture(checker.semantic_model(), decorator) {
if is_pytest_yield_fixture(decorator, checker.semantic()) {
checker.diagnostics.push(Diagnostic::new(
PytestDeprecatedYieldFixture,
decorator.range(),
@ -504,7 +504,7 @@ pub(crate) fn fixture(
decorators: &[Decorator],
body: &[Stmt],
) {
let decorator = get_fixture_decorator(checker.semantic_model(), decorators);
let decorator = get_fixture_decorator(decorators, checker.semantic());
if let Some(decorator) = decorator {
if checker.enabled(Rule::PytestFixtureIncorrectParenthesesStyle)
|| checker.enabled(Rule::PytestFixturePositionalArgs)
@ -522,7 +522,7 @@ pub(crate) fn fixture(
if (checker.enabled(Rule::PytestMissingFixtureNameUnderscore)
|| checker.enabled(Rule::PytestIncorrectFixtureNameUnderscore)
|| checker.enabled(Rule::PytestUselessYieldFixture))
&& !is_abstract(checker.semantic_model(), decorators)
&& !is_abstract(decorators, checker.semantic())
{
check_fixture_returns(checker, stmt, name, body);
}

View file

@ -20,41 +20,41 @@ pub(super) fn get_mark_decorators(
})
}
pub(super) fn is_pytest_fail(model: &SemanticModel, call: &Expr) -> bool {
model.resolve_call_path(call).map_or(false, |call_path| {
pub(super) fn is_pytest_fail(call: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(call).map_or(false, |call_path| {
call_path.as_slice() == ["pytest", "fail"]
})
}
pub(super) fn is_pytest_fixture(model: &SemanticModel, decorator: &Decorator) -> bool {
model
pub(super) fn is_pytest_fixture(decorator: &Decorator, semantic: &SemanticModel) -> bool {
semantic
.resolve_call_path(map_callable(&decorator.expression))
.map_or(false, |call_path| {
call_path.as_slice() == ["pytest", "fixture"]
})
}
pub(super) fn is_pytest_yield_fixture(model: &SemanticModel, decorator: &Decorator) -> bool {
model
pub(super) fn is_pytest_yield_fixture(decorator: &Decorator, semantic: &SemanticModel) -> bool {
semantic
.resolve_call_path(map_callable(&decorator.expression))
.map_or(false, |call_path| {
call_path.as_slice() == ["pytest", "yield_fixture"]
})
}
pub(super) fn is_pytest_parametrize(model: &SemanticModel, decorator: &Decorator) -> bool {
model
pub(super) fn is_pytest_parametrize(decorator: &Decorator, semantic: &SemanticModel) -> bool {
semantic
.resolve_call_path(map_callable(&decorator.expression))
.map_or(false, |call_path| {
call_path.as_slice() == ["pytest", "mark", "parametrize"]
})
}
pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool {
pub(super) fn keyword_is_literal(keyword: &Keyword, literal: &str) -> bool {
if let Expr::Constant(ast::ExprConstant {
value: Constant::Str(string),
..
}) = &kw.value
}) = &keyword.value
{
string == literal
} else {

View file

@ -419,7 +419,7 @@ fn handle_value_rows(
pub(crate) fn parametrize(checker: &mut Checker, decorators: &[Decorator]) {
for decorator in decorators {
if is_pytest_parametrize(checker.semantic_model(), decorator) {
if is_pytest_parametrize(decorator, checker.semantic()) {
if let Expr::Call(ast::ExprCall { args, .. }) = &decorator.expression {
if checker.enabled(Rule::PytestParametrizeNamesWrongType) {
if let Some(names) = args.get(0) {

View file

@ -47,8 +47,8 @@ impl Violation for PytestRaisesWithoutException {
}
}
fn is_pytest_raises(func: &Expr, model: &SemanticModel) -> bool {
model.resolve_call_path(func).map_or(false, |call_path| {
fn is_pytest_raises(func: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(func).map_or(false, |call_path| {
call_path.as_slice() == ["pytest", "raises"]
})
}
@ -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.semantic_model()) {
if is_pytest_raises(func, checker.semantic()) {
if checker.enabled(Rule::PytestRaisesWithoutException) {
if args.is_empty() && keywords.is_empty() {
checker
@ -100,7 +100,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.semantic_model()),
Expr::Call(ast::ExprCall { func, .. }) => is_pytest_raises(func, checker.semantic()),
_ => false,
});
@ -141,7 +141,7 @@ pub(crate) fn complex_raises(
/// PT011
fn exception_needs_match(checker: &mut Checker, exception: &Expr) {
if let Some(call_path) = checker
.semantic_model()
.semantic()
.resolve_call_path(exception)
.and_then(|call_path| {
let is_broad_exception = checker

View file

@ -398,12 +398,12 @@ const NORETURN_FUNCS: &[&[&str]] = &[
];
/// Return `true` if the `func` is a known function that never returns.
fn is_noreturn_func(model: &SemanticModel, func: &Expr) -> bool {
model.resolve_call_path(func).map_or(false, |call_path| {
fn is_noreturn_func(func: &Expr, semantic: &SemanticModel) -> bool {
semantic.resolve_call_path(func).map_or(false, |call_path| {
NORETURN_FUNCS
.iter()
.any(|target| call_path.as_slice() == *target)
|| model.match_typing_call_path(&call_path, "assert_never")
|| semantic.match_typing_call_path(&call_path, "assert_never")
})
}
@ -489,7 +489,7 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) {
if matches!(
value.as_ref(),
Expr::Call(ast::ExprCall { func, .. })
if is_noreturn_func(checker.semantic_model(), func)
if is_noreturn_func(func, checker.semantic())
) => {}
_ => {
let mut diagnostic = Diagnostic::new(ImplicitReturn, stmt.range());

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