mirror of https://github.com/astral-sh/ruff
Introduce a `ruff_python_semantic` crate (#3865)
This commit is contained in:
parent
46bcb1f725
commit
d919adc13c
|
|
@ -2010,6 +2010,7 @@ dependencies = [
|
||||||
"ruff_diagnostics",
|
"ruff_diagnostics",
|
||||||
"ruff_macros",
|
"ruff_macros",
|
||||||
"ruff_python_ast",
|
"ruff_python_ast",
|
||||||
|
"ruff_python_semantic",
|
||||||
"ruff_python_stdlib",
|
"ruff_python_stdlib",
|
||||||
"ruff_rustpython",
|
"ruff_rustpython",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
|
|
@ -2170,12 +2171,10 @@ dependencies = [
|
||||||
"is-macro",
|
"is-macro",
|
||||||
"itertools",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"nohash-hasher",
|
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
"ruff_python_stdlib",
|
|
||||||
"ruff_rustpython",
|
"ruff_rustpython",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustpython-common",
|
"rustpython-common",
|
||||||
|
|
@ -2196,7 +2195,6 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ruff_formatter",
|
"ruff_formatter",
|
||||||
"ruff_python_ast",
|
"ruff_python_ast",
|
||||||
"ruff_python_stdlib",
|
|
||||||
"ruff_rustpython",
|
"ruff_rustpython",
|
||||||
"ruff_testing_macros",
|
"ruff_testing_macros",
|
||||||
"ruff_text_size",
|
"ruff_text_size",
|
||||||
|
|
@ -2207,6 +2205,20 @@ dependencies = [
|
||||||
"test-case",
|
"test-case",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruff_python_semantic"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"is-macro",
|
||||||
|
"nohash-hasher",
|
||||||
|
"ruff_python_ast",
|
||||||
|
"ruff_python_stdlib",
|
||||||
|
"rustc-hash",
|
||||||
|
"rustpython-parser",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff_python_stdlib"
|
name = "ruff_python_stdlib"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ is-macro = { version = "0.2.2" }
|
||||||
itertools = { version = "0.10.5" }
|
itertools = { version = "0.10.5" }
|
||||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
|
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
|
||||||
log = { version = "0.4.17" }
|
log = { version = "0.4.17" }
|
||||||
|
nohash-hasher = { version = "0.2.0" }
|
||||||
once_cell = { version = "1.17.1" }
|
once_cell = { version = "1.17.1" }
|
||||||
path-absolutize = { version = "3.0.14" }
|
path-absolutize = { version = "3.0.14" }
|
||||||
proc-macro2 = { version = "1.0.51" }
|
proc-macro2 = { version = "1.0.51" }
|
||||||
|
|
@ -40,6 +41,7 @@ serde = { version = "1.0.152", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.93", features = ["preserve_order"] }
|
serde_json = { version = "1.0.93", features = ["preserve_order"] }
|
||||||
shellexpand = { version = "3.0.0" }
|
shellexpand = { version = "3.0.0" }
|
||||||
similar = { version = "2.2.1" }
|
similar = { version = "2.2.1" }
|
||||||
|
smallvec = { version = "1.10.0" }
|
||||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||||
strum_macros = { version = "0.24.3" }
|
strum_macros = { version = "0.24.3" }
|
||||||
syn = { version = "1.0.109" }
|
syn = { version = "1.0.109" }
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ ruff_cache = { path = "../ruff_cache" }
|
||||||
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
|
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
|
||||||
ruff_macros = { path = "../ruff_macros" }
|
ruff_macros = { path = "../ruff_macros" }
|
||||||
ruff_python_ast = { path = "../ruff_python_ast" }
|
ruff_python_ast = { path = "../ruff_python_ast" }
|
||||||
|
ruff_python_semantic = { path = "../ruff_python_semantic" }
|
||||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
||||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||||
|
|
||||||
|
|
@ -37,7 +38,7 @@ itertools = { workspace = true }
|
||||||
libcst = { workspace = true }
|
libcst = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
natord = { version = "1.0.9" }
|
natord = { version = "1.0.9" }
|
||||||
nohash-hasher = { version = "0.2.0" }
|
nohash-hasher = { workspace = true }
|
||||||
num-bigint = { version = "0.4.3" }
|
num-bigint = { version = "0.4.3" }
|
||||||
num-traits = { version = "0.2.15" }
|
num-traits = { version = "0.2.15" }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
|
|
@ -57,7 +58,7 @@ semver = { version = "1.0.16" }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
shellexpand = { workspace = true }
|
shellexpand = { workspace = true }
|
||||||
smallvec = { version = "1.10.0" }
|
smallvec = { workspace = true }
|
||||||
strum = { workspace = true }
|
strum = { workspace = true }
|
||||||
strum_macros = { workspace = true }
|
strum_macros = { workspace = true }
|
||||||
textwrap = { workspace = true }
|
textwrap = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,12 @@ use rustpython_parser::ast::{ExcepthandlerKind, Expr, Keyword, Location, Stmt, S
|
||||||
use rustpython_parser::{lexer, Mode, Tok};
|
use rustpython_parser::{lexer, Mode, Tok};
|
||||||
|
|
||||||
use ruff_diagnostics::Edit;
|
use ruff_diagnostics::Edit;
|
||||||
use ruff_python_ast::context::Context;
|
|
||||||
use ruff_python_ast::helpers;
|
use ruff_python_ast::helpers;
|
||||||
use ruff_python_ast::helpers::to_absolute;
|
use ruff_python_ast::helpers::to_absolute;
|
||||||
use ruff_python_ast::imports::{AnyImport, Import};
|
use ruff_python_ast::imports::{AnyImport, Import};
|
||||||
use ruff_python_ast::newlines::NewlineWithTrailingNewline;
|
use ruff_python_ast::newlines::NewlineWithTrailingNewline;
|
||||||
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
||||||
|
use ruff_python_semantic::context::Context;
|
||||||
|
|
||||||
use crate::cst::helpers::compose_module_path;
|
use crate::cst::helpers::compose_module_path;
|
||||||
use crate::cst::matchers::match_module;
|
use crate::cst::matchers::match_module;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use ruff_python_ast::scope::ScopeStack;
|
use ruff_python_semantic::scope::ScopeStack;
|
||||||
use rustpython_parser::ast::{Expr, Stmt};
|
use rustpython_parser::ast::{Expr, Stmt};
|
||||||
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::types::RefEquality;
|
use ruff_python_ast::types::RefEquality;
|
||||||
use ruff_python_ast::visibility::{Visibility, VisibleScope};
|
use ruff_python_semantic::analyze::visibility::{Visibility, VisibleScope};
|
||||||
|
|
||||||
use crate::checkers::ast::AnnotationContext;
|
use crate::checkers::ast::AnnotationContext;
|
||||||
use crate::docstrings::definition::Definition;
|
use crate::docstrings::definition::Definition;
|
||||||
|
|
|
||||||
|
|
@ -14,22 +14,22 @@ use rustpython_parser::ast::{
|
||||||
|
|
||||||
use ruff_diagnostics::Diagnostic;
|
use ruff_diagnostics::Diagnostic;
|
||||||
use ruff_python_ast::all::{extract_all_names, AllNamesFlags};
|
use ruff_python_ast::all::{extract_all_names, AllNamesFlags};
|
||||||
use ruff_python_ast::binding::{
|
use ruff_python_ast::helpers::{extract_handled_exceptions, to_module_path};
|
||||||
|
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
||||||
|
use ruff_python_ast::types::{Node, Range, RefEquality};
|
||||||
|
use ruff_python_ast::typing::parse_type_annotation;
|
||||||
|
use ruff_python_ast::visitor::{walk_excepthandler, walk_pattern, Visitor};
|
||||||
|
use ruff_python_ast::{branch_detection, cast, helpers, str, visitor};
|
||||||
|
use ruff_python_semantic::analyze;
|
||||||
|
use ruff_python_semantic::analyze::typing::{Callable, SubscriptKind};
|
||||||
|
use ruff_python_semantic::binding::{
|
||||||
Binding, BindingId, BindingKind, Exceptions, ExecutionContext, Export, FromImportation,
|
Binding, BindingId, BindingKind, Exceptions, ExecutionContext, Export, FromImportation,
|
||||||
Importation, StarImportation, SubmoduleImportation,
|
Importation, StarImportation, SubmoduleImportation,
|
||||||
};
|
};
|
||||||
use ruff_python_ast::context::Context;
|
use ruff_python_semantic::context::Context;
|
||||||
use ruff_python_ast::helpers::{extract_handled_exceptions, to_module_path};
|
use ruff_python_semantic::scope::{
|
||||||
use ruff_python_ast::scope::{
|
|
||||||
ClassDef, FunctionDef, Lambda, Scope, ScopeId, ScopeKind, ScopeStack,
|
ClassDef, FunctionDef, Lambda, Scope, ScopeId, ScopeKind, ScopeStack,
|
||||||
};
|
};
|
||||||
use ruff_python_ast::source_code::{Indexer, Locator, Stylist};
|
|
||||||
use ruff_python_ast::types::{Node, Range, RefEquality};
|
|
||||||
use ruff_python_ast::typing::{
|
|
||||||
match_annotated_subscript, parse_type_annotation, Callable, SubscriptKind,
|
|
||||||
};
|
|
||||||
use ruff_python_ast::visitor::{walk_excepthandler, walk_pattern, Visitor};
|
|
||||||
use ruff_python_ast::{branch_detection, cast, helpers, str, typing, visibility, visitor};
|
|
||||||
use ruff_python_stdlib::builtins::{BUILTINS, MAGIC_GLOBALS};
|
use ruff_python_stdlib::builtins::{BUILTINS, MAGIC_GLOBALS};
|
||||||
use ruff_python_stdlib::path::is_python_stub_file;
|
use ruff_python_stdlib::path::is_python_stub_file;
|
||||||
|
|
||||||
|
|
@ -2248,7 +2248,7 @@ where
|
||||||
|| (self.settings.target_version >= PythonVersion::Py37
|
|| (self.settings.target_version >= PythonVersion::Py37
|
||||||
&& self.ctx.annotations_future_enabled
|
&& self.ctx.annotations_future_enabled
|
||||||
&& self.ctx.in_annotation))
|
&& self.ctx.in_annotation))
|
||||||
&& typing::is_pep585_builtin(expr, &self.ctx)
|
&& analyze::typing::is_pep585_builtin(expr, &self.ctx)
|
||||||
{
|
{
|
||||||
pyupgrade::rules::use_pep585_annotation(self, expr);
|
pyupgrade::rules::use_pep585_annotation(self, expr);
|
||||||
}
|
}
|
||||||
|
|
@ -2291,7 +2291,7 @@ where
|
||||||
|| (self.settings.target_version >= PythonVersion::Py37
|
|| (self.settings.target_version >= PythonVersion::Py37
|
||||||
&& self.ctx.annotations_future_enabled
|
&& self.ctx.annotations_future_enabled
|
||||||
&& self.ctx.in_annotation))
|
&& self.ctx.in_annotation))
|
||||||
&& typing::is_pep585_builtin(expr, &self.ctx)
|
&& analyze::typing::is_pep585_builtin(expr, &self.ctx)
|
||||||
{
|
{
|
||||||
pyupgrade::rules::use_pep585_annotation(self, expr);
|
pyupgrade::rules::use_pep585_annotation(self, expr);
|
||||||
}
|
}
|
||||||
|
|
@ -3632,7 +3632,7 @@ where
|
||||||
self.ctx.in_subscript = true;
|
self.ctx.in_subscript = true;
|
||||||
visitor::walk_expr(self, expr);
|
visitor::walk_expr(self, expr);
|
||||||
} else {
|
} else {
|
||||||
match match_annotated_subscript(
|
match analyze::typing::match_annotated_subscript(
|
||||||
value,
|
value,
|
||||||
&self.ctx,
|
&self.ctx,
|
||||||
self.settings.typing_modules.iter().map(String::as_str),
|
self.settings.typing_modules.iter().map(String::as_str),
|
||||||
|
|
@ -4051,7 +4051,7 @@ impl<'a> Checker<'a> {
|
||||||
&& binding.redefines(existing)
|
&& binding.redefines(existing)
|
||||||
&& (!self.settings.dummy_variable_rgx.is_match(name) || existing_is_import)
|
&& (!self.settings.dummy_variable_rgx.is_match(name) || existing_is_import)
|
||||||
&& !(existing.kind.is_function_definition()
|
&& !(existing.kind.is_function_definition()
|
||||||
&& visibility::is_overload(
|
&& analyze::visibility::is_overload(
|
||||||
&self.ctx,
|
&self.ctx,
|
||||||
cast::decorator_list(existing.source.as_ref().unwrap()),
|
cast::decorator_list(existing.source.as_ref().unwrap()),
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use ruff_python_ast::visibility::{
|
use rustpython_parser::ast::{Expr, Stmt};
|
||||||
|
|
||||||
|
use ruff_python_semantic::analyze::visibility::{
|
||||||
class_visibility, function_visibility, method_visibility, Modifier, Visibility, VisibleScope,
|
class_visibility, function_visibility, method_visibility, Modifier, Visibility, VisibleScope,
|
||||||
};
|
};
|
||||||
use rustpython_parser::ast::{Expr, Stmt};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum DefinitionKind<'a> {
|
pub enum DefinitionKind<'a> {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_python_ast::visibility::{Modifier, VisibleScope};
|
use ruff_python_semantic::analyze::visibility;
|
||||||
|
|
||||||
use crate::docstrings::definition::{Definition, DefinitionKind, Documentable};
|
use crate::docstrings::definition::{Definition, DefinitionKind, Documentable};
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ pub fn docstring_from(suite: &[Stmt]) -> Option<&Expr> {
|
||||||
|
|
||||||
/// Extract a `Definition` from the AST node defined by a `Stmt`.
|
/// Extract a `Definition` from the AST node defined by a `Stmt`.
|
||||||
pub fn extract<'a>(
|
pub fn extract<'a>(
|
||||||
scope: VisibleScope,
|
scope: visibility::VisibleScope,
|
||||||
stmt: &'a Stmt,
|
stmt: &'a Stmt,
|
||||||
body: &'a [Stmt],
|
body: &'a [Stmt],
|
||||||
kind: Documentable,
|
kind: Documentable,
|
||||||
|
|
@ -36,22 +36,22 @@ pub fn extract<'a>(
|
||||||
let expr = docstring_from(body);
|
let expr = docstring_from(body);
|
||||||
match kind {
|
match kind {
|
||||||
Documentable::Function => match scope {
|
Documentable::Function => match scope {
|
||||||
VisibleScope {
|
visibility::VisibleScope {
|
||||||
modifier: Modifier::Module,
|
modifier: visibility::Modifier::Module,
|
||||||
..
|
..
|
||||||
} => Definition {
|
} => Definition {
|
||||||
kind: DefinitionKind::Function(stmt),
|
kind: DefinitionKind::Function(stmt),
|
||||||
docstring: expr,
|
docstring: expr,
|
||||||
},
|
},
|
||||||
VisibleScope {
|
visibility::VisibleScope {
|
||||||
modifier: Modifier::Class,
|
modifier: visibility::Modifier::Class,
|
||||||
..
|
..
|
||||||
} => Definition {
|
} => Definition {
|
||||||
kind: DefinitionKind::Method(stmt),
|
kind: DefinitionKind::Method(stmt),
|
||||||
docstring: expr,
|
docstring: expr,
|
||||||
},
|
},
|
||||||
VisibleScope {
|
visibility::VisibleScope {
|
||||||
modifier: Modifier::Function,
|
modifier: visibility::Modifier::Function,
|
||||||
..
|
..
|
||||||
} => Definition {
|
} => Definition {
|
||||||
kind: DefinitionKind::NestedFunction(stmt),
|
kind: DefinitionKind::NestedFunction(stmt),
|
||||||
|
|
@ -59,22 +59,22 @@ pub fn extract<'a>(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Documentable::Class => match scope {
|
Documentable::Class => match scope {
|
||||||
VisibleScope {
|
visibility::VisibleScope {
|
||||||
modifier: Modifier::Module,
|
modifier: visibility::Modifier::Module,
|
||||||
..
|
..
|
||||||
} => Definition {
|
} => Definition {
|
||||||
kind: DefinitionKind::Class(stmt),
|
kind: DefinitionKind::Class(stmt),
|
||||||
docstring: expr,
|
docstring: expr,
|
||||||
},
|
},
|
||||||
VisibleScope {
|
visibility::VisibleScope {
|
||||||
modifier: Modifier::Class,
|
modifier: visibility::Modifier::Class,
|
||||||
..
|
..
|
||||||
} => Definition {
|
} => Definition {
|
||||||
kind: DefinitionKind::NestedClass(stmt),
|
kind: DefinitionKind::NestedClass(stmt),
|
||||||
docstring: expr,
|
docstring: expr,
|
||||||
},
|
},
|
||||||
VisibleScope {
|
visibility::VisibleScope {
|
||||||
modifier: Modifier::Function,
|
modifier: visibility::Modifier::Function,
|
||||||
..
|
..
|
||||||
} => Definition {
|
} => Definition {
|
||||||
kind: DefinitionKind::NestedClass(stmt),
|
kind: DefinitionKind::NestedClass(stmt),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use rustpython_parser::ast::{Arguments, Expr, Stmt, StmtKind};
|
use rustpython_parser::ast::{Arguments, Expr, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_python_ast::cast;
|
use ruff_python_ast::cast;
|
||||||
use ruff_python_ast::visibility;
|
use ruff_python_semantic::analyze::visibility;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::docstrings::definition::{Definition, DefinitionKind};
|
use crate::docstrings::definition::{Definition, DefinitionKind};
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::ReturnStatementVisitor;
|
use ruff_python_ast::helpers::ReturnStatementVisitor;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::visibility::Visibility;
|
|
||||||
use ruff_python_ast::visibility::{self};
|
|
||||||
use ruff_python_ast::visitor::Visitor;
|
use ruff_python_ast::visitor::Visitor;
|
||||||
use ruff_python_ast::{cast, helpers};
|
use ruff_python_ast::{cast, helpers};
|
||||||
|
use ruff_python_semantic::analyze::visibility;
|
||||||
|
use ruff_python_semantic::analyze::visibility::Visibility;
|
||||||
use ruff_python_stdlib::typing::SIMPLE_MAGIC_RETURN_TYPES;
|
use ruff_python_stdlib::typing::SIMPLE_MAGIC_RETURN_TYPES;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::{find_keyword, is_const_true};
|
use ruff_python_ast::helpers::{find_keyword, is_const_true};
|
||||||
use ruff_python_ast::logging;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::analyze::logging;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Stmt, StmtKind};
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::visibility::{is_abstract, is_overload};
|
use ruff_python_semantic::analyze::visibility::{is_abstract, is_overload};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use rustpython_parser::ast::Expr;
|
use rustpython_parser::ast::Expr;
|
||||||
|
|
||||||
use ruff_python_ast::context::Context;
|
use ruff_python_semantic::context::Context;
|
||||||
|
|
||||||
/// Return `true` if a Python class appears to be a Django model, based on its base classes.
|
/// Return `true` if a Python class appears to be a Django model, based on its base classes.
|
||||||
pub fn is_model(context: &Context, base: &Expr) -> bool {
|
pub fn is_model(context: &Context, base: &Expr) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Location, Operat
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Edit};
|
use ruff_diagnostics::{Diagnostic, Edit};
|
||||||
use ruff_python_ast::helpers::{find_keyword, SimpleCallArgs};
|
use ruff_python_ast::helpers::{find_keyword, SimpleCallArgs};
|
||||||
use ruff_python_ast::logging;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::analyze::logging;
|
||||||
|
use ruff_python_stdlib::logging::LoggingLevel;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::{AsRule, Rule};
|
use crate::registry::{AsRule, Rule};
|
||||||
|
|
@ -128,7 +129,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum LoggingCallType {
|
enum LoggingCallType {
|
||||||
/// Logging call with a level method, e.g., `logging.info`.
|
/// Logging call with a level method, e.g., `logging.info`.
|
||||||
LevelCall(logging::LoggingLevel),
|
LevelCall(LoggingLevel),
|
||||||
/// Logging call with an integer level as an argument, e.g., `logger.log(level, ...)`.
|
/// Logging call with an integer level as an argument, e.g., `logger.log(level, ...)`.
|
||||||
LogCall,
|
LogCall,
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +139,7 @@ impl LoggingCallType {
|
||||||
if attr == "log" {
|
if attr == "log" {
|
||||||
Some(LoggingCallType::LogCall)
|
Some(LoggingCallType::LogCall)
|
||||||
} else {
|
} else {
|
||||||
logging::LoggingLevel::from_attribute(attr).map(LoggingCallType::LevelCall)
|
LoggingLevel::from_attribute(attr).map(LoggingCallType::LevelCall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +174,7 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
||||||
if checker.settings.rules.enabled(Rule::LoggingWarn)
|
if checker.settings.rules.enabled(Rule::LoggingWarn)
|
||||||
&& matches!(
|
&& matches!(
|
||||||
logging_call_type,
|
logging_call_type,
|
||||||
LoggingCallType::LevelCall(logging::LoggingLevel::Warn)
|
LoggingCallType::LevelCall(LoggingLevel::Warn)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let mut diagnostic = Diagnostic::new(LoggingWarn, level_call_range);
|
let mut diagnostic = Diagnostic::new(LoggingWarn, level_call_range);
|
||||||
|
|
@ -228,14 +229,14 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
||||||
|
|
||||||
if let LoggingCallType::LevelCall(logging_level) = logging_call_type {
|
if let LoggingCallType::LevelCall(logging_level) = logging_call_type {
|
||||||
match logging_level {
|
match logging_level {
|
||||||
logging::LoggingLevel::Error => {
|
LoggingLevel::Error => {
|
||||||
if checker.settings.rules.enabled(Rule::LoggingExcInfo) {
|
if checker.settings.rules.enabled(Rule::LoggingExcInfo) {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
.push(Diagnostic::new(LoggingExcInfo, level_call_range));
|
.push(Diagnostic::new(LoggingExcInfo, level_call_range));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logging::LoggingLevel::Exception => {
|
LoggingLevel::Exception => {
|
||||||
if checker
|
if checker
|
||||||
.settings
|
.settings
|
||||||
.rules
|
.rules
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::call_path::collect_call_path;
|
use ruff_python_ast::call_path::collect_call_path;
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ use rustpython_parser::ast::{
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Violation};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, AutofixKind, Diagnostic, Edit, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::comparable::ComparableExpr;
|
use ruff_python_ast::comparable::ComparableExpr;
|
||||||
use ruff_python_ast::context::Context;
|
|
||||||
use ruff_python_ast::helpers::{contains_effect, create_expr, has_comments, unparse_expr};
|
use ruff_python_ast::helpers::{contains_effect, create_expr, has_comments, unparse_expr};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::context::Context;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,12 @@ use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::comparable::{ComparableConstant, ComparableExpr, ComparableStmt};
|
use ruff_python_ast::comparable::{ComparableConstant, ComparableExpr, ComparableStmt};
|
||||||
use ruff_python_ast::helpers::{
|
use ruff_python_ast::helpers::{
|
||||||
contains_call_path, contains_effect, create_expr, create_stmt, first_colon_range, has_comments,
|
any_over_expr, contains_effect, create_expr, create_stmt, first_colon_range, has_comments,
|
||||||
has_comments_in, unparse_expr, unparse_stmt,
|
has_comments_in, unparse_expr, unparse_stmt,
|
||||||
};
|
};
|
||||||
use ruff_python_ast::newlines::StrExt;
|
use ruff_python_ast::newlines::StrExt;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::context::Context;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
|
@ -415,6 +416,14 @@ fn ternary(target_var: &Expr, body_value: &Expr, test: &Expr, orelse_value: &Exp
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return `true` if the `Expr` contains a reference to `${module}.${target}`.
|
||||||
|
fn contains_call_path(ctx: &Context, expr: &Expr, target: &[&str]) -> bool {
|
||||||
|
any_over_expr(expr, &|expr| {
|
||||||
|
ctx.resolve_call_path(expr)
|
||||||
|
.map_or(false, |call_path| call_path.as_slice() == target)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// SIM108
|
/// SIM108
|
||||||
pub fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: Option<&Stmt>) {
|
pub fn use_ternary_operator(checker: &mut Checker, stmt: &Stmt, parent: Option<&Stmt>) {
|
||||||
let StmtKind::If { test, body, orelse } = &stmt.node else {
|
let StmtKind::If { test, body, orelse } = &stmt.node else {
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use rustpython_parser::ast::{Cmpop, Expr, ExprKind, Stmt, StmtKind, Unaryop};
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::{create_expr, unparse_expr};
|
use ruff_python_ast::helpers::{create_expr, unparse_expr};
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
use num_traits::Zero;
|
use num_traits::Zero;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_python_ast::binding::{Binding, BindingKind, ExecutionContext};
|
|
||||||
use ruff_python_ast::call_path::from_qualified_name;
|
use ruff_python_ast::call_path::from_qualified_name;
|
||||||
use ruff_python_ast::context::Context;
|
|
||||||
use ruff_python_ast::helpers::map_callable;
|
use ruff_python_ast::helpers::map_callable;
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
use ruff_python_semantic::binding::{Binding, BindingKind, ExecutionContext};
|
||||||
|
use ruff_python_semantic::context::Context;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
/// Return `true` if [`Expr`] is a guard for a type-checking block.
|
/// Return `true` if [`Expr`] is a guard for a type-checking block.
|
||||||
pub fn is_type_checking_block(context: &Context, test: &Expr) -> bool {
|
pub fn is_type_checking_block(context: &Context, test: &Expr) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::binding::{
|
use ruff_python_semantic::binding::{
|
||||||
Binding, BindingKind, ExecutionContext, FromImportation, Importation, SubmoduleImportation,
|
Binding, BindingKind, ExecutionContext, FromImportation, Importation, SubmoduleImportation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::path::Path;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::binding::{
|
use ruff_python_semantic::binding::{
|
||||||
Binding, BindingKind, ExecutionContext, FromImportation, Importation, SubmoduleImportation,
|
Binding, BindingKind, ExecutionContext, FromImportation, Importation, SubmoduleImportation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ use rustpython_parser::ast::{Arg, Arguments};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::binding::Bindings;
|
use ruff_python_semantic::analyze::function_type;
|
||||||
use ruff_python_ast::function_type;
|
use ruff_python_semantic::analyze::function_type::FunctionType;
|
||||||
use ruff_python_ast::function_type::FunctionType;
|
use ruff_python_semantic::analyze::visibility;
|
||||||
use ruff_python_ast::scope::{FunctionDef, Lambda, Scope, ScopeKind};
|
use ruff_python_semantic::binding::Bindings;
|
||||||
use ruff_python_ast::visibility;
|
use ruff_python_semantic::scope::{FunctionDef, Lambda, Scope, ScopeKind};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
use ruff_diagnostics::Violation;
|
use ruff_diagnostics::Violation;
|
||||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::binding::BindingKind;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::binding::BindingKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
use ruff_diagnostics::Violation;
|
use ruff_diagnostics::Violation;
|
||||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::binding::{BindingKind, Importation};
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::binding::{BindingKind, Importation};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ use rustpython_parser::ast::Stmt;
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::identifier_range;
|
use ruff_python_ast::helpers::identifier_range;
|
||||||
use ruff_python_ast::scope::{Scope, ScopeKind};
|
|
||||||
use ruff_python_ast::source_code::Locator;
|
use ruff_python_ast::source_code::Locator;
|
||||||
|
use ruff_python_semantic::scope::{Scope, ScopeKind};
|
||||||
|
|
||||||
/// ## What it does
|
/// ## What it does
|
||||||
/// Checks for functions with "dunder" names (that is, names with two
|
/// Checks for functions with "dunder" names (that is, names with two
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ use rustpython_parser::ast::{Arguments, Expr};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::function_type;
|
|
||||||
use ruff_python_ast::scope::Scope;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::analyze::function_type;
|
||||||
|
use ruff_python_semantic::scope::Scope;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ use rustpython_parser::ast::{Arguments, Expr};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::function_type;
|
|
||||||
use ruff_python_ast::scope::Scope;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::analyze::function_type;
|
||||||
|
use ruff_python_semantic::scope::Scope;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::{match_leading_content, match_trailing_content, unparse_stmt};
|
use ruff_python_ast::helpers::{match_leading_content, match_trailing_content, unparse_stmt};
|
||||||
use ruff_python_ast::newlines::StrExt;
|
use ruff_python_ast::newlines::StrExt;
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
|
||||||
use ruff_python_ast::source_code::Stylist;
|
use ruff_python_ast::source_code::Stylist;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::whitespace::leading_space;
|
use ruff_python_ast::whitespace::leading_space;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::cast;
|
use ruff_python_ast::cast;
|
||||||
use ruff_python_ast::helpers::identifier_range;
|
use ruff_python_ast::helpers::identifier_range;
|
||||||
use ruff_python_ast::visibility::is_overload;
|
use ruff_python_semantic::analyze::visibility::is_overload;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use ruff_python_ast::call_path::{from_qualified_name, CallPath};
|
||||||
use ruff_python_ast::cast;
|
use ruff_python_ast::cast;
|
||||||
use ruff_python_ast::newlines::StrExt;
|
use ruff_python_ast::newlines::StrExt;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::visibility::{is_property, is_test};
|
use ruff_python_semantic::analyze::visibility::{is_property, is_test};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::cast;
|
use ruff_python_ast::cast;
|
||||||
use ruff_python_ast::helpers::identifier_range;
|
use ruff_python_ast::helpers::identifier_range;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::visibility::{
|
use ruff_python_semantic::analyze::visibility::{
|
||||||
is_call, is_init, is_magic, is_new, is_overload, is_override, Visibility,
|
is_call, is_init, is_magic, is_new, is_overload, is_override, Visibility,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::identifier_range;
|
use ruff_python_ast::helpers::identifier_range;
|
||||||
use ruff_python_ast::newlines::NewlineWithTrailingNewline;
|
use ruff_python_ast::newlines::NewlineWithTrailingNewline;
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
use ruff_python_ast::visibility::is_staticmethod;
|
|
||||||
use ruff_python_ast::{cast, whitespace};
|
use ruff_python_ast::{cast, whitespace};
|
||||||
|
use ruff_python_semantic::analyze::visibility::is_staticmethod;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
use crate::docstrings::definition::{DefinitionKind, Docstring};
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use rustpython_parser::ast::Stmt;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::scope::Scope;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::Scope;
|
||||||
|
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct UndefinedExport {
|
pub struct UndefinedExport {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use std::string::ToString;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::binding::Bindings;
|
use ruff_python_semantic::binding::Bindings;
|
||||||
use ruff_python_ast::scope::{Scope, ScopeKind};
|
use ruff_python_semantic::scope::{Scope, ScopeKind};
|
||||||
|
|
||||||
#[violation]
|
#[violation]
|
||||||
pub struct UndefinedLocal {
|
pub struct UndefinedLocal {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::scope::ScopeId;
|
use ruff_python_semantic::scope::ScopeId;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ use rustpython_parser::{lexer, Mode, Tok};
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::contains_effect;
|
use ruff_python_ast::helpers::contains_effect;
|
||||||
use ruff_python_ast::scope::{ScopeId, ScopeKind};
|
|
||||||
use ruff_python_ast::source_code::Locator;
|
use ruff_python_ast::source_code::Locator;
|
||||||
use ruff_python_ast::types::{Range, RefEquality};
|
use ruff_python_ast::types::{Range, RefEquality};
|
||||||
|
use ruff_python_semantic::scope::{ScopeId, ScopeKind};
|
||||||
|
|
||||||
use crate::autofix::actions::delete_stmt;
|
use crate::autofix::actions::delete_stmt;
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use ruff_python_ast::function_type;
|
use ruff_python_semantic::analyze::function_type;
|
||||||
use ruff_python_ast::function_type::FunctionType;
|
use ruff_python_semantic::analyze::function_type::FunctionType;
|
||||||
use ruff_python_ast::scope::{FunctionDef, ScopeKind};
|
use ruff_python_semantic::scope::{FunctionDef, ScopeKind};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use rustpython_parser::ast::Expr;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::scope::{FunctionDef, ScopeKind};
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::{FunctionDef, ScopeKind};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use rustpython_parser::ast::Expr;
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::helpers::SimpleCallArgs;
|
use ruff_python_ast::helpers::SimpleCallArgs;
|
||||||
use ruff_python_ast::logging;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::analyze::logging;
|
||||||
|
use ruff_python_stdlib::logging::LoggingLevel;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
|
|
@ -105,7 +106,7 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ExprKind::Attribute { attr, .. } = &func.node {
|
if let ExprKind::Attribute { attr, .. } = &func.node {
|
||||||
if logging::LoggingLevel::from_attribute(attr.as_str()).is_some() {
|
if LoggingLevel::from_attribute(attr.as_str()).is_some() {
|
||||||
let call_args = SimpleCallArgs::new(args, keywords);
|
let call_args = SimpleCallArgs::new(args, keywords);
|
||||||
if let Some(msg) = call_args.argument("msg", 0) {
|
if let Some(msg) = call_args.argument("msg", 0) {
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Expr, ExprContext
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::call_path::compose_call_path;
|
use ruff_python_ast::call_path::compose_call_path;
|
||||||
use ruff_python_ast::context::Context;
|
|
||||||
use ruff_python_ast::helpers::{create_expr, unparse_expr};
|
use ruff_python_ast::helpers::{create_expr, unparse_expr};
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::context::Context;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use rustpython_parser::ast::{ArgData, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::scope::ScopeKind;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::scope::ScopeKind;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ use rustpython_parser::ast::{Expr, ExprKind, Keyword, Stmt};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
use ruff_python_ast::binding::{Binding, BindingKind, Bindings};
|
|
||||||
use ruff_python_ast::scope::Scope;
|
|
||||||
use ruff_python_ast::types::Range;
|
use ruff_python_ast::types::Range;
|
||||||
|
use ruff_python_semantic::binding::{Binding, BindingKind, Bindings};
|
||||||
|
use ruff_python_semantic::scope::Scope;
|
||||||
|
|
||||||
use crate::autofix::actions::remove_argument;
|
use crate::autofix::actions::remove_argument;
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_python_ast::context::Context;
|
use ruff_python_ast::visitor;
|
||||||
use ruff_python_ast::visitor::Visitor;
|
use ruff_python_ast::visitor::Visitor;
|
||||||
use ruff_python_ast::{logging, visitor};
|
use ruff_python_semantic::analyze::logging;
|
||||||
|
use ruff_python_semantic::context::Context;
|
||||||
|
|
||||||
/// Collect `logging`-like calls from an AST.
|
/// Collect `logging`-like calls from an AST.
|
||||||
pub struct LoggerCandidateVisitor<'a> {
|
pub struct LoggerCandidateVisitor<'a> {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ rust-version = { workspace = true }
|
||||||
[lib]
|
[lib]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
|
||||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||||
|
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
|
|
@ -16,7 +15,6 @@ bitflags = { workspace = true }
|
||||||
is-macro = { workspace = true }
|
is-macro = { workspace = true }
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
nohash-hasher = { version = "0.2.0" }
|
|
||||||
num-bigint = { version = "0.4.3" }
|
num-bigint = { version = "0.4.3" }
|
||||||
num-traits = { version = "0.2.15" }
|
num-traits = { version = "0.2.15" }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
|
|
@ -25,4 +23,4 @@ rustc-hash = { workspace = true }
|
||||||
rustpython-common = { workspace = true }
|
rustpython-common = { workspace = true }
|
||||||
rustpython-parser = { workspace = true }
|
rustpython-parser = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
smallvec = { version = "1.10.0" }
|
smallvec = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ use rustpython_parser::{lexer, Mode, Tok};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::call_path::CallPath;
|
use crate::call_path::CallPath;
|
||||||
use crate::context::Context;
|
|
||||||
use crate::source_code::{Generator, Indexer, Locator, Stylist};
|
use crate::source_code::{Generator, Indexer, Locator, Stylist};
|
||||||
use crate::types::Range;
|
use crate::types::Range;
|
||||||
use crate::visitor;
|
use crate::visitor;
|
||||||
|
|
@ -50,14 +49,6 @@ pub fn unparse_constant(constant: &Constant, stylist: &Stylist) -> String {
|
||||||
generator.generate()
|
generator.generate()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if the `Expr` contains a reference to `${module}.${target}`.
|
|
||||||
pub fn contains_call_path(ctx: &Context, expr: &Expr, target: &[&str]) -> bool {
|
|
||||||
any_over_expr(expr, &|expr| {
|
|
||||||
ctx.resolve_call_path(expr)
|
|
||||||
.map_or(false, |call_path| call_path.as_slice() == target)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` if the `Expr` contains an expression that appears to include a
|
/// Return `true` if the `Expr` contains an expression that appears to include a
|
||||||
/// side-effect (like a function call).
|
/// side-effect (like a function call).
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,17 @@
|
||||||
pub mod all;
|
pub mod all;
|
||||||
pub mod binding;
|
|
||||||
pub mod branch_detection;
|
pub mod branch_detection;
|
||||||
pub mod call_path;
|
pub mod call_path;
|
||||||
pub mod cast;
|
pub mod cast;
|
||||||
pub mod comparable;
|
pub mod comparable;
|
||||||
pub mod context;
|
|
||||||
pub mod function_type;
|
|
||||||
pub mod hashable;
|
pub mod hashable;
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
pub mod imports;
|
pub mod imports;
|
||||||
pub mod logging;
|
|
||||||
pub mod newlines;
|
pub mod newlines;
|
||||||
pub mod relocate;
|
pub mod relocate;
|
||||||
pub mod scope;
|
|
||||||
pub mod source_code;
|
pub mod source_code;
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod token_kind;
|
pub mod token_kind;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub mod typing;
|
pub mod typing;
|
||||||
pub mod visibility;
|
|
||||||
pub mod visitor;
|
pub mod visitor;
|
||||||
pub mod whitespace;
|
pub mod whitespace;
|
||||||
|
|
|
||||||
|
|
@ -1,80 +1,12 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use rustpython_parser as parser;
|
use rustpython_parser as parser;
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Location};
|
use rustpython_parser::ast::{Expr, Location};
|
||||||
|
|
||||||
use ruff_python_stdlib::typing::{PEP_585_BUILTINS_ELIGIBLE, PEP_593_SUBSCRIPTS, SUBSCRIPTS};
|
|
||||||
|
|
||||||
use crate::call_path::{from_unqualified_name, CallPath};
|
|
||||||
use crate::context::Context;
|
|
||||||
use crate::relocate::relocate_expr;
|
use crate::relocate::relocate_expr;
|
||||||
use crate::source_code::Locator;
|
use crate::source_code::Locator;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
use crate::types::Range;
|
use crate::types::Range;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub enum Callable {
|
|
||||||
Cast,
|
|
||||||
NewType,
|
|
||||||
TypeVar,
|
|
||||||
NamedTuple,
|
|
||||||
TypedDict,
|
|
||||||
MypyExtension,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub enum SubscriptKind {
|
|
||||||
AnnotatedSubscript,
|
|
||||||
PEP593AnnotatedSubscript,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn match_annotated_subscript<'a>(
|
|
||||||
expr: &Expr,
|
|
||||||
context: &Context,
|
|
||||||
typing_modules: impl Iterator<Item = &'a str>,
|
|
||||||
) -> Option<SubscriptKind> {
|
|
||||||
if !matches!(
|
|
||||||
expr.node,
|
|
||||||
ExprKind::Name { .. } | ExprKind::Attribute { .. }
|
|
||||||
) {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.resolve_call_path(expr).and_then(|call_path| {
|
|
||||||
if SUBSCRIPTS.contains(&call_path.as_slice()) {
|
|
||||||
return Some(SubscriptKind::AnnotatedSubscript);
|
|
||||||
}
|
|
||||||
if PEP_593_SUBSCRIPTS.contains(&call_path.as_slice()) {
|
|
||||||
return Some(SubscriptKind::PEP593AnnotatedSubscript);
|
|
||||||
}
|
|
||||||
|
|
||||||
for module in typing_modules {
|
|
||||||
let module_call_path: CallPath = from_unqualified_name(module);
|
|
||||||
if call_path.starts_with(&module_call_path) {
|
|
||||||
for subscript in SUBSCRIPTS.iter() {
|
|
||||||
if call_path.last() == subscript.last() {
|
|
||||||
return Some(SubscriptKind::AnnotatedSubscript);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for subscript in PEP_593_SUBSCRIPTS.iter() {
|
|
||||||
if call_path.last() == subscript.last() {
|
|
||||||
return Some(SubscriptKind::PEP593AnnotatedSubscript);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if `Expr` represents a reference to a typing object with a
|
|
||||||
/// PEP 585 built-in.
|
|
||||||
pub fn is_pep585_builtin(expr: &Expr, context: &Context) -> bool {
|
|
||||||
context.resolve_call_path(expr).map_or(false, |call_path| {
|
|
||||||
PEP_585_BUILTINS_ELIGIBLE.contains(&call_path.as_slice())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(is_macro::Is, Copy, Clone)]
|
#[derive(is_macro::Is, Copy, Clone)]
|
||||||
pub enum AnnotationKind {
|
pub enum AnnotationKind {
|
||||||
/// The annotation is defined as part a simple string literal,
|
/// The annotation is defined as part a simple string literal,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ rust-version = { workspace = true }
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ruff_formatter = { path = "../ruff_formatter" }
|
ruff_formatter = { path = "../ruff_formatter" }
|
||||||
ruff_python_ast = { path = "../ruff_python_ast" }
|
ruff_python_ast = { path = "../ruff_python_ast" }
|
||||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
|
||||||
ruff_rustpython = { path = "../ruff_rustpython" }
|
ruff_rustpython = { path = "../ruff_rustpython" }
|
||||||
ruff_text_size = { path = "../ruff_text_size" }
|
ruff_text_size = { path = "../ruff_text_size" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "ruff_python_semantic"
|
||||||
|
version = "0.0.0"
|
||||||
|
publish = false
|
||||||
|
edition = { workspace = true }
|
||||||
|
rust-version = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ruff_python_ast = { path = "../ruff_python_ast" }
|
||||||
|
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
||||||
|
|
||||||
|
bitflags = { workspace = true }
|
||||||
|
is-macro = { workspace = true }
|
||||||
|
nohash-hasher = { workspace = true }
|
||||||
|
rustc-hash = { workspace = true }
|
||||||
|
rustpython-parser = { workspace = true }
|
||||||
|
smallvec = { workspace = true }
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use rustpython_parser::ast::Expr;
|
use rustpython_parser::ast::Expr;
|
||||||
|
|
||||||
use crate::call_path::from_qualified_name;
|
use ruff_python_ast::call_path::from_qualified_name;
|
||||||
|
use ruff_python_ast::helpers::map_callable;
|
||||||
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::helpers::map_callable;
|
|
||||||
use crate::scope::{Scope, ScopeKind};
|
use crate::scope::{Scope, ScopeKind};
|
||||||
|
|
||||||
const CLASS_METHODS: [&str; 3] = ["__new__", "__init_subclass__", "__class_getitem__"];
|
const CLASS_METHODS: [&str; 3] = ["__new__", "__init_subclass__", "__class_getitem__"];
|
||||||
|
|
@ -1,34 +1,9 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
|
|
||||||
use crate::call_path::collect_call_path;
|
use ruff_python_ast::call_path::collect_call_path;
|
||||||
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub enum LoggingLevel {
|
|
||||||
Debug,
|
|
||||||
Critical,
|
|
||||||
Error,
|
|
||||||
Exception,
|
|
||||||
Info,
|
|
||||||
Warn,
|
|
||||||
Warning,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LoggingLevel {
|
|
||||||
pub fn from_attribute(level: &str) -> Option<Self> {
|
|
||||||
match level {
|
|
||||||
"debug" => Some(LoggingLevel::Debug),
|
|
||||||
"critical" => Some(LoggingLevel::Critical),
|
|
||||||
"error" => Some(LoggingLevel::Error),
|
|
||||||
"exception" => Some(LoggingLevel::Exception),
|
|
||||||
"info" => Some(LoggingLevel::Info),
|
|
||||||
"warn" => Some(LoggingLevel::Warn),
|
|
||||||
"warning" => Some(LoggingLevel::Warning),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` if the given `Expr` is a potential logging call. Matches
|
/// Return `true` if the given `Expr` is a potential logging call. Matches
|
||||||
/// `logging.error`, `logger.error`, `self.logger.error`, etc., but not
|
/// `logging.error`, `logger.error`, `self.logger.error`, etc., but not
|
||||||
/// arbitrary `foo.error` calls.
|
/// arbitrary `foo.error` calls.
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
pub mod function_type;
|
||||||
|
pub mod logging;
|
||||||
|
pub mod typing;
|
||||||
|
pub mod visibility;
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
use rustpython_parser::ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
use ruff_python_ast::call_path::{from_unqualified_name, CallPath};
|
||||||
|
use ruff_python_stdlib::typing::{PEP_585_BUILTINS_ELIGIBLE, PEP_593_SUBSCRIPTS, SUBSCRIPTS};
|
||||||
|
|
||||||
|
use crate::context::Context;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum Callable {
|
||||||
|
Cast,
|
||||||
|
NewType,
|
||||||
|
TypeVar,
|
||||||
|
NamedTuple,
|
||||||
|
TypedDict,
|
||||||
|
MypyExtension,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum SubscriptKind {
|
||||||
|
AnnotatedSubscript,
|
||||||
|
PEP593AnnotatedSubscript,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn match_annotated_subscript<'a>(
|
||||||
|
expr: &Expr,
|
||||||
|
context: &Context,
|
||||||
|
typing_modules: impl Iterator<Item = &'a str>,
|
||||||
|
) -> Option<SubscriptKind> {
|
||||||
|
if !matches!(
|
||||||
|
expr.node,
|
||||||
|
ExprKind::Name { .. } | ExprKind::Attribute { .. }
|
||||||
|
) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.resolve_call_path(expr).and_then(|call_path| {
|
||||||
|
if SUBSCRIPTS.contains(&call_path.as_slice()) {
|
||||||
|
return Some(SubscriptKind::AnnotatedSubscript);
|
||||||
|
}
|
||||||
|
if PEP_593_SUBSCRIPTS.contains(&call_path.as_slice()) {
|
||||||
|
return Some(SubscriptKind::PEP593AnnotatedSubscript);
|
||||||
|
}
|
||||||
|
|
||||||
|
for module in typing_modules {
|
||||||
|
let module_call_path: CallPath = from_unqualified_name(module);
|
||||||
|
if call_path.starts_with(&module_call_path) {
|
||||||
|
for subscript in SUBSCRIPTS.iter() {
|
||||||
|
if call_path.last() == subscript.last() {
|
||||||
|
return Some(SubscriptKind::AnnotatedSubscript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for subscript in PEP_593_SUBSCRIPTS.iter() {
|
||||||
|
if call_path.last() == subscript.last() {
|
||||||
|
return Some(SubscriptKind::PEP593AnnotatedSubscript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `Expr` represents a reference to a typing object with a
|
||||||
|
/// PEP 585 built-in.
|
||||||
|
pub fn is_pep585_builtin(expr: &Expr, context: &Context) -> bool {
|
||||||
|
context.resolve_call_path(expr).map_or(false, |call_path| {
|
||||||
|
PEP_585_BUILTINS_ELIGIBLE.contains(&call_path.as_slice())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -2,10 +2,10 @@ use std::path::Path;
|
||||||
|
|
||||||
use rustpython_parser::ast::{Expr, Stmt, StmtKind};
|
use rustpython_parser::ast::{Expr, Stmt, StmtKind};
|
||||||
|
|
||||||
use crate::call_path::collect_call_path;
|
use ruff_python_ast::call_path::{collect_call_path, CallPath};
|
||||||
use crate::call_path::CallPath;
|
use ruff_python_ast::helpers::map_callable;
|
||||||
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::helpers::map_callable;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Modifier {
|
pub enum Modifier {
|
||||||
|
|
@ -4,8 +4,9 @@ use std::ops::{Deref, Index, IndexMut};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use rustpython_parser::ast::Stmt;
|
use rustpython_parser::ast::Stmt;
|
||||||
|
|
||||||
|
use ruff_python_ast::types::{Range, RefEquality};
|
||||||
|
|
||||||
use crate::scope::ScopeId;
|
use crate::scope::ScopeId;
|
||||||
use crate::types::{Range, RefEquality};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Binding<'a> {
|
pub struct Binding<'a> {
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use nohash_hasher::{BuildNoHashHasher, IntMap};
|
use nohash_hasher::{BuildNoHashHasher, IntMap};
|
||||||
|
use ruff_python_ast::call_path::{collect_call_path, from_unqualified_name, CallPath};
|
||||||
|
use ruff_python_ast::helpers::from_relative_import;
|
||||||
|
use ruff_python_ast::types::RefEquality;
|
||||||
|
use ruff_python_ast::typing::AnnotationKind;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use rustpython_parser::ast::{Expr, Stmt};
|
use rustpython_parser::ast::{Expr, Stmt};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
|
||||||
|
use crate::analyze::visibility::{module_visibility, Modifier, VisibleScope};
|
||||||
use ruff_python_stdlib::path::is_python_stub_file;
|
use ruff_python_stdlib::path::is_python_stub_file;
|
||||||
use ruff_python_stdlib::typing::TYPING_EXTENSIONS;
|
use ruff_python_stdlib::typing::TYPING_EXTENSIONS;
|
||||||
|
|
||||||
|
|
@ -12,12 +17,7 @@ use crate::binding::{
|
||||||
Binding, BindingId, BindingKind, Bindings, Exceptions, ExecutionContext, FromImportation,
|
Binding, BindingId, BindingKind, Bindings, Exceptions, ExecutionContext, FromImportation,
|
||||||
Importation, SubmoduleImportation,
|
Importation, SubmoduleImportation,
|
||||||
};
|
};
|
||||||
use crate::call_path::{collect_call_path, from_unqualified_name, CallPath};
|
|
||||||
use crate::helpers::from_relative_import;
|
|
||||||
use crate::scope::{Scope, ScopeId, ScopeKind, ScopeStack, Scopes};
|
use crate::scope::{Scope, ScopeId, ScopeKind, ScopeStack, Scopes};
|
||||||
use crate::types::RefEquality;
|
|
||||||
use crate::typing::AnnotationKind;
|
|
||||||
use crate::visibility::{module_visibility, Modifier, VisibleScope};
|
|
||||||
|
|
||||||
#[allow(clippy::struct_excessive_bools)]
|
#[allow(clippy::struct_excessive_bools)]
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
pub mod analyze;
|
||||||
|
pub mod binding;
|
||||||
|
pub mod context;
|
||||||
|
pub mod scope;
|
||||||
|
|
@ -189,7 +189,7 @@ impl<'a> Scopes<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a new scope and returns its unique id
|
/// Pushes a new scope and returns its unique id
|
||||||
pub(crate) fn push_scope(&mut self, kind: ScopeKind<'a>) -> ScopeId {
|
pub fn push_scope(&mut self, kind: ScopeKind<'a>) -> ScopeId {
|
||||||
let next_id = ScopeId::try_from(self.0.len()).unwrap();
|
let next_id = ScopeId::try_from(self.0.len()).unwrap();
|
||||||
self.0.push(Scope::local(next_id, kind));
|
self.0.push(Scope::local(next_id, kind));
|
||||||
next_id
|
next_id
|
||||||
|
|
@ -2,6 +2,7 @@ pub mod builtins;
|
||||||
pub mod future;
|
pub mod future;
|
||||||
pub mod identifiers;
|
pub mod identifiers;
|
||||||
pub mod keyword;
|
pub mod keyword;
|
||||||
|
pub mod logging;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum LoggingLevel {
|
||||||
|
Debug,
|
||||||
|
Critical,
|
||||||
|
Error,
|
||||||
|
Exception,
|
||||||
|
Info,
|
||||||
|
Warn,
|
||||||
|
Warning,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoggingLevel {
|
||||||
|
pub fn from_attribute(level: &str) -> Option<Self> {
|
||||||
|
match level {
|
||||||
|
"debug" => Some(LoggingLevel::Debug),
|
||||||
|
"critical" => Some(LoggingLevel::Critical),
|
||||||
|
"error" => Some(LoggingLevel::Error),
|
||||||
|
"exception" => Some(LoggingLevel::Exception),
|
||||||
|
"info" => Some(LoggingLevel::Info),
|
||||||
|
"warn" => Some(LoggingLevel::Warn),
|
||||||
|
"warning" => Some(LoggingLevel::Warning),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue