mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 14:51:25 +00:00
Pass Checker
by immutable reference to lint rules (#16012)
This very large PR changes the field `.diagnostics` in the `Checker` from a `Vec<Diagnostic>` to a `RefCell<Vec<Diagnostic>>`, adds methods to push new diagnostics to this cell, and then removes unnecessary mutability throughout all of our lint rule implementations. Consequently, the compiler may now enforce what was, till now, the _convention_ that the only changes to the `Checker` that can happen during a lint are the addition of diagnostics[^1]. The PR is best reviewed commit-by-commit. I have tried to keep the large commits limited to "bulk actions that you can easily see are performing the same find/replace on a large number of files", and separate anything ad-hoc or with larger diffs. Please let me know if there's anything else I can do to make this easier to review! Many thanks to [`ast-grep`](https://github.com/ast-grep/ast-grep), [`helix`](https://github.com/helix-editor/helix), and good ol' fashioned`git` magic, without which this PR would have taken the rest of my natural life. [^1]: And randomly also the seen variables violating `flake8-bugbear`?
This commit is contained in:
parent
1f7a29d347
commit
46fe17767d
552 changed files with 1751 additions and 2288 deletions
|
@ -9,7 +9,7 @@ use crate::rules::{
|
|||
};
|
||||
|
||||
/// Run lint rules over the [`Binding`]s.
|
||||
pub(crate) fn bindings(checker: &mut Checker) {
|
||||
pub(crate) fn bindings(checker: &Checker) {
|
||||
if !checker.any_enabled(&[
|
||||
Rule::AssignmentInAssert,
|
||||
Rule::InvalidAllFormat,
|
||||
|
@ -48,22 +48,22 @@ pub(crate) fn bindings(checker: &mut Checker) {
|
|||
pyflakes::fixes::remove_exception_handler_assignment(binding, checker.locator)
|
||||
.map(Fix::safe_edit)
|
||||
});
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::InvalidAllFormat) {
|
||||
if let Some(diagnostic) = pylint::rules::invalid_all_format(binding) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::InvalidAllObject) {
|
||||
if let Some(diagnostic) = pylint::rules::invalid_all_object(binding) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::NonAsciiName) {
|
||||
if let Some(diagnostic) = pylint::rules::non_ascii_name(binding, checker.locator) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::UnconventionalImportAlias) {
|
||||
|
@ -72,61 +72,61 @@ pub(crate) fn bindings(checker: &mut Checker) {
|
|||
binding,
|
||||
&checker.settings.flake8_import_conventions.aliases,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::UnaliasedCollectionsAbcSetImport) {
|
||||
if let Some(diagnostic) =
|
||||
flake8_pyi::rules::unaliased_collections_abc_set_import(checker, binding)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if !checker.source_type.is_stub() && checker.enabled(Rule::UnquotedTypeAlias) {
|
||||
if let Some(diagnostics) =
|
||||
flake8_type_checking::rules::unquoted_type_alias(checker, binding)
|
||||
{
|
||||
checker.diagnostics.extend(diagnostics);
|
||||
checker.report_diagnostics(diagnostics);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::UnsortedDunderSlots) {
|
||||
if let Some(diagnostic) = ruff::rules::sort_dunder_slots(checker, binding) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::UsedDummyVariable) {
|
||||
if let Some(diagnostic) = ruff::rules::used_dummy_variable(checker, binding, binding_id)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::AssignmentInAssert) {
|
||||
if let Some(diagnostic) = ruff::rules::assignment_in_assert(checker, binding) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::PytestUnittestRaisesAssertion) {
|
||||
if let Some(diagnostic) =
|
||||
flake8_pytest_style::rules::unittest_raises_assertion_binding(checker, binding)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::ForLoopWrites) {
|
||||
if let Some(diagnostic) = refurb::rules::for_loop_writes_binding(checker, binding) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::CustomTypeVarForSelf) {
|
||||
if let Some(diagnostic) =
|
||||
flake8_pyi::rules::custom_type_var_instead_of_self(checker, binding)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::PrivateTypeParameter) {
|
||||
if let Some(diagnostic) = pyupgrade::rules::private_type_parameter(checker, binding) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::codes::Rule;
|
|||
use crate::rules::{flake8_simplify, pylint, refurb};
|
||||
|
||||
/// Run lint rules over a [`Comprehension`] syntax nodes.
|
||||
pub(crate) fn comprehension(comprehension: &Comprehension, checker: &mut Checker) {
|
||||
pub(crate) fn comprehension(comprehension: &Comprehension, checker: &Checker) {
|
||||
if checker.enabled(Rule::InDictKeys) {
|
||||
flake8_simplify::rules::key_in_dict_comprehension(checker, comprehension);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::rules::{
|
|||
};
|
||||
|
||||
/// Run lint rules over all deferred scopes in the [`SemanticModel`].
|
||||
pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
||||
pub(crate) fn deferred_scopes(checker: &Checker) {
|
||||
if !checker.any_enabled(&[
|
||||
Rule::AsyncioDanglingTask,
|
||||
Rule::BadStaticmethodArgument,
|
||||
|
@ -85,12 +85,11 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
vec![]
|
||||
};
|
||||
|
||||
let mut diagnostics: Vec<Diagnostic> = vec![];
|
||||
for scope_id in checker.analyze.scopes.iter().rev().copied() {
|
||||
let scope = &checker.semantic.scopes[scope_id];
|
||||
|
||||
if checker.enabled(Rule::UndefinedLocal) {
|
||||
pyflakes::rules::undefined_local(checker, scope_id, scope, &mut diagnostics);
|
||||
pyflakes::rules::undefined_local(checker, scope_id, scope);
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::GlobalVariableNotAssigned) {
|
||||
|
@ -112,7 +111,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
.map(|id| checker.semantic.reference(*id))
|
||||
.all(ResolvedReference::is_load)
|
||||
{
|
||||
diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pylint::rules::GlobalVariableNotAssigned {
|
||||
name: (*name).to_string(),
|
||||
},
|
||||
|
@ -146,7 +145,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
if scope.kind.is_generator() {
|
||||
continue;
|
||||
}
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pylint::rules::RedefinedArgumentFromLocal {
|
||||
name: name.to_string(),
|
||||
},
|
||||
|
@ -186,7 +185,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
continue;
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::ImportShadowedByLoopVar {
|
||||
name: name.to_string(),
|
||||
row: checker.compute_source_row(shadowed.start()),
|
||||
|
@ -347,7 +346,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
diagnostic.set_fix(fix.clone());
|
||||
}
|
||||
|
||||
diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -356,55 +355,47 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
|| matches!(scope.kind, ScopeKind::Module | ScopeKind::Function(_))
|
||||
{
|
||||
if checker.enabled(Rule::UnusedPrivateTypeVar) {
|
||||
flake8_pyi::rules::unused_private_type_var(checker, scope, &mut diagnostics);
|
||||
flake8_pyi::rules::unused_private_type_var(checker, scope);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateProtocol) {
|
||||
flake8_pyi::rules::unused_private_protocol(checker, scope, &mut diagnostics);
|
||||
flake8_pyi::rules::unused_private_protocol(checker, scope);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateTypeAlias) {
|
||||
flake8_pyi::rules::unused_private_type_alias(checker, scope, &mut diagnostics);
|
||||
flake8_pyi::rules::unused_private_type_alias(checker, scope);
|
||||
}
|
||||
if checker.enabled(Rule::UnusedPrivateTypedDict) {
|
||||
flake8_pyi::rules::unused_private_typed_dict(checker, scope, &mut diagnostics);
|
||||
flake8_pyi::rules::unused_private_typed_dict(checker, scope);
|
||||
}
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::AsyncioDanglingTask) {
|
||||
ruff::rules::asyncio_dangling_binding(scope, &checker.semantic, &mut diagnostics);
|
||||
ruff::rules::asyncio_dangling_binding(scope, checker);
|
||||
}
|
||||
|
||||
if let Some(class_def) = scope.kind.as_class() {
|
||||
if checker.enabled(Rule::BuiltinAttributeShadowing) {
|
||||
flake8_builtins::rules::builtin_attribute_shadowing(
|
||||
checker,
|
||||
scope_id,
|
||||
scope,
|
||||
class_def,
|
||||
&mut diagnostics,
|
||||
checker, scope_id, scope, class_def,
|
||||
);
|
||||
}
|
||||
if checker.enabled(Rule::FunctionCallInDataclassDefaultArgument) {
|
||||
ruff::rules::function_call_in_dataclass_default(
|
||||
checker,
|
||||
class_def,
|
||||
&mut diagnostics,
|
||||
);
|
||||
ruff::rules::function_call_in_dataclass_default(checker, class_def);
|
||||
}
|
||||
if checker.enabled(Rule::MutableClassDefault) {
|
||||
ruff::rules::mutable_class_default(checker, class_def, &mut diagnostics);
|
||||
ruff::rules::mutable_class_default(checker, class_def);
|
||||
}
|
||||
if checker.enabled(Rule::MutableDataclassDefault) {
|
||||
ruff::rules::mutable_dataclass_default(checker, class_def, &mut diagnostics);
|
||||
ruff::rules::mutable_dataclass_default(checker, class_def);
|
||||
}
|
||||
}
|
||||
|
||||
if matches!(scope.kind, ScopeKind::Function(_) | ScopeKind::Lambda(_)) {
|
||||
if checker.enabled(Rule::UnusedVariable) {
|
||||
pyflakes::rules::unused_variable(checker, scope, &mut diagnostics);
|
||||
pyflakes::rules::unused_variable(checker, scope);
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::UnusedAnnotation) {
|
||||
pyflakes::rules::unused_annotation(checker, scope, &mut diagnostics);
|
||||
pyflakes::rules::unused_annotation(checker, scope);
|
||||
}
|
||||
|
||||
if !checker.source_type.is_stub() {
|
||||
|
@ -415,11 +406,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
Rule::UnusedMethodArgument,
|
||||
Rule::UnusedStaticMethodArgument,
|
||||
]) {
|
||||
flake8_unused_arguments::rules::unused_arguments(
|
||||
checker,
|
||||
scope,
|
||||
&mut diagnostics,
|
||||
);
|
||||
flake8_unused_arguments::rules::unused_arguments(checker, scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -428,11 +415,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
if !checker.source_type.is_stub()
|
||||
&& checker.enabled(Rule::RuntimeImportInTypeCheckingBlock)
|
||||
{
|
||||
flake8_type_checking::rules::runtime_import_in_type_checking_block(
|
||||
checker,
|
||||
scope,
|
||||
&mut diagnostics,
|
||||
);
|
||||
flake8_type_checking::rules::runtime_import_in_type_checking_block(checker, scope);
|
||||
}
|
||||
if enforce_typing_only_imports {
|
||||
let runtime_imports: Vec<&Binding> = checker
|
||||
|
@ -447,47 +430,45 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
|||
checker,
|
||||
scope,
|
||||
&runtime_imports,
|
||||
&mut diagnostics,
|
||||
);
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::UnusedImport) {
|
||||
pyflakes::rules::unused_import(checker, scope, &mut diagnostics);
|
||||
pyflakes::rules::unused_import(checker, scope);
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::ImportPrivateName) {
|
||||
pylint::rules::import_private_name(checker, scope, &mut diagnostics);
|
||||
pylint::rules::import_private_name(checker, scope);
|
||||
}
|
||||
}
|
||||
|
||||
if scope.kind.is_function() {
|
||||
if checker.enabled(Rule::NoSelfUse) {
|
||||
pylint::rules::no_self_use(checker, scope_id, scope, &mut diagnostics);
|
||||
pylint::rules::no_self_use(checker, scope_id, scope);
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::TooManyLocals) {
|
||||
pylint::rules::too_many_locals(checker, scope, &mut diagnostics);
|
||||
pylint::rules::too_many_locals(checker, scope);
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::SingledispatchMethod) {
|
||||
pylint::rules::singledispatch_method(checker, scope, &mut diagnostics);
|
||||
pylint::rules::singledispatch_method(checker, scope);
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::SingledispatchmethodFunction) {
|
||||
pylint::rules::singledispatchmethod_function(checker, scope, &mut diagnostics);
|
||||
pylint::rules::singledispatchmethod_function(checker, scope);
|
||||
}
|
||||
|
||||
if checker.enabled(Rule::BadStaticmethodArgument) {
|
||||
pylint::rules::bad_staticmethod_argument(checker, scope, &mut diagnostics);
|
||||
pylint::rules::bad_staticmethod_argument(checker, scope);
|
||||
}
|
||||
|
||||
if checker.any_enabled(&[
|
||||
Rule::InvalidFirstArgumentNameForClassMethod,
|
||||
Rule::InvalidFirstArgumentNameForMethod,
|
||||
]) {
|
||||
pep8_naming::rules::invalid_first_argument_name(checker, scope, &mut diagnostics);
|
||||
pep8_naming::rules::invalid_first_argument_name(checker, scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
checker.diagnostics.extend(diagnostics);
|
||||
}
|
||||
|
|
|
@ -139,13 +139,11 @@ pub(crate) fn definitions(checker: &mut Checker) {
|
|||
&checker.semantic,
|
||||
)
|
||||
}) {
|
||||
checker
|
||||
.diagnostics
|
||||
.extend(flake8_annotations::rules::definition(
|
||||
checker,
|
||||
definition,
|
||||
*visibility,
|
||||
));
|
||||
checker.report_diagnostics(flake8_annotations::rules::definition(
|
||||
checker,
|
||||
definition,
|
||||
*visibility,
|
||||
));
|
||||
}
|
||||
overloaded_name =
|
||||
flake8_annotations::helpers::overloaded_name(definition, &checker.semantic);
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::rules::{
|
|||
};
|
||||
|
||||
/// Run lint rules over an [`ExceptHandler`] syntax node.
|
||||
pub(crate) fn except_handler(except_handler: &ExceptHandler, checker: &mut Checker) {
|
||||
pub(crate) fn except_handler(except_handler: &ExceptHandler, checker: &Checker) {
|
||||
match except_handler {
|
||||
ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
|
||||
type_,
|
||||
|
@ -23,7 +23,7 @@ pub(crate) fn except_handler(except_handler: &ExceptHandler, checker: &mut Check
|
|||
except_handler,
|
||||
checker.locator,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::RaiseWithoutFromInsideExcept) {
|
||||
|
|
|
@ -21,7 +21,7 @@ use crate::rules::{
|
|||
use crate::settings::types::PythonVersion;
|
||||
|
||||
/// Run lint rules over an [`Expr`] syntax node.
|
||||
pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
||||
pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
||||
match expr {
|
||||
Expr::Subscript(subscript @ ast::ExprSubscript { value, slice, .. }) => {
|
||||
// Ex) Optional[...], Union[...]
|
||||
|
@ -201,7 +201,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
check_two_starred_expressions,
|
||||
expr.range(),
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
match pyflakes::format::FormatSummary::try_from(string_value.to_str()) {
|
||||
Err(e) => {
|
||||
if checker.enabled(Rule::StringDotFormatInvalidFormat) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::StringDotFormatInvalidFormat {
|
||||
message: pyflakes::format::error_to_string(&e),
|
||||
},
|
||||
|
@ -925,7 +925,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
}
|
||||
if checker.enabled(Rule::PytestPatchWithLambda) {
|
||||
if let Some(diagnostic) = flake8_pytest_style::rules::patch_with_lambda(call) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.any_enabled(&[
|
||||
|
@ -1281,7 +1281,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
..
|
||||
}) => {
|
||||
if checker.enabled(Rule::PercentFormatUnsupportedFormatCharacter) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::PercentFormatUnsupportedFormatCharacter {
|
||||
char: c,
|
||||
},
|
||||
|
@ -1291,7 +1291,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
}
|
||||
Err(e) => {
|
||||
if checker.enabled(Rule::PercentFormatInvalidFormat) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::PercentFormatInvalidFormat {
|
||||
message: e.to_string(),
|
||||
},
|
||||
|
@ -1365,7 +1365,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
checker.locator,
|
||||
checker.settings,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::CollectionLiteralConcatenation) {
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::codes::Rule;
|
|||
use crate::rules::{flake8_bugbear, ruff};
|
||||
|
||||
/// Run lint rules over a module.
|
||||
pub(crate) fn module(suite: &Suite, checker: &mut Checker) {
|
||||
pub(crate) fn module(suite: &Suite, checker: &Checker) {
|
||||
if checker.enabled(Rule::FStringDocstring) {
|
||||
flake8_bugbear::rules::f_string_docstring(checker, suite);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::codes::Rule;
|
|||
use crate::rules::{flake8_builtins, pycodestyle};
|
||||
|
||||
/// Run lint rules over a [`Parameter`] syntax node.
|
||||
pub(crate) fn parameter(parameter: &Parameter, checker: &mut Checker) {
|
||||
pub(crate) fn parameter(parameter: &Parameter, checker: &Checker) {
|
||||
if checker.enabled(Rule::AmbiguousVariableName) {
|
||||
pycodestyle::rules::ambiguous_variable_name(
|
||||
checker,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::codes::Rule;
|
|||
use crate::rules::{flake8_bugbear, flake8_pyi, ruff};
|
||||
|
||||
/// Run lint rules over a [`Parameters`] syntax node.
|
||||
pub(crate) fn parameters(parameters: &Parameters, checker: &mut Checker) {
|
||||
pub(crate) fn parameters(parameters: &Parameters, checker: &Checker) {
|
||||
if checker.enabled(Rule::FunctionCallInDefaultArgument) {
|
||||
flake8_bugbear::rules::function_call_in_argument_default(checker, parameters);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if !checker.semantic.scope_id.is_global() {
|
||||
for name in names {
|
||||
if checker.semantic.nonlocal(name).is_none() {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pylint::rules::NonlocalWithoutBinding {
|
||||
name: name.to_string(),
|
||||
},
|
||||
|
@ -59,7 +59,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
stmt,
|
||||
&mut checker.semantic.current_statements().skip(1),
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
stmt,
|
||||
&mut checker.semantic.current_statements().skip(1),
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
if checker.enabled(Rule::AmbiguousFunctionName) {
|
||||
if let Some(diagnostic) = pycodestyle::rules::ambiguous_function_name(name) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::InvalidBoolReturnType) {
|
||||
|
@ -128,7 +128,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.pep8_naming.ignore_names,
|
||||
&checker.semantic,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.source_type.is_stub() {
|
||||
|
@ -187,7 +187,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
name,
|
||||
&checker.settings.pep8_naming.ignore_names,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::GlobalStatement) {
|
||||
|
@ -239,7 +239,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
body,
|
||||
checker.settings.mccabe.max_complexity,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::HardcodedPasswordDefault) {
|
||||
|
@ -265,7 +265,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
body,
|
||||
checker.settings.pylint.max_returns,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::TooManyBranches) {
|
||||
|
@ -274,7 +274,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
body,
|
||||
checker.settings.pylint.max_branches,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::TooManyStatements) {
|
||||
|
@ -283,7 +283,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
body,
|
||||
checker.settings.pylint.max_statements,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.any_enabled(&[
|
||||
|
@ -351,9 +351,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
#[cfg(any(feature = "test-rules", test))]
|
||||
if checker.enabled(Rule::UnreachableCode) {
|
||||
checker
|
||||
.diagnostics
|
||||
.extend(pylint::rules::in_function(name, body));
|
||||
checker.report_diagnostics(pylint::rules::in_function(name, body));
|
||||
}
|
||||
if checker.enabled(Rule::ReimplementedOperator) {
|
||||
refurb::rules::reimplemented_operator(checker, &function_def.into());
|
||||
|
@ -456,7 +454,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
if checker.enabled(Rule::AmbiguousClassName) {
|
||||
if let Some(diagnostic) = pycodestyle::rules::ambiguous_class_name(name) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::InvalidClassName) {
|
||||
|
@ -465,7 +463,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
name,
|
||||
&checker.settings.pep8_naming.ignore_names,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::ErrorSuffixOnExceptionName) {
|
||||
|
@ -475,7 +473,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
name,
|
||||
&checker.settings.pep8_naming.ignore_names,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if !checker.source_type.is_stub() {
|
||||
|
@ -615,7 +613,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if let Some(diagnostic) =
|
||||
flake8_debugger::rules::debugger_import(stmt, None, &alias.name)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::BannedApi) {
|
||||
|
@ -642,7 +640,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if let Some(diagnostic) =
|
||||
pylint::rules::import_self(alias, checker.module.qualified_name())
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if let Some(asname) = &alias.asname {
|
||||
|
@ -657,7 +655,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.pep8_naming.ignore_names,
|
||||
)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::LowercaseImportedAsNonLowercase) {
|
||||
|
@ -670,7 +668,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.pep8_naming.ignore_names,
|
||||
)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::CamelcaseImportedAsLowercase) {
|
||||
|
@ -683,7 +681,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.pep8_naming.ignore_names,
|
||||
)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::CamelcaseImportedAsConstant) {
|
||||
|
@ -694,14 +692,14 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
stmt,
|
||||
&checker.settings.pep8_naming.ignore_names,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::CamelcaseImportedAsAcronym) {
|
||||
if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_acronym(
|
||||
name, asname, alias, stmt, checker,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -715,7 +713,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.flake8_import_conventions.banned_aliases,
|
||||
)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -725,7 +723,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&alias.name,
|
||||
alias.asname.as_deref(),
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::BuiltinImportShadowing) {
|
||||
|
@ -841,7 +839,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if let Some(diagnostic) =
|
||||
flake8_pytest_style::rules::import_from(stmt, module, level)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.source_type.is_stub() {
|
||||
|
@ -856,7 +854,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
if checker.enabled(Rule::LateFutureImport) {
|
||||
if checker.semantic.seen_futures_boundary() {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::LateFutureImport,
|
||||
stmt.range(),
|
||||
));
|
||||
|
@ -865,7 +863,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
} else if &alias.name == "*" {
|
||||
if checker.enabled(Rule::UndefinedLocalWithNestedImportStarUsage) {
|
||||
if !matches!(checker.semantic.current_scope().kind, ScopeKind::Module) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::UndefinedLocalWithNestedImportStarUsage {
|
||||
name: helpers::format_import_from(level, module).to_string(),
|
||||
},
|
||||
|
@ -874,7 +872,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
}
|
||||
if checker.enabled(Rule::UndefinedLocalWithImportStar) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::UndefinedLocalWithImportStar {
|
||||
name: helpers::format_import_from(level, module).to_string(),
|
||||
},
|
||||
|
@ -891,14 +889,14 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
checker.module.qualified_name(),
|
||||
checker.settings.flake8_tidy_imports.ban_relative_imports,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::Debugger) {
|
||||
if let Some(diagnostic) =
|
||||
flake8_debugger::rules::debugger_import(stmt, module, &alias.name)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::BannedImportAlias) {
|
||||
|
@ -913,7 +911,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.flake8_import_conventions.banned_aliases,
|
||||
)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -928,7 +926,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.pep8_naming.ignore_names,
|
||||
)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::LowercaseImportedAsNonLowercase) {
|
||||
|
@ -941,7 +939,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.pep8_naming.ignore_names,
|
||||
)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::CamelcaseImportedAsLowercase) {
|
||||
|
@ -954,7 +952,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&checker.settings.pep8_naming.ignore_names,
|
||||
)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::CamelcaseImportedAsConstant) {
|
||||
|
@ -965,7 +963,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
stmt,
|
||||
&checker.settings.pep8_naming.ignore_names,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::CamelcaseImportedAsAcronym) {
|
||||
|
@ -976,7 +974,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
stmt,
|
||||
checker,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if !checker.source_type.is_stub() {
|
||||
|
@ -996,7 +994,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
names,
|
||||
checker.module.qualified_name(),
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::BannedImportFrom) {
|
||||
|
@ -1005,7 +1003,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
&helpers::format_import_from(level, module),
|
||||
&checker.settings.flake8_import_conventions.banned_from,
|
||||
) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::ByteStringUsage) {
|
||||
|
@ -1174,7 +1172,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
if checker.any_enabled(&[Rule::BadVersionInfoComparison, Rule::BadVersionInfoOrder]) {
|
||||
fn bad_version_info_comparison(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
test: &Expr,
|
||||
has_else_clause: bool,
|
||||
) {
|
||||
|
@ -1221,9 +1219,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
) => {
|
||||
if !checker.semantic.in_type_checking_block() {
|
||||
if checker.enabled(Rule::Assert) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(flake8_bandit::rules::assert_used(stmt));
|
||||
checker.report_diagnostic(flake8_bandit::rules::assert_used(stmt));
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::AssertTuple) {
|
||||
|
@ -1440,7 +1436,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if let Some(diagnostic) =
|
||||
pyflakes::rules::default_except_not_last(handlers, checker.locator)
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.any_enabled(&[
|
||||
|
@ -1537,7 +1533,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
}
|
||||
if checker.enabled(Rule::PandasDfVariableName) {
|
||||
if let Some(diagnostic) = pandas_vet::rules::assignment_to_df(targets) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker
|
||||
|
@ -1735,7 +1731,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
|||
if let Some(diagnostic) =
|
||||
ruff::rules::asyncio_dangling_task(value, checker.semantic())
|
||||
{
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
if checker.enabled(Rule::RepeatedAppend) {
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::codes::Rule;
|
|||
use crate::rules::{flake8_bandit, flake8_pyi, flake8_quotes, pycodestyle, ruff};
|
||||
|
||||
/// Run lint rules over a [`StringLike`] syntax nodes.
|
||||
pub(crate) fn string_like(string_like: StringLike, checker: &mut Checker) {
|
||||
pub(crate) fn string_like(string_like: StringLike, checker: &Checker) {
|
||||
if checker.any_enabled(&[
|
||||
Rule::AmbiguousUnicodeCharacterString,
|
||||
Rule::AmbiguousUnicodeCharacterDocstring,
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::rules::flake8_pie;
|
|||
use crate::rules::refurb;
|
||||
|
||||
/// Run lint rules over a suite of [`Stmt`] syntax nodes.
|
||||
pub(crate) fn suite(suite: &[Stmt], checker: &mut Checker) {
|
||||
pub(crate) fn suite(suite: &[Stmt], checker: &Checker) {
|
||||
if checker.enabled(Rule::UnnecessaryPlaceholder) {
|
||||
flake8_pie::rules::unnecessary_placeholder(checker, suite);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::codes::Rule;
|
|||
use crate::rules::pyflakes;
|
||||
|
||||
/// Run lint rules over all [`UnresolvedReference`] entities in the [`SemanticModel`].
|
||||
pub(crate) fn unresolved_references(checker: &mut Checker) {
|
||||
pub(crate) fn unresolved_references(checker: &Checker) {
|
||||
if !checker.any_enabled(&[Rule::UndefinedLocalWithImportStarUsage, Rule::UndefinedName]) {
|
||||
return;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ pub(crate) fn unresolved_references(checker: &mut Checker) {
|
|||
for reference in checker.semantic.unresolved_references() {
|
||||
if reference.is_wildcard_import() {
|
||||
if checker.enabled(Rule::UndefinedLocalWithImportStarUsage) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::UndefinedLocalWithImportStarUsage {
|
||||
name: reference.name(checker.source()).to_string(),
|
||||
},
|
||||
|
@ -42,7 +42,7 @@ pub(crate) fn unresolved_references(checker: &mut Checker) {
|
|||
|
||||
let symbol_name = reference.name(checker.source());
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::UndefinedName {
|
||||
name: symbol_name.to_string(),
|
||||
minor_version_builtin_added: version_builtin_was_added(symbol_name),
|
||||
|
|
|
@ -9,11 +9,6 @@
|
|||
//! parent scopes have been fully traversed. Individual rules may also perform internal traversals
|
||||
//! of the AST.
|
||||
//!
|
||||
//! While the [`Checker`] is typically passed by mutable reference to the individual lint rule
|
||||
//! implementations, most of its constituent components are intended to be treated immutably, with
|
||||
//! the exception of the [`Diagnostic`] vector, which is intended to be mutated by the individual
|
||||
//! lint rules. In the future, this should be formalized in the API.
|
||||
//!
|
||||
//! The individual [`Visitor`] implementations within the [`Checker`] typically proceed in four
|
||||
//! steps:
|
||||
//!
|
||||
|
@ -31,7 +26,7 @@ use std::path::Path;
|
|||
|
||||
use itertools::Itertools;
|
||||
use log::debug;
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, IsolationLevel};
|
||||
use ruff_notebook::{CellOffsets, NotebookIndex};
|
||||
|
@ -221,9 +216,9 @@ pub(crate) struct Checker<'a> {
|
|||
/// A set of deferred nodes to be analyzed after the AST traversal (e.g., `for` loops).
|
||||
analyze: deferred::Analyze,
|
||||
/// The cumulative set of diagnostics computed across all lint rules.
|
||||
pub(crate) diagnostics: Vec<Diagnostic>,
|
||||
diagnostics: RefCell<Vec<Diagnostic>>,
|
||||
/// The list of names already seen by flake8-bugbear diagnostics, to avoid duplicate violations.
|
||||
pub(crate) flake8_bugbear_seen: Vec<TextRange>,
|
||||
flake8_bugbear_seen: RefCell<FxHashSet<TextRange>>,
|
||||
/// The end offset of the last visited statement.
|
||||
last_stmt_end: TextSize,
|
||||
/// A state describing if a docstring is expected or not.
|
||||
|
@ -271,8 +266,8 @@ impl<'a> Checker<'a> {
|
|||
semantic,
|
||||
visit: deferred::Visit::default(),
|
||||
analyze: deferred::Analyze::default(),
|
||||
diagnostics: Vec::default(),
|
||||
flake8_bugbear_seen: Vec::default(),
|
||||
diagnostics: RefCell::default(),
|
||||
flake8_bugbear_seen: RefCell::default(),
|
||||
cell_offsets,
|
||||
notebook_index,
|
||||
last_stmt_end: TextSize::default(),
|
||||
|
@ -362,6 +357,30 @@ impl<'a> Checker<'a> {
|
|||
self.indexer.comment_ranges()
|
||||
}
|
||||
|
||||
/// Push a new [`Diagnostic`] to the collection in the [`Checker`]
|
||||
pub(crate) fn report_diagnostic(&self, diagnostic: Diagnostic) {
|
||||
let mut diagnostics = self.diagnostics.borrow_mut();
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
|
||||
/// Extend the collection of [`Diagnostic`] objects in the [`Checker`]
|
||||
pub(crate) fn report_diagnostics<I>(&self, diagnostics: I)
|
||||
where
|
||||
I: IntoIterator<Item = Diagnostic>,
|
||||
{
|
||||
let mut checker_diagnostics = self.diagnostics.borrow_mut();
|
||||
checker_diagnostics.extend(diagnostics);
|
||||
}
|
||||
|
||||
/// Adds a [`TextRange`] to the set of ranges of variable names
|
||||
/// flagged in `flake8-bugbear` violations so far.
|
||||
///
|
||||
/// Returns whether the value was newly inserted.
|
||||
pub(crate) fn insert_flake8_bugbear_range(&self, range: TextRange) -> bool {
|
||||
let mut ranges = self.flake8_bugbear_seen.borrow_mut();
|
||||
ranges.insert(range)
|
||||
}
|
||||
|
||||
/// Returns the [`Tokens`] for the parsed type annotation if the checker is in a typing context
|
||||
/// or the parsed source code.
|
||||
pub(crate) fn tokens(&self) -> &'a Tokens {
|
||||
|
@ -476,9 +495,9 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
|
||||
/// Push `diagnostic` if the checker is not in a `@no_type_check` context.
|
||||
pub(crate) fn push_type_diagnostic(&mut self, diagnostic: Diagnostic) {
|
||||
pub(crate) fn report_type_diagnostic(&self, diagnostic: Diagnostic) {
|
||||
if !self.semantic.in_no_type_check() {
|
||||
self.diagnostics.push(diagnostic);
|
||||
self.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2419,7 +2438,7 @@ impl<'a> Checker<'a> {
|
|||
self.semantic.restore(snapshot);
|
||||
|
||||
if self.enabled(Rule::ForwardAnnotationSyntaxError) {
|
||||
self.push_type_diagnostic(Diagnostic::new(
|
||||
self.report_type_diagnostic(Diagnostic::new(
|
||||
pyflakes::rules::ForwardAnnotationSyntaxError {
|
||||
parse_error: parse_error.error.to_string(),
|
||||
},
|
||||
|
@ -2561,7 +2580,7 @@ impl<'a> Checker<'a> {
|
|||
} else {
|
||||
if self.semantic.global_scope().uses_star_imports() {
|
||||
if self.enabled(Rule::UndefinedLocalWithImportStarUsage) {
|
||||
self.diagnostics.push(
|
||||
self.diagnostics.get_mut().push(
|
||||
Diagnostic::new(
|
||||
pyflakes::rules::UndefinedLocalWithImportStarUsage {
|
||||
name: name.to_string(),
|
||||
|
@ -2576,7 +2595,7 @@ impl<'a> Checker<'a> {
|
|||
if self.settings.preview.is_enabled()
|
||||
|| !self.path.ends_with("__init__.py")
|
||||
{
|
||||
self.diagnostics.push(
|
||||
self.diagnostics.get_mut().push(
|
||||
Diagnostic::new(
|
||||
pyflakes::rules::UndefinedExport {
|
||||
name: name.to_string(),
|
||||
|
@ -2700,13 +2719,13 @@ pub(crate) fn check_ast(
|
|||
analyze::deferred_lambdas(&mut checker);
|
||||
analyze::deferred_for_loops(&mut checker);
|
||||
analyze::definitions(&mut checker);
|
||||
analyze::bindings(&mut checker);
|
||||
analyze::unresolved_references(&mut checker);
|
||||
analyze::bindings(&checker);
|
||||
analyze::unresolved_references(&checker);
|
||||
|
||||
// Reset the scope to module-level, and check all consumed scopes.
|
||||
checker.semantic.scope_id = ScopeId::global();
|
||||
checker.analyze.scopes.push(ScopeId::global());
|
||||
analyze::deferred_scopes(&mut checker);
|
||||
analyze::deferred_scopes(&checker);
|
||||
|
||||
checker.diagnostics
|
||||
checker.diagnostics.take()
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ impl Violation for AirflowDagNoScheduleArgument {
|
|||
}
|
||||
|
||||
/// AIR301
|
||||
pub(crate) fn dag_no_schedule_argument(checker: &mut Checker, expr: &Expr) {
|
||||
pub(crate) fn dag_no_schedule_argument(checker: &Checker, expr: &Expr) {
|
||||
if !checker.semantic().seen_module(Modules::AIRFLOW) {
|
||||
return;
|
||||
}
|
||||
|
@ -86,5 +86,5 @@ pub(crate) fn dag_no_schedule_argument(checker: &mut Checker, expr: &Expr) {
|
|||
|
||||
// Produce a diagnostic when the `schedule` keyword argument is not found.
|
||||
let diagnostic = Diagnostic::new(AirflowDagNoScheduleArgument, expr.range());
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ impl Violation for Airflow3MovedToProvider {
|
|||
}
|
||||
|
||||
/// AIR303
|
||||
pub(crate) fn moved_to_provider_in_3(checker: &mut Checker, expr: &Expr) {
|
||||
pub(crate) fn moved_to_provider_in_3(checker: &Checker, expr: &Expr) {
|
||||
if !checker.semantic().seen_module(Modules::AIRFLOW) {
|
||||
return;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ enum Replacement {
|
|||
},
|
||||
}
|
||||
|
||||
fn check_names_moved_to_provider(checker: &mut Checker, expr: &Expr, ranged: TextRange) {
|
||||
fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRange) {
|
||||
let Some(qualified_name) = checker.semantic().resolve_qualified_name(expr) else {
|
||||
return;
|
||||
};
|
||||
|
@ -1018,7 +1018,7 @@ fn check_names_moved_to_provider(checker: &mut Checker, expr: &Expr, ranged: Tex
|
|||
},
|
||||
_ => return,
|
||||
};
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3MovedToProvider {
|
||||
deprecated: qualified_name.to_string(),
|
||||
replacement,
|
||||
|
|
|
@ -80,7 +80,7 @@ enum Replacement {
|
|||
}
|
||||
|
||||
/// AIR302
|
||||
pub(crate) fn airflow_3_removal_expr(checker: &mut Checker, expr: &Expr) {
|
||||
pub(crate) fn airflow_3_removal_expr(checker: &Checker, expr: &Expr) {
|
||||
if !checker.semantic().seen_module(Modules::AIRFLOW) {
|
||||
return;
|
||||
}
|
||||
|
@ -117,10 +117,7 @@ pub(crate) fn airflow_3_removal_expr(checker: &mut Checker, expr: &Expr) {
|
|||
}
|
||||
|
||||
/// AIR302
|
||||
pub(crate) fn airflow_3_removal_function_def(
|
||||
checker: &mut Checker,
|
||||
function_def: &StmtFunctionDef,
|
||||
) {
|
||||
pub(crate) fn airflow_3_removal_function_def(checker: &Checker, function_def: &StmtFunctionDef) {
|
||||
if !checker.semantic().seen_module(Modules::AIRFLOW) {
|
||||
return;
|
||||
}
|
||||
|
@ -156,7 +153,7 @@ const REMOVED_CONTEXT_KEYS: [&str; 12] = [
|
|||
/// # 'execution_date' is removed in Airflow 3.0
|
||||
/// pass
|
||||
/// ```
|
||||
fn check_function_parameters(checker: &mut Checker, function_def: &StmtFunctionDef) {
|
||||
fn check_function_parameters(checker: &Checker, function_def: &StmtFunctionDef) {
|
||||
if !is_airflow_task(function_def, checker.semantic())
|
||||
&& !is_execute_method_inherits_from_airflow_operator(function_def, checker.semantic())
|
||||
{
|
||||
|
@ -166,7 +163,7 @@ fn check_function_parameters(checker: &mut Checker, function_def: &StmtFunctionD
|
|||
for param in function_def.parameters.iter_non_variadic_params() {
|
||||
let param_name = param.name();
|
||||
if REMOVED_CONTEXT_KEYS.contains(¶m_name.as_str()) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3Removal {
|
||||
deprecated: param_name.to_string(),
|
||||
replacement: Replacement::None,
|
||||
|
@ -186,29 +183,25 @@ fn check_function_parameters(checker: &mut Checker, function_def: &StmtFunctionD
|
|||
///
|
||||
/// DAG(schedule_interval="@daily")
|
||||
/// ```
|
||||
fn check_call_arguments(
|
||||
checker: &mut Checker,
|
||||
qualified_name: &QualifiedName,
|
||||
arguments: &Arguments,
|
||||
) {
|
||||
fn check_call_arguments(checker: &Checker, qualified_name: &QualifiedName, arguments: &Arguments) {
|
||||
match qualified_name.segments() {
|
||||
["airflow", .., "DAG" | "dag"] => {
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"schedule_interval",
|
||||
Some("schedule"),
|
||||
));
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"timetable",
|
||||
Some("schedule"),
|
||||
));
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"sla_miss_callback",
|
||||
None,
|
||||
));
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"fail_stop",
|
||||
Some("fail_fast"),
|
||||
|
@ -217,7 +210,7 @@ fn check_call_arguments(
|
|||
_ => {
|
||||
if is_airflow_auth_manager(qualified_name.segments()) {
|
||||
if !arguments.is_empty() {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3Removal {
|
||||
deprecated: String::from("appbuilder"),
|
||||
replacement: Replacement::Message(
|
||||
|
@ -228,44 +221,42 @@ fn check_call_arguments(
|
|||
));
|
||||
}
|
||||
} else if is_airflow_task_handler(qualified_name.segments()) {
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"filename_template",
|
||||
None,
|
||||
));
|
||||
} else if is_airflow_operator(qualified_name.segments()) {
|
||||
checker
|
||||
.diagnostics
|
||||
.extend(diagnostic_for_argument(arguments, "sla", None));
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(arguments, "sla", None));
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"task_concurrency",
|
||||
Some("max_active_tis_per_dag"),
|
||||
));
|
||||
match qualified_name.segments() {
|
||||
["airflow", .., "operators", "trigger_dagrun", "TriggerDagRunOperator"] => {
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"execution_date",
|
||||
Some("logical_date"),
|
||||
));
|
||||
}
|
||||
["airflow", .., "operators", "datetime", "BranchDateTimeOperator"] => {
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"use_task_execution_day",
|
||||
Some("use_task_logical_date"),
|
||||
));
|
||||
}
|
||||
["airflow", .., "operators", "weekday", "DayOfWeekSensor"] => {
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"use_task_execution_day",
|
||||
Some("use_task_logical_date"),
|
||||
));
|
||||
}
|
||||
["airflow", .., "operators", "weekday", "BranchDayOfWeekOperator"] => {
|
||||
checker.diagnostics.extend(diagnostic_for_argument(
|
||||
checker.report_diagnostics(diagnostic_for_argument(
|
||||
arguments,
|
||||
"use_task_execution_day",
|
||||
Some("use_task_logical_date"),
|
||||
|
@ -288,7 +279,7 @@ fn check_call_arguments(
|
|||
/// info = DatasetLineageInfo()
|
||||
/// info.dataset
|
||||
/// ```
|
||||
fn check_class_attribute(checker: &mut Checker, attribute_expr: &ExprAttribute) {
|
||||
fn check_class_attribute(checker: &Checker, attribute_expr: &ExprAttribute) {
|
||||
let ExprAttribute { value, attr, .. } = attribute_expr;
|
||||
|
||||
let Some(qualname) = typing::resolve_assignment(value, checker.semantic()) else {
|
||||
|
@ -312,7 +303,7 @@ fn check_class_attribute(checker: &mut Checker, attribute_expr: &ExprAttribute)
|
|||
};
|
||||
|
||||
if let Some(replacement) = replacement {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3Removal {
|
||||
deprecated: attr.to_string(),
|
||||
replacement,
|
||||
|
@ -350,7 +341,7 @@ fn check_class_attribute(checker: &mut Checker, attribute_expr: &ExprAttribute)
|
|||
/// def my_task(**context):
|
||||
/// context.get("conf") # 'conf' is removed in Airflow 3.0
|
||||
/// ```
|
||||
fn check_context_key_usage_in_call(checker: &mut Checker, call_expr: &ExprCall) {
|
||||
fn check_context_key_usage_in_call(checker: &Checker, call_expr: &ExprCall) {
|
||||
if !in_airflow_task_function(checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
@ -386,7 +377,7 @@ fn check_context_key_usage_in_call(checker: &mut Checker, call_expr: &ExprCall)
|
|||
continue;
|
||||
};
|
||||
if value == removed_key {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3Removal {
|
||||
deprecated: removed_key.to_string(),
|
||||
replacement: Replacement::None,
|
||||
|
@ -399,7 +390,7 @@ fn check_context_key_usage_in_call(checker: &mut Checker, call_expr: &ExprCall)
|
|||
|
||||
/// Check if a subscript expression accesses a removed Airflow context variable.
|
||||
/// If a removed key is found, push a corresponding diagnostic.
|
||||
fn check_context_key_usage_in_subscript(checker: &mut Checker, subscript: &ExprSubscript) {
|
||||
fn check_context_key_usage_in_subscript(checker: &Checker, subscript: &ExprSubscript) {
|
||||
if !in_airflow_task_function(checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
@ -427,7 +418,7 @@ fn check_context_key_usage_in_subscript(checker: &mut Checker, subscript: &ExprS
|
|||
}
|
||||
|
||||
if REMOVED_CONTEXT_KEYS.contains(&key.to_str()) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3Removal {
|
||||
deprecated: key.to_string(),
|
||||
replacement: Replacement::None,
|
||||
|
@ -463,7 +454,7 @@ fn is_kwarg_parameter(semantic: &SemanticModel, name: &ExprName) -> bool {
|
|||
/// manager = DatasetManager()
|
||||
/// manager.register_datsaet_change()
|
||||
/// ```
|
||||
fn check_method(checker: &mut Checker, call_expr: &ExprCall) {
|
||||
fn check_method(checker: &Checker, call_expr: &ExprCall) {
|
||||
let Expr::Attribute(ExprAttribute { attr, value, .. }) = &*call_expr.func else {
|
||||
return;
|
||||
};
|
||||
|
@ -528,7 +519,7 @@ fn check_method(checker: &mut Checker, call_expr: &ExprCall) {
|
|||
}
|
||||
};
|
||||
if let Some(replacement) = replacement {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3Removal {
|
||||
deprecated: attr.to_string(),
|
||||
replacement,
|
||||
|
@ -552,7 +543,7 @@ fn check_method(checker: &mut Checker, call_expr: &ExprCall) {
|
|||
/// # Or, directly
|
||||
/// SubDagOperator()
|
||||
/// ```
|
||||
fn check_name(checker: &mut Checker, expr: &Expr, range: TextRange) {
|
||||
fn check_name(checker: &Checker, expr: &Expr, range: TextRange) {
|
||||
let Some(qualified_name) = checker.semantic().resolve_qualified_name(expr) else {
|
||||
return;
|
||||
};
|
||||
|
@ -876,7 +867,7 @@ fn check_name(checker: &mut Checker, expr: &Expr, range: TextRange) {
|
|||
_ => return,
|
||||
};
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3Removal {
|
||||
deprecated: qualified_name.to_string(),
|
||||
replacement,
|
||||
|
@ -897,7 +888,7 @@ fn check_name(checker: &mut Checker, expr: &Expr, range: TextRange) {
|
|||
/// executors = "some.third.party.executor"
|
||||
/// ```
|
||||
fn check_airflow_plugin_extension(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
expr: &Expr,
|
||||
name: &str,
|
||||
class_def: &StmtClassDef,
|
||||
|
@ -914,7 +905,7 @@ fn check_airflow_plugin_extension(
|
|||
)
|
||||
})
|
||||
}) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Airflow3Removal {
|
||||
deprecated: name.to_string(),
|
||||
replacement: Replacement::Message(
|
||||
|
|
|
@ -45,7 +45,7 @@ impl Violation for AirflowVariableNameTaskIdMismatch {
|
|||
}
|
||||
|
||||
/// AIR001
|
||||
pub(crate) fn variable_name_task_id(checker: &mut Checker, targets: &[Expr], value: &Expr) {
|
||||
pub(crate) fn variable_name_task_id(checker: &Checker, targets: &[Expr], value: &Expr) {
|
||||
if !checker.semantic().seen_module(Modules::AIRFLOW) {
|
||||
return;
|
||||
}
|
||||
|
@ -116,5 +116,5 @@ pub(crate) fn variable_name_task_id(checker: &mut Checker, targets: &[Expr], val
|
|||
},
|
||||
target.range(),
|
||||
);
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ impl Violation for FastApiNonAnnotatedDependency {
|
|||
|
||||
/// FAST002
|
||||
pub(crate) fn fastapi_non_annotated_dependency(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
function_def: &ast::StmtFunctionDef,
|
||||
) {
|
||||
if !checker.semantic().seen_module(Modules::FASTAPI)
|
||||
|
@ -219,7 +219,7 @@ impl<'a> DependencyCall<'a> {
|
|||
/// necessary to determine this while generating the fix, thus the need to return an updated
|
||||
/// `seen_default` here.
|
||||
fn create_diagnostic(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
parameter: &DependencyParameter,
|
||||
dependency_call: Option<DependencyCall>,
|
||||
mut seen_default: bool,
|
||||
|
@ -304,7 +304,7 @@ fn create_diagnostic(
|
|||
}
|
||||
diagnostic.try_set_optional_fix(|| fix);
|
||||
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
|
||||
seen_default
|
||||
}
|
||||
|
|
|
@ -74,10 +74,7 @@ impl AlwaysFixableViolation for FastApiRedundantResponseModel {
|
|||
}
|
||||
|
||||
/// FAST001
|
||||
pub(crate) fn fastapi_redundant_response_model(
|
||||
checker: &mut Checker,
|
||||
function_def: &StmtFunctionDef,
|
||||
) {
|
||||
pub(crate) fn fastapi_redundant_response_model(checker: &Checker, function_def: &StmtFunctionDef) {
|
||||
if !checker.semantic().seen_module(Modules::FASTAPI) {
|
||||
return;
|
||||
}
|
||||
|
@ -98,7 +95,7 @@ pub(crate) fn fastapi_redundant_response_model(
|
|||
)
|
||||
.map(Fix::unsafe_edit)
|
||||
});
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ impl Violation for FastApiUnusedPathParameter {
|
|||
|
||||
/// FAST003
|
||||
pub(crate) fn fastapi_unused_path_parameter(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
function_def: &ast::StmtFunctionDef,
|
||||
) {
|
||||
if !checker.semantic().seen_module(Modules::FASTAPI) {
|
||||
|
@ -163,7 +163,6 @@ pub(crate) fn fastapi_unused_path_parameter(
|
|||
}
|
||||
|
||||
// Check if any of the path parameters are not in the function signature.
|
||||
let mut diagnostics = vec![];
|
||||
for (path_param, range) in path_params {
|
||||
// Ignore invalid identifiers (e.g., `user-id`, as opposed to `user_id`)
|
||||
if !is_identifier(path_param) {
|
||||
|
@ -203,10 +202,8 @@ pub(crate) fn fastapi_unused_path_parameter(
|
|||
checker.locator().contents(),
|
||||
)));
|
||||
}
|
||||
diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
||||
checker.diagnostics.extend(diagnostics);
|
||||
}
|
||||
|
||||
/// Returns an iterator over the non-positional-only, non-variadic parameters of a function.
|
||||
|
|
|
@ -223,7 +223,7 @@ impl Violation for SysVersionCmpStr10 {
|
|||
}
|
||||
|
||||
/// YTT103, YTT201, YTT203, YTT204, YTT302
|
||||
pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[CmpOp], comparators: &[Expr]) {
|
||||
pub(crate) fn compare(checker: &Checker, left: &Expr, ops: &[CmpOp], comparators: &[Expr]) {
|
||||
match left {
|
||||
Expr::Subscript(ast::ExprSubscript { value, slice, .. })
|
||||
if is_sys(value, "version_info", checker.semantic()) =>
|
||||
|
@ -243,9 +243,10 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[CmpOp], compara
|
|||
) = (ops, comparators)
|
||||
{
|
||||
if *n == 3 && checker.enabled(Rule::SysVersionInfo0Eq3) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersionInfo0Eq3, left.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SysVersionInfo0Eq3,
|
||||
left.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if *i == 1 {
|
||||
|
@ -258,9 +259,10 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[CmpOp], compara
|
|||
) = (ops, comparators)
|
||||
{
|
||||
if checker.enabled(Rule::SysVersionInfo1CmpInt) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersionInfo1CmpInt, left.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SysVersionInfo1CmpInt,
|
||||
left.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -279,9 +281,10 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[CmpOp], compara
|
|||
) = (ops, comparators)
|
||||
{
|
||||
if checker.enabled(Rule::SysVersionInfoMinorCmpInt) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersionInfoMinorCmpInt, left.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SysVersionInfoMinorCmpInt,
|
||||
left.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,14 +300,10 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[CmpOp], compara
|
|||
{
|
||||
if value.len() == 1 {
|
||||
if checker.enabled(Rule::SysVersionCmpStr10) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersionCmpStr10, left.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SysVersionCmpStr10, left.range()));
|
||||
}
|
||||
} else if checker.enabled(Rule::SysVersionCmpStr3) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersionCmpStr3, left.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SysVersionCmpStr3, left.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ impl Violation for SixPY3 {
|
|||
}
|
||||
|
||||
/// YTT202
|
||||
pub(crate) fn name_or_attribute(checker: &mut Checker, expr: &Expr) {
|
||||
pub(crate) fn name_or_attribute(checker: &Checker, expr: &Expr) {
|
||||
if !checker.semantic().seen_module(Modules::SIX) {
|
||||
return;
|
||||
}
|
||||
|
@ -56,8 +56,6 @@ pub(crate) fn name_or_attribute(checker: &mut Checker, expr: &Expr) {
|
|||
.resolve_qualified_name(expr)
|
||||
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["six", "PY3"]))
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SixPY3, expr.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SixPY3, expr.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ impl Violation for SysVersionSlice1 {
|
|||
}
|
||||
|
||||
/// YTT101, YTT102, YTT301, YTT303
|
||||
pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
|
||||
pub(crate) fn subscript(checker: &Checker, value: &Expr, slice: &Expr) {
|
||||
if is_sys(value, "version", checker.semantic()) {
|
||||
match slice {
|
||||
Expr::Slice(ast::ExprSlice {
|
||||
|
@ -183,13 +183,9 @@ pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
|
|||
}) = upper.as_ref()
|
||||
{
|
||||
if *i == 1 && checker.enabled(Rule::SysVersionSlice1) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersionSlice1, value.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SysVersionSlice1, value.range()));
|
||||
} else if *i == 3 && checker.enabled(Rule::SysVersionSlice3) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersionSlice3, value.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SysVersionSlice3, value.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -199,13 +195,9 @@ pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
|
|||
..
|
||||
}) => {
|
||||
if *i == 2 && checker.enabled(Rule::SysVersion2) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersion2, value.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SysVersion2, value.range()));
|
||||
} else if *i == 0 && checker.enabled(Rule::SysVersion0) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SysVersion0, value.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SysVersion0, value.range()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ impl Violation for AsyncBusyWait {
|
|||
}
|
||||
|
||||
/// ASYNC110
|
||||
pub(crate) fn async_busy_wait(checker: &mut Checker, while_stmt: &ast::StmtWhile) {
|
||||
pub(crate) fn async_busy_wait(checker: &Checker, while_stmt: &ast::StmtWhile) {
|
||||
// The body should be a single `await` call.
|
||||
let [stmt] = while_stmt.body.as_slice() else {
|
||||
return;
|
||||
|
@ -74,7 +74,7 @@ pub(crate) fn async_busy_wait(checker: &mut Checker, while_stmt: &ast::StmtWhile
|
|||
qualified_name.segments(),
|
||||
["trio" | "anyio", "sleep" | "sleep_until"] | ["asyncio", "sleep"]
|
||||
) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
AsyncBusyWait {
|
||||
module: AsyncModule::try_from(&qualified_name).unwrap(),
|
||||
},
|
||||
|
|
|
@ -87,10 +87,7 @@ impl Violation for AsyncFunctionWithTimeout {
|
|||
}
|
||||
|
||||
/// ASYNC109
|
||||
pub(crate) fn async_function_with_timeout(
|
||||
checker: &mut Checker,
|
||||
function_def: &ast::StmtFunctionDef,
|
||||
) {
|
||||
pub(crate) fn async_function_with_timeout(checker: &Checker, function_def: &ast::StmtFunctionDef) {
|
||||
// Detect `async` calls with a `timeout` argument.
|
||||
if !function_def.is_async {
|
||||
return;
|
||||
|
@ -115,7 +112,7 @@ pub(crate) fn async_function_with_timeout(
|
|||
return;
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
AsyncFunctionWithTimeout { module },
|
||||
timeout.range(),
|
||||
));
|
||||
|
|
|
@ -51,7 +51,7 @@ impl AlwaysFixableViolation for AsyncZeroSleep {
|
|||
}
|
||||
|
||||
/// ASYNC115
|
||||
pub(crate) fn async_zero_sleep(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn async_zero_sleep(checker: &Checker, call: &ExprCall) {
|
||||
if !(checker.semantic().seen_module(Modules::TRIO)
|
||||
|| checker.semantic().seen_module(Modules::ANYIO))
|
||||
{
|
||||
|
@ -103,6 +103,6 @@ pub(crate) fn async_zero_sleep(checker: &mut Checker, call: &ExprCall) {
|
|||
let arg_edit = Edit::range_replacement("()".to_string(), call.arguments.range());
|
||||
Ok(Fix::safe_edits(import_edit, [reference_edit, arg_edit]))
|
||||
});
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ fn is_blocking_http_call(qualified_name: &QualifiedName) -> bool {
|
|||
}
|
||||
|
||||
/// ASYNC210
|
||||
pub(crate) fn blocking_http_call(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn blocking_http_call(checker: &Checker, call: &ExprCall) {
|
||||
if checker.semantic().in_async_context() {
|
||||
if checker
|
||||
.semantic()
|
||||
|
@ -70,7 +70,7 @@ pub(crate) fn blocking_http_call(checker: &mut Checker, call: &ExprCall) {
|
|||
.as_ref()
|
||||
.is_some_and(is_blocking_http_call)
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
BlockingHttpCallInAsyncFunction,
|
||||
call.func.range(),
|
||||
));
|
||||
|
|
|
@ -44,7 +44,7 @@ impl Violation for BlockingOpenCallInAsyncFunction {
|
|||
}
|
||||
|
||||
/// ASYNC230
|
||||
pub(crate) fn blocking_open_call(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn blocking_open_call(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().in_async_context() {
|
||||
return;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ pub(crate) fn blocking_open_call(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
if is_open_call(&call.func, checker.semantic())
|
||||
|| is_open_call_from_pathlib(call.func.as_ref(), checker.semantic())
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
BlockingOpenCallInAsyncFunction,
|
||||
call.func.range(),
|
||||
));
|
||||
|
|
|
@ -112,7 +112,7 @@ impl Violation for WaitForProcessInAsyncFunction {
|
|||
}
|
||||
|
||||
/// ASYNC220, ASYNC221, ASYNC222
|
||||
pub(crate) fn blocking_process_invocation(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn blocking_process_invocation(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().in_async_context() {
|
||||
return;
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ pub(crate) fn blocking_process_invocation(checker: &mut Checker, call: &ast::Exp
|
|||
};
|
||||
let diagnostic = Diagnostic::new::<DiagnosticKind>(diagnostic_kind, call.func.range());
|
||||
if checker.enabled(diagnostic.kind.rule()) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ fn is_blocking_sleep(qualified_name: &QualifiedName) -> bool {
|
|||
}
|
||||
|
||||
/// ASYNC251
|
||||
pub(crate) fn blocking_sleep(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn blocking_sleep(checker: &Checker, call: &ExprCall) {
|
||||
if checker.semantic().in_async_context() {
|
||||
if checker
|
||||
.semantic()
|
||||
|
@ -51,7 +51,7 @@ pub(crate) fn blocking_sleep(checker: &mut Checker, call: &ExprCall) {
|
|||
.as_ref()
|
||||
.is_some_and(is_blocking_sleep)
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
BlockingSleepInAsyncFunction,
|
||||
call.func.range(),
|
||||
));
|
||||
|
|
|
@ -53,7 +53,7 @@ impl Violation for CancelScopeNoCheckpoint {
|
|||
|
||||
/// ASYNC100
|
||||
pub(crate) fn cancel_scope_no_checkpoint(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
with_stmt: &StmtWith,
|
||||
with_items: &[WithItem],
|
||||
) {
|
||||
|
@ -98,7 +98,7 @@ pub(crate) fn cancel_scope_no_checkpoint(
|
|||
return;
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
CancelScopeNoCheckpoint { method_name },
|
||||
with_stmt.range,
|
||||
));
|
||||
|
|
|
@ -56,7 +56,7 @@ impl Violation for LongSleepNotForever {
|
|||
}
|
||||
|
||||
/// ASYNC116
|
||||
pub(crate) fn long_sleep_not_forever(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn long_sleep_not_forever(checker: &Checker, call: &ExprCall) {
|
||||
if !(checker.semantic().seen_module(Modules::TRIO)
|
||||
|| checker.semantic().seen_module(Modules::ANYIO))
|
||||
{
|
||||
|
@ -127,5 +127,5 @@ pub(crate) fn long_sleep_not_forever(checker: &mut Checker, call: &ExprCall) {
|
|||
let arg_edit = Edit::range_replacement("()".to_string(), call.arguments.range());
|
||||
Ok(Fix::unsafe_edits(import_edit, [reference_edit, arg_edit]))
|
||||
});
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ impl Violation for TrioSyncCall {
|
|||
}
|
||||
|
||||
/// ASYNC105
|
||||
pub(crate) fn sync_call(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn sync_call(checker: &Checker, call: &ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::TRIO) {
|
||||
return;
|
||||
}
|
||||
|
@ -91,5 +91,5 @@ pub(crate) fn sync_call(checker: &mut Checker, call: &ExprCall) {
|
|||
call.func.start(),
|
||||
)));
|
||||
}
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ enum Reason {
|
|||
}
|
||||
|
||||
/// S103
|
||||
pub(crate) fn bad_file_permissions(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn bad_file_permissions(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::OS) {
|
||||
return;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ pub(crate) fn bad_file_permissions(checker: &mut Checker, call: &ast::ExprCall)
|
|||
// The mask is a valid integer value -- check for overly permissive permissions.
|
||||
Ok(Some(mask)) => {
|
||||
if (mask & WRITE_WORLD > 0) || (mask & EXECUTE_GROUP > 0) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
BadFilePermissions {
|
||||
reason: Reason::Permissive(mask),
|
||||
},
|
||||
|
@ -88,7 +88,7 @@ pub(crate) fn bad_file_permissions(checker: &mut Checker, call: &ast::ExprCall)
|
|||
}
|
||||
// The mask is an invalid integer value (i.e., it's out of range).
|
||||
Err(_) => {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
BadFilePermissions {
|
||||
reason: Reason::Invalid,
|
||||
},
|
||||
|
|
|
@ -44,7 +44,7 @@ impl Violation for DjangoExtra {
|
|||
}
|
||||
|
||||
/// S610
|
||||
pub(crate) fn django_extra(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn django_extra(checker: &Checker, call: &ast::ExprCall) {
|
||||
let Expr::Attribute(ExprAttribute { attr, .. }) = call.func.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
@ -54,9 +54,7 @@ pub(crate) fn django_extra(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
}
|
||||
|
||||
if is_call_insecure(call) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(DjangoExtra, call.arguments.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(DjangoExtra, call.arguments.range()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ impl Violation for DjangoRawSql {
|
|||
}
|
||||
|
||||
/// S611
|
||||
pub(crate) fn django_raw_sql(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn django_raw_sql(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::DJANGO) {
|
||||
return;
|
||||
}
|
||||
|
@ -55,9 +55,7 @@ pub(crate) fn django_raw_sql(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
.find_argument_value("sql", 0)
|
||||
.is_some_and(Expr::is_string_literal_expr)
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(DjangoRawSql, call.func.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(DjangoRawSql, call.func.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,10 +32,8 @@ impl Violation for ExecBuiltin {
|
|||
}
|
||||
|
||||
/// S102
|
||||
pub(crate) fn exec_used(checker: &mut Checker, func: &Expr) {
|
||||
pub(crate) fn exec_used(checker: &Checker, func: &Expr) {
|
||||
if checker.semantic().match_builtin_expr(func, "exec") {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ExecBuiltin, func.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(ExecBuiltin, func.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ impl Violation for FlaskDebugTrue {
|
|||
}
|
||||
|
||||
/// S201
|
||||
pub(crate) fn flask_debug_true(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn flask_debug_true(checker: &Checker, call: &ExprCall) {
|
||||
let Expr::Attribute(ExprAttribute { attr, value, .. }) = call.func.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
@ -67,8 +67,6 @@ pub(crate) fn flask_debug_true(checker: &mut Checker, call: &ExprCall) {
|
|||
if typing::resolve_assignment(value, checker.semantic())
|
||||
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["flask", "Flask"]))
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(FlaskDebugTrue, debug_argument.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(FlaskDebugTrue, debug_argument.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,13 +37,12 @@ impl Violation for HardcodedBindAllInterfaces {
|
|||
}
|
||||
|
||||
/// S104
|
||||
pub(crate) fn hardcoded_bind_all_interfaces(checker: &mut Checker, string: StringLike) {
|
||||
pub(crate) fn hardcoded_bind_all_interfaces(checker: &Checker, string: StringLike) {
|
||||
match string {
|
||||
StringLike::String(ast::ExprStringLiteral { value, .. }) => {
|
||||
if value == "0.0.0.0" {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(HardcodedBindAllInterfaces, string.range()));
|
||||
.report_diagnostic(Diagnostic::new(HardcodedBindAllInterfaces, string.range()));
|
||||
}
|
||||
}
|
||||
StringLike::FString(ast::ExprFString { value, .. }) => {
|
||||
|
@ -51,15 +50,16 @@ pub(crate) fn hardcoded_bind_all_interfaces(checker: &mut Checker, string: Strin
|
|||
match part {
|
||||
ast::FStringPart::Literal(literal) => {
|
||||
if &**literal == "0.0.0.0" {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(HardcodedBindAllInterfaces, literal.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
HardcodedBindAllInterfaces,
|
||||
literal.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
ast::FStringPart::FString(f_string) => {
|
||||
for literal in f_string.elements.literals() {
|
||||
if &**literal == "0.0.0.0" {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
HardcodedBindAllInterfaces,
|
||||
literal.range(),
|
||||
));
|
||||
|
|
|
@ -69,13 +69,13 @@ fn check_password_kwarg(parameter: &Parameter, default: &Expr) -> Option<Diagnos
|
|||
}
|
||||
|
||||
/// S107
|
||||
pub(crate) fn hardcoded_password_default(checker: &mut Checker, parameters: &Parameters) {
|
||||
pub(crate) fn hardcoded_password_default(checker: &Checker, parameters: &Parameters) {
|
||||
for parameter in parameters.iter_non_variadic_params() {
|
||||
let Some(default) = parameter.default() else {
|
||||
continue;
|
||||
};
|
||||
if let Some(diagnostic) = check_password_kwarg(¶meter.parameter, default) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,20 +51,18 @@ impl Violation for HardcodedPasswordFuncArg {
|
|||
}
|
||||
|
||||
/// S106
|
||||
pub(crate) fn hardcoded_password_func_arg(checker: &mut Checker, keywords: &[Keyword]) {
|
||||
checker
|
||||
.diagnostics
|
||||
.extend(keywords.iter().filter_map(|keyword| {
|
||||
string_literal(&keyword.value).filter(|string| !string.is_empty())?;
|
||||
let arg = keyword.arg.as_ref()?;
|
||||
if !matches_password_name(arg) {
|
||||
return None;
|
||||
}
|
||||
Some(Diagnostic::new(
|
||||
HardcodedPasswordFuncArg {
|
||||
name: arg.to_string(),
|
||||
},
|
||||
keyword.range(),
|
||||
))
|
||||
}));
|
||||
pub(crate) fn hardcoded_password_func_arg(checker: &Checker, keywords: &[Keyword]) {
|
||||
checker.report_diagnostics(keywords.iter().filter_map(|keyword| {
|
||||
string_literal(&keyword.value).filter(|string| !string.is_empty())?;
|
||||
let arg = keyword.arg.as_ref()?;
|
||||
if !matches_password_name(arg) {
|
||||
return None;
|
||||
}
|
||||
Some(Diagnostic::new(
|
||||
HardcodedPasswordFuncArg {
|
||||
name: arg.to_string(),
|
||||
},
|
||||
keyword.range(),
|
||||
))
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -72,37 +72,31 @@ fn password_target(target: &Expr) -> Option<&str> {
|
|||
|
||||
/// S105
|
||||
pub(crate) fn compare_to_hardcoded_password_string(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
left: &Expr,
|
||||
comparators: &[Expr],
|
||||
) {
|
||||
checker
|
||||
.diagnostics
|
||||
.extend(comparators.iter().filter_map(|comp| {
|
||||
string_literal(comp).filter(|string| !string.is_empty())?;
|
||||
let name = password_target(left)?;
|
||||
Some(Diagnostic::new(
|
||||
HardcodedPasswordString {
|
||||
name: name.to_string(),
|
||||
},
|
||||
comp.range(),
|
||||
))
|
||||
}));
|
||||
checker.report_diagnostics(comparators.iter().filter_map(|comp| {
|
||||
string_literal(comp).filter(|string| !string.is_empty())?;
|
||||
let name = password_target(left)?;
|
||||
Some(Diagnostic::new(
|
||||
HardcodedPasswordString {
|
||||
name: name.to_string(),
|
||||
},
|
||||
comp.range(),
|
||||
))
|
||||
}));
|
||||
}
|
||||
|
||||
/// S105
|
||||
pub(crate) fn assign_hardcoded_password_string(
|
||||
checker: &mut Checker,
|
||||
value: &Expr,
|
||||
targets: &[Expr],
|
||||
) {
|
||||
pub(crate) fn assign_hardcoded_password_string(checker: &Checker, value: &Expr, targets: &[Expr]) {
|
||||
if string_literal(value)
|
||||
.filter(|string| !string.is_empty())
|
||||
.is_some()
|
||||
{
|
||||
for target in targets {
|
||||
if let Some(name) = password_target(target) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
HardcodedPasswordString {
|
||||
name: name.to_string(),
|
||||
},
|
||||
|
|
|
@ -55,7 +55,7 @@ impl Violation for HardcodedSQLExpression {
|
|||
}
|
||||
|
||||
/// S608
|
||||
pub(crate) fn hardcoded_sql_expression(checker: &mut Checker, expr: &Expr) {
|
||||
pub(crate) fn hardcoded_sql_expression(checker: &Checker, expr: &Expr) {
|
||||
let content = match expr {
|
||||
// "select * from table where val = " + "str" + ...
|
||||
Expr::BinOp(ast::ExprBinOp {
|
||||
|
@ -105,9 +105,7 @@ pub(crate) fn hardcoded_sql_expression(checker: &mut Checker, expr: &Expr) {
|
|||
};
|
||||
|
||||
if SQL_REGEX.is_match(&content) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(HardcodedSQLExpression, expr.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(HardcodedSQLExpression, expr.range()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ impl Violation for HardcodedTempFile {
|
|||
}
|
||||
|
||||
/// S108
|
||||
pub(crate) fn hardcoded_tmp_directory(checker: &mut Checker, string: StringLike) {
|
||||
pub(crate) fn hardcoded_tmp_directory(checker: &Checker, string: StringLike) {
|
||||
match string {
|
||||
StringLike::String(ast::ExprStringLiteral { value, .. }) => {
|
||||
check(checker, value.to_str(), string.range());
|
||||
|
@ -79,7 +79,7 @@ pub(crate) fn hardcoded_tmp_directory(checker: &mut Checker, string: StringLike)
|
|||
}
|
||||
}
|
||||
|
||||
fn check(checker: &mut Checker, value: &str, range: TextRange) {
|
||||
fn check(checker: &Checker, value: &str, range: TextRange) {
|
||||
if !checker
|
||||
.settings
|
||||
.flake8_bandit
|
||||
|
@ -102,7 +102,7 @@ fn check(checker: &mut Checker, value: &str, range: TextRange) {
|
|||
}
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
HardcodedTempFile {
|
||||
string: value.to_string(),
|
||||
},
|
||||
|
|
|
@ -64,7 +64,7 @@ impl Violation for HashlibInsecureHashFunction {
|
|||
}
|
||||
|
||||
/// S324
|
||||
pub(crate) fn hashlib_insecure_hash_functions(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn hashlib_insecure_hash_functions(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker
|
||||
.semantic()
|
||||
.seen_module(Modules::HASHLIB | Modules::CRYPT)
|
||||
|
@ -105,7 +105,7 @@ pub(crate) fn hashlib_insecure_hash_functions(checker: &mut Checker, call: &ast:
|
|||
}
|
||||
|
||||
fn detect_insecure_hashlib_calls(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
call: &ast::ExprCall,
|
||||
hashlib_call: HashlibCall,
|
||||
) {
|
||||
|
@ -128,7 +128,7 @@ fn detect_insecure_hashlib_calls(
|
|||
hash_func_name,
|
||||
"md4" | "md5" | "sha" | "sha1" | "MD4" | "MD5" | "SHA" | "SHA1"
|
||||
) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
HashlibInsecureHashFunction {
|
||||
library: "hashlib".to_string(),
|
||||
string: hash_func_name.to_string(),
|
||||
|
@ -138,7 +138,7 @@ fn detect_insecure_hashlib_calls(
|
|||
}
|
||||
}
|
||||
HashlibCall::WeakHash(func_name) => {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
HashlibInsecureHashFunction {
|
||||
library: "hashlib".to_string(),
|
||||
string: (*func_name).to_string(),
|
||||
|
@ -149,7 +149,7 @@ fn detect_insecure_hashlib_calls(
|
|||
}
|
||||
}
|
||||
|
||||
fn detect_insecure_crypt_calls(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
fn detect_insecure_crypt_calls(checker: &Checker, call: &ast::ExprCall) {
|
||||
let Some(method) = checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
|
@ -173,7 +173,7 @@ fn detect_insecure_crypt_calls(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
qualified_name.segments(),
|
||||
["crypt", "METHOD_CRYPT" | "METHOD_MD5" | "METHOD_BLOWFISH"]
|
||||
) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
HashlibInsecureHashFunction {
|
||||
library: "crypt".to_string(),
|
||||
string: qualified_name.to_string(),
|
||||
|
|
|
@ -56,7 +56,7 @@ impl Violation for Jinja2AutoescapeFalse {
|
|||
}
|
||||
|
||||
/// S701
|
||||
pub(crate) fn jinja2_autoescape_false(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn jinja2_autoescape_false(checker: &Checker, call: &ast::ExprCall) {
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
|
@ -70,20 +70,20 @@ pub(crate) fn jinja2_autoescape_false(checker: &mut Checker, call: &ast::ExprCal
|
|||
Expr::Call(ast::ExprCall { func, .. }) => {
|
||||
if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() {
|
||||
if id != "select_autoescape" {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Jinja2AutoescapeFalse { value: true },
|
||||
keyword.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => checker.diagnostics.push(Diagnostic::new(
|
||||
_ => checker.report_diagnostic(Diagnostic::new(
|
||||
Jinja2AutoescapeFalse { value: true },
|
||||
keyword.range(),
|
||||
)),
|
||||
}
|
||||
} else {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
Jinja2AutoescapeFalse { value: false },
|
||||
call.func.range(),
|
||||
));
|
||||
|
|
|
@ -35,7 +35,7 @@ impl Violation for LoggingConfigInsecureListen {
|
|||
}
|
||||
|
||||
/// S612
|
||||
pub(crate) fn logging_config_insecure_listen(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn logging_config_insecure_listen(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::LOGGING) {
|
||||
return;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ pub(crate) fn logging_config_insecure_listen(checker: &mut Checker, call: &ast::
|
|||
return;
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
LoggingConfigInsecureListen,
|
||||
call.func.range(),
|
||||
));
|
||||
|
|
|
@ -42,7 +42,7 @@ impl Violation for MakoTemplates {
|
|||
}
|
||||
|
||||
/// S702
|
||||
pub(crate) fn mako_templates(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn mako_templates(checker: &Checker, call: &ast::ExprCall) {
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
|
@ -50,8 +50,6 @@ pub(crate) fn mako_templates(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
matches!(qualified_name.segments(), ["mako", "template", "Template"])
|
||||
})
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(MakoTemplates, call.func.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(MakoTemplates, call.func.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ impl Violation for ParamikoCall {
|
|||
}
|
||||
|
||||
/// S601
|
||||
pub(crate) fn paramiko_call(checker: &mut Checker, func: &Expr) {
|
||||
pub(crate) fn paramiko_call(checker: &Checker, func: &Expr) {
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(func)
|
||||
|
@ -45,8 +45,6 @@ pub(crate) fn paramiko_call(checker: &mut Checker, func: &Expr) {
|
|||
matches!(qualified_name.segments(), ["paramiko", "exec_command"])
|
||||
})
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ParamikoCall, func.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(ParamikoCall, func.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ impl Violation for RequestWithNoCertValidation {
|
|||
}
|
||||
|
||||
/// S501
|
||||
pub(crate) fn request_with_no_cert_validation(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn request_with_no_cert_validation(checker: &Checker, call: &ast::ExprCall) {
|
||||
if let Some(target) = checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
|
@ -61,7 +61,7 @@ pub(crate) fn request_with_no_cert_validation(checker: &mut Checker, call: &ast:
|
|||
{
|
||||
if let Some(keyword) = call.arguments.find_keyword("verify") {
|
||||
if is_const_false(&keyword.value) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
RequestWithNoCertValidation {
|
||||
string: target.to_string(),
|
||||
},
|
||||
|
|
|
@ -51,7 +51,7 @@ impl Violation for RequestWithoutTimeout {
|
|||
}
|
||||
|
||||
/// S113
|
||||
pub(crate) fn request_without_timeout(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn request_without_timeout(checker: &Checker, call: &ast::ExprCall) {
|
||||
if let Some(module) = checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
|
@ -67,13 +67,13 @@ pub(crate) fn request_without_timeout(checker: &mut Checker, call: &ast::ExprCal
|
|||
{
|
||||
if let Some(keyword) = call.arguments.find_keyword("timeout") {
|
||||
if keyword.value.is_none_literal_expr() {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
RequestWithoutTimeout { implicit: false, module: module.to_string() },
|
||||
keyword.range(),
|
||||
));
|
||||
}
|
||||
} else if module == "requests" {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
RequestWithoutTimeout { implicit: true, module: module.to_string() },
|
||||
call.func.range(),
|
||||
));
|
||||
|
|
|
@ -288,7 +288,7 @@ impl Violation for UnixCommandWildcardInjection {
|
|||
}
|
||||
|
||||
/// S602, S603, S604, S605, S606, S607, S609
|
||||
pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn shell_injection(checker: &Checker, call: &ast::ExprCall) {
|
||||
let call_kind = get_call_kind(&call.func, checker.semantic());
|
||||
let shell_keyword = find_shell_keyword(&call.arguments, checker.semantic());
|
||||
|
||||
|
@ -300,7 +300,7 @@ pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
truthiness: truthiness @ (Truthiness::True | Truthiness::Truthy),
|
||||
}) => {
|
||||
if checker.enabled(Rule::SubprocessPopenWithShellEqualsTrue) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SubprocessPopenWithShellEqualsTrue {
|
||||
safety: Safety::from(arg),
|
||||
is_exact: matches!(truthiness, Truthiness::True),
|
||||
|
@ -315,7 +315,7 @@ pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
Truthiness::False | Truthiness::Falsey | Truthiness::None | Truthiness::Unknown,
|
||||
}) => {
|
||||
if checker.enabled(Rule::SubprocessWithoutShellEqualsTrue) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SubprocessWithoutShellEqualsTrue,
|
||||
call.func.range(),
|
||||
));
|
||||
|
@ -324,7 +324,7 @@ pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
// S603
|
||||
None => {
|
||||
if checker.enabled(Rule::SubprocessWithoutShellEqualsTrue) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SubprocessWithoutShellEqualsTrue,
|
||||
call.func.range(),
|
||||
));
|
||||
|
@ -338,7 +338,7 @@ pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
{
|
||||
// S604
|
||||
if checker.enabled(Rule::CallWithShellEqualsTrue) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
CallWithShellEqualsTrue {
|
||||
is_exact: matches!(truthiness, Truthiness::True),
|
||||
},
|
||||
|
@ -351,7 +351,7 @@ pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
if checker.enabled(Rule::StartProcessWithAShell) {
|
||||
if matches!(call_kind, Some(CallKind::Shell)) {
|
||||
if let Some(arg) = call.arguments.args.first() {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
StartProcessWithAShell {
|
||||
safety: Safety::from(arg),
|
||||
},
|
||||
|
@ -364,9 +364,7 @@ pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
// S606
|
||||
if checker.enabled(Rule::StartProcessWithNoShell) {
|
||||
if matches!(call_kind, Some(CallKind::NoShell)) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(StartProcessWithNoShell, call.func.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(StartProcessWithNoShell, call.func.range()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,9 +373,10 @@ pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
if call_kind.is_some() {
|
||||
if let Some(arg) = call.arguments.args.first() {
|
||||
if is_partial_path(arg) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(StartProcessWithPartialPath, arg.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
StartProcessWithPartialPath,
|
||||
arg.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -398,9 +397,10 @@ pub(crate) fn shell_injection(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
{
|
||||
if let Some(arg) = call.arguments.args.first() {
|
||||
if is_wildcard_command(arg) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(UnixCommandWildcardInjection, arg.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
UnixCommandWildcardInjection,
|
||||
arg.range(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ impl Violation for SnmpInsecureVersion {
|
|||
}
|
||||
|
||||
/// S508
|
||||
pub(crate) fn snmp_insecure_version(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn snmp_insecure_version(checker: &Checker, call: &ast::ExprCall) {
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
|
@ -60,9 +60,7 @@ pub(crate) fn snmp_insecure_version(checker: &mut Checker, call: &ast::ExprCall)
|
|||
..
|
||||
})
|
||||
) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SnmpInsecureVersion, keyword.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SnmpInsecureVersion, keyword.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ impl Violation for SnmpWeakCryptography {
|
|||
}
|
||||
|
||||
/// S509
|
||||
pub(crate) fn snmp_weak_cryptography(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn snmp_weak_cryptography(checker: &Checker, call: &ast::ExprCall) {
|
||||
if call.arguments.len() < 3 {
|
||||
if checker
|
||||
.semantic()
|
||||
|
@ -52,9 +52,7 @@ pub(crate) fn snmp_weak_cryptography(checker: &mut Checker, call: &ast::ExprCall
|
|||
)
|
||||
})
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SnmpWeakCryptography, call.func.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SnmpWeakCryptography, call.func.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ impl Violation for SSHNoHostKeyVerification {
|
|||
}
|
||||
|
||||
/// S507
|
||||
pub(crate) fn ssh_no_host_key_verification(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn ssh_no_host_key_verification(checker: &Checker, call: &ExprCall) {
|
||||
let Expr::Attribute(ExprAttribute { attr, value, .. }) = call.func.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
@ -78,7 +78,7 @@ pub(crate) fn ssh_no_host_key_verification(checker: &mut Checker, call: &ExprCal
|
|||
["paramiko", "client", "SSHClient"] | ["paramiko", "SSHClient"]
|
||||
)
|
||||
}) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SSHNoHostKeyVerification,
|
||||
policy_argument.range(),
|
||||
));
|
||||
|
|
|
@ -48,7 +48,7 @@ impl Violation for SslInsecureVersion {
|
|||
}
|
||||
|
||||
/// S502
|
||||
pub(crate) fn ssl_insecure_version(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn ssl_insecure_version(checker: &Checker, call: &ExprCall) {
|
||||
let Some(keyword) = checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(call.func.as_ref())
|
||||
|
@ -68,7 +68,7 @@ pub(crate) fn ssl_insecure_version(checker: &mut Checker, call: &ExprCall) {
|
|||
match &keyword.value {
|
||||
Expr::Name(ast::ExprName { id, .. }) => {
|
||||
if is_insecure_protocol(id) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SslInsecureVersion {
|
||||
protocol: id.to_string(),
|
||||
},
|
||||
|
@ -78,7 +78,7 @@ pub(crate) fn ssl_insecure_version(checker: &mut Checker, call: &ExprCall) {
|
|||
}
|
||||
Expr::Attribute(ast::ExprAttribute { attr, .. }) => {
|
||||
if is_insecure_protocol(attr) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SslInsecureVersion {
|
||||
protocol: attr.to_string(),
|
||||
},
|
||||
|
|
|
@ -48,7 +48,7 @@ impl Violation for SslWithBadDefaults {
|
|||
}
|
||||
|
||||
/// S503
|
||||
pub(crate) fn ssl_with_bad_defaults(checker: &mut Checker, function_def: &StmtFunctionDef) {
|
||||
pub(crate) fn ssl_with_bad_defaults(checker: &Checker, function_def: &StmtFunctionDef) {
|
||||
for default in function_def
|
||||
.parameters
|
||||
.iter_non_variadic_params()
|
||||
|
@ -57,7 +57,7 @@ pub(crate) fn ssl_with_bad_defaults(checker: &mut Checker, function_def: &StmtFu
|
|||
match default {
|
||||
Expr::Name(ast::ExprName { id, range, .. }) => {
|
||||
if is_insecure_protocol(id.as_str()) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SslWithBadDefaults {
|
||||
protocol: id.to_string(),
|
||||
},
|
||||
|
@ -67,7 +67,7 @@ pub(crate) fn ssl_with_bad_defaults(checker: &mut Checker, function_def: &StmtFu
|
|||
}
|
||||
Expr::Attribute(ast::ExprAttribute { attr, range, .. }) => {
|
||||
if is_insecure_protocol(attr.as_str()) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
SslWithBadDefaults {
|
||||
protocol: attr.to_string(),
|
||||
},
|
||||
|
|
|
@ -36,16 +36,14 @@ impl Violation for SslWithNoVersion {
|
|||
}
|
||||
|
||||
/// S504
|
||||
pub(crate) fn ssl_with_no_version(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn ssl_with_no_version(checker: &Checker, call: &ExprCall) {
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(call.func.as_ref())
|
||||
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["ssl", "wrap_socket"]))
|
||||
{
|
||||
if call.arguments.find_keyword("ssl_version").is_none() {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(SslWithNoVersion, call.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(SslWithNoVersion, call.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -908,7 +908,7 @@ impl Violation for SuspiciousFTPLibUsage {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn suspicious_function_call(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn suspicious_function_call(checker: &Checker, call: &ExprCall) {
|
||||
suspicious_function(
|
||||
checker,
|
||||
call.func.as_ref(),
|
||||
|
@ -917,7 +917,7 @@ pub(crate) fn suspicious_function_call(checker: &mut Checker, call: &ExprCall) {
|
|||
);
|
||||
}
|
||||
|
||||
pub(crate) fn suspicious_function_reference(checker: &mut Checker, func: &Expr) {
|
||||
pub(crate) fn suspicious_function_reference(checker: &Checker, func: &Expr) {
|
||||
if checker.settings.preview.is_disabled() {
|
||||
return;
|
||||
}
|
||||
|
@ -953,7 +953,7 @@ pub(crate) fn suspicious_function_reference(checker: &mut Checker, func: &Expr)
|
|||
|
||||
/// S301, S302, S303, S304, S305, S306, S307, S308, S310, S311, S312, S313, S314, S315, S316, S317, S318, S319, S320, S321, S323
|
||||
fn suspicious_function(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
func: &Expr,
|
||||
arguments: Option<&Arguments>,
|
||||
range: TextRange,
|
||||
|
@ -1176,12 +1176,12 @@ fn suspicious_function(
|
|||
|
||||
let diagnostic = Diagnostic::new(diagnostic_kind, range);
|
||||
if checker.enabled(diagnostic.kind.rule()) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
/// S308
|
||||
pub(crate) fn suspicious_function_decorator(checker: &mut Checker, decorator: &Decorator) {
|
||||
pub(crate) fn suspicious_function_decorator(checker: &Checker, decorator: &Decorator) {
|
||||
// In preview mode, references are handled collectively by `suspicious_function_reference`
|
||||
if checker.settings.preview.is_disabled() {
|
||||
suspicious_function(checker, &decorator.expression, None, decorator.range);
|
||||
|
|
|
@ -351,7 +351,7 @@ impl Violation for SuspiciousPyghmiImport {
|
|||
}
|
||||
|
||||
/// S401, S402, S403, S404, S405, S406, S407, S408, S409, S410, S411, S412, S413, S415
|
||||
pub(crate) fn suspicious_imports(checker: &mut Checker, stmt: &Stmt) {
|
||||
pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
|
||||
// Skip stub files.
|
||||
if checker.source_type.is_stub() {
|
||||
return;
|
||||
|
@ -602,13 +602,9 @@ pub(crate) fn suspicious_imports(checker: &mut Checker, stmt: &Stmt) {
|
|||
};
|
||||
}
|
||||
|
||||
fn check_and_push_diagnostic(
|
||||
checker: &mut Checker,
|
||||
diagnostic_kind: DiagnosticKind,
|
||||
range: TextRange,
|
||||
) {
|
||||
fn check_and_push_diagnostic(checker: &Checker, diagnostic_kind: DiagnosticKind, range: TextRange) {
|
||||
let diagnostic = Diagnostic::new::<DiagnosticKind>(diagnostic_kind, range);
|
||||
if checker.enabled(diagnostic.kind.rule()) {
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ impl Violation for TarfileUnsafeMembers {
|
|||
}
|
||||
|
||||
/// S202
|
||||
pub(crate) fn tarfile_unsafe_members(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn tarfile_unsafe_members(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::TARFILE) {
|
||||
return;
|
||||
}
|
||||
|
@ -70,7 +70,5 @@ pub(crate) fn tarfile_unsafe_members(checker: &mut Checker, call: &ast::ExprCall
|
|||
return;
|
||||
}
|
||||
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(TarfileUnsafeMembers, call.func.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(TarfileUnsafeMembers, call.func.range()));
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ impl Violation for TryExceptContinue {
|
|||
|
||||
/// S112
|
||||
pub(crate) fn try_except_continue(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
except_handler: &ExceptHandler,
|
||||
type_: Option<&Expr>,
|
||||
body: &[Stmt],
|
||||
|
@ -61,9 +61,7 @@ pub(crate) fn try_except_continue(
|
|||
) {
|
||||
if matches!(body, [Stmt::Continue(_)]) {
|
||||
if check_typed_exception || is_untyped_exception(type_, checker.semantic()) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(TryExceptContinue, except_handler.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(TryExceptContinue, except_handler.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ impl Violation for TryExceptPass {
|
|||
|
||||
/// S110
|
||||
pub(crate) fn try_except_pass(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
except_handler: &ExceptHandler,
|
||||
type_: Option<&Expr>,
|
||||
body: &[Stmt],
|
||||
|
@ -57,9 +57,7 @@ pub(crate) fn try_except_pass(
|
|||
) {
|
||||
if matches!(body, [Stmt::Pass(_)]) {
|
||||
if check_typed_exception || is_untyped_exception(type_, checker.semantic()) {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(TryExceptPass, except_handler.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(TryExceptPass, except_handler.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ impl Violation for UnsafeYAMLLoad {
|
|||
}
|
||||
|
||||
/// S506
|
||||
pub(crate) fn unsafe_yaml_load(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn unsafe_yaml_load(checker: &Checker, call: &ast::ExprCall) {
|
||||
if checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
|
@ -82,13 +82,13 @@ pub(crate) fn unsafe_yaml_load(checker: &mut Checker, call: &ast::ExprCall) {
|
|||
Expr::Name(ast::ExprName { id, .. }) => Some(id.to_string()),
|
||||
_ => None,
|
||||
};
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
UnsafeYAMLLoad { loader },
|
||||
loader_arg.range(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
UnsafeYAMLLoad { loader: None },
|
||||
call.func.range(),
|
||||
));
|
||||
|
|
|
@ -49,13 +49,13 @@ impl Violation for WeakCryptographicKey {
|
|||
}
|
||||
|
||||
/// S505
|
||||
pub(crate) fn weak_cryptographic_key(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn weak_cryptographic_key(checker: &Checker, call: &ExprCall) {
|
||||
let Some((cryptographic_key, range)) = extract_cryptographic_key(checker, call) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if cryptographic_key.is_vulnerable() {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
WeakCryptographicKey { cryptographic_key },
|
||||
range,
|
||||
));
|
||||
|
@ -98,7 +98,7 @@ impl Display for CryptographicKey {
|
|||
}
|
||||
|
||||
fn extract_cryptographic_key(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
call: &ExprCall,
|
||||
) -> Option<(CryptographicKey, TextRange)> {
|
||||
let qualified_name = checker.semantic().resolve_qualified_name(&call.func)?;
|
||||
|
|
|
@ -76,7 +76,7 @@ impl Violation for BlindExcept {
|
|||
|
||||
/// BLE001
|
||||
pub(crate) fn blind_except(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
type_: Option<&Expr>,
|
||||
name: Option<&str>,
|
||||
body: &[Stmt],
|
||||
|
@ -107,7 +107,7 @@ pub(crate) fn blind_except(
|
|||
return;
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
BlindExcept {
|
||||
name: builtin_exception_type.to_string(),
|
||||
},
|
||||
|
|
|
@ -101,7 +101,7 @@ impl Violation for BooleanDefaultValuePositionalArgument {
|
|||
|
||||
/// FBT002
|
||||
pub(crate) fn boolean_default_value_positional_argument(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
name: &str,
|
||||
decorator_list: &[Decorator],
|
||||
parameters: &Parameters,
|
||||
|
@ -131,7 +131,7 @@ pub(crate) fn boolean_default_value_positional_argument(
|
|||
return;
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
BooleanDefaultValuePositionalArgument,
|
||||
param.identifier(),
|
||||
));
|
||||
|
|
|
@ -51,7 +51,7 @@ impl Violation for BooleanPositionalValueInCall {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn boolean_positional_value_in_call(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn boolean_positional_value_in_call(checker: &Checker, call: &ast::ExprCall) {
|
||||
if allow_boolean_trap(call, checker) {
|
||||
return;
|
||||
}
|
||||
|
@ -61,8 +61,6 @@ pub(crate) fn boolean_positional_value_in_call(checker: &mut Checker, call: &ast
|
|||
.iter()
|
||||
.filter(|arg| arg.is_boolean_literal_expr())
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(BooleanPositionalValueInCall, arg.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(BooleanPositionalValueInCall, arg.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ impl Violation for BooleanTypeHintPositionalArgument {
|
|||
|
||||
/// FBT001
|
||||
pub(crate) fn boolean_type_hint_positional_argument(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
name: &str,
|
||||
decorator_list: &[Decorator],
|
||||
parameters: &Parameters,
|
||||
|
@ -157,7 +157,7 @@ pub(crate) fn boolean_type_hint_positional_argument(
|
|||
return;
|
||||
}
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
BooleanTypeHintPositionalArgument,
|
||||
parameter.identifier(),
|
||||
));
|
||||
|
|
|
@ -144,7 +144,7 @@ fn is_empty_body(body: &[Stmt]) -> bool {
|
|||
/// B024
|
||||
/// B027
|
||||
pub(crate) fn abstract_base_class(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
stmt: &Stmt,
|
||||
name: &str,
|
||||
arguments: Option<&Arguments>,
|
||||
|
@ -196,7 +196,7 @@ pub(crate) fn abstract_base_class(
|
|||
&& is_empty_body(body)
|
||||
&& !is_overload(decorator_list, checker.semantic())
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
EmptyMethodWithoutAbstractDecorator {
|
||||
name: format!("{name}.{method_name}"),
|
||||
},
|
||||
|
@ -206,7 +206,7 @@ pub(crate) fn abstract_base_class(
|
|||
}
|
||||
if checker.enabled(Rule::AbstractBaseClassWithoutAbstractMethod) {
|
||||
if !has_abstract_method {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
AbstractBaseClassWithoutAbstractMethod {
|
||||
name: name.to_string(),
|
||||
},
|
||||
|
|
|
@ -74,7 +74,7 @@ fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
|||
}
|
||||
|
||||
/// B011
|
||||
pub(crate) fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option<&Expr>) {
|
||||
pub(crate) fn assert_false(checker: &Checker, stmt: &Stmt, test: &Expr, msg: Option<&Expr>) {
|
||||
if !is_const_false(test) {
|
||||
return;
|
||||
}
|
||||
|
@ -84,5 +84,5 @@ pub(crate) fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg:
|
|||
checker.generator().stmt(&assertion_error(msg)),
|
||||
stmt.range(),
|
||||
)));
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ impl fmt::Display for ExceptionKind {
|
|||
}
|
||||
|
||||
/// B017
|
||||
pub(crate) fn assert_raises_exception(checker: &mut Checker, items: &[WithItem]) {
|
||||
pub(crate) fn assert_raises_exception(checker: &Checker, items: &[WithItem]) {
|
||||
for item in items {
|
||||
let Expr::Call(ast::ExprCall {
|
||||
func,
|
||||
|
@ -99,7 +99,7 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, items: &[WithItem])
|
|||
continue;
|
||||
};
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
AssertRaisesException { exception },
|
||||
item.range(),
|
||||
));
|
||||
|
|
|
@ -50,7 +50,7 @@ impl Violation for AssignmentToOsEnviron {
|
|||
}
|
||||
|
||||
/// B003
|
||||
pub(crate) fn assignment_to_os_environ(checker: &mut Checker, targets: &[Expr]) {
|
||||
pub(crate) fn assignment_to_os_environ(checker: &Checker, targets: &[Expr]) {
|
||||
let [target] = targets else {
|
||||
return;
|
||||
};
|
||||
|
@ -66,7 +66,5 @@ pub(crate) fn assignment_to_os_environ(checker: &mut Checker, targets: &[Expr])
|
|||
if id != "os" {
|
||||
return;
|
||||
}
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(AssignmentToOsEnviron, target.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(AssignmentToOsEnviron, target.range()));
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ impl Violation for BatchedWithoutExplicitStrict {
|
|||
}
|
||||
|
||||
/// B911
|
||||
pub(crate) fn batched_without_explicit_strict(checker: &mut Checker, call: &ExprCall) {
|
||||
pub(crate) fn batched_without_explicit_strict(checker: &Checker, call: &ExprCall) {
|
||||
if checker.settings.target_version < PythonVersion::Py313 {
|
||||
return;
|
||||
}
|
||||
|
@ -87,5 +87,5 @@ pub(crate) fn batched_without_explicit_strict(checker: &mut Checker, call: &Expr
|
|||
}
|
||||
|
||||
let diagnostic = Diagnostic::new(BatchedWithoutExplicitStrict, call.range);
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ impl Violation for CachedInstanceMethod {
|
|||
}
|
||||
|
||||
/// B019
|
||||
pub(crate) fn cached_instance_method(checker: &mut Checker, function_def: &ast::StmtFunctionDef) {
|
||||
pub(crate) fn cached_instance_method(checker: &Checker, function_def: &ast::StmtFunctionDef) {
|
||||
let scope = checker.semantic().current_scope();
|
||||
|
||||
// Parent scope _must_ be a class.
|
||||
|
@ -102,9 +102,7 @@ pub(crate) fn cached_instance_method(checker: &mut Checker, function_def: &ast::
|
|||
return;
|
||||
}
|
||||
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(CachedInstanceMethod, decorator.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(CachedInstanceMethod, decorator.range()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ impl Violation for ClassAsDataStructure {
|
|||
}
|
||||
|
||||
/// B903
|
||||
pub(crate) fn class_as_data_structure(checker: &mut Checker, class_def: &ast::StmtClassDef) {
|
||||
pub(crate) fn class_as_data_structure(checker: &Checker, class_def: &ast::StmtClassDef) {
|
||||
// skip stub files
|
||||
if checker.source_type.is_stub() {
|
||||
return;
|
||||
|
@ -105,9 +105,7 @@ pub(crate) fn class_as_data_structure(checker: &mut Checker, class_def: &ast::St
|
|||
}
|
||||
|
||||
if has_dunder_init && public_methods == 1 {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ClassAsDataStructure, class_def.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(ClassAsDataStructure, class_def.range()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ fn type_pattern(elts: Vec<&Expr>) -> Expr {
|
|||
|
||||
/// B014
|
||||
fn duplicate_handler_exceptions<'a>(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
expr: &'a Expr,
|
||||
elts: &'a [Expr],
|
||||
) -> FxHashMap<UnqualifiedName<'a>, &'a Expr> {
|
||||
|
@ -167,7 +167,7 @@ fn duplicate_handler_exceptions<'a>(
|
|||
},
|
||||
expr.range(),
|
||||
)));
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ fn duplicate_handler_exceptions<'a>(
|
|||
}
|
||||
|
||||
/// B025
|
||||
pub(crate) fn duplicate_exceptions(checker: &mut Checker, handlers: &[ExceptHandler]) {
|
||||
pub(crate) fn duplicate_exceptions(checker: &Checker, handlers: &[ExceptHandler]) {
|
||||
let mut seen: FxHashSet<UnqualifiedName> = FxHashSet::default();
|
||||
let mut duplicates: FxHashMap<UnqualifiedName, Vec<&Expr>> = FxHashMap::default();
|
||||
for handler in handlers {
|
||||
|
@ -217,7 +217,7 @@ pub(crate) fn duplicate_exceptions(checker: &mut Checker, handlers: &[ExceptHand
|
|||
.current_statement()
|
||||
.as_try_stmt()
|
||||
.is_some_and(|try_stmt| try_stmt.is_star);
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
DuplicateTryBlockException {
|
||||
name: name.segments().join("."),
|
||||
is_star,
|
||||
|
|
|
@ -55,7 +55,7 @@ impl Violation for DuplicateValue {
|
|||
}
|
||||
|
||||
/// B033
|
||||
pub(crate) fn duplicate_value(checker: &mut Checker, set: &ast::ExprSet) {
|
||||
pub(crate) fn duplicate_value(checker: &Checker, set: &ast::ExprSet) {
|
||||
let mut seen_values: FxHashMap<HashableExpr, &Expr> = FxHashMap::default();
|
||||
for (index, value) in set.iter().enumerate() {
|
||||
if value.is_literal_expr() {
|
||||
|
@ -72,7 +72,7 @@ pub(crate) fn duplicate_value(checker: &mut Checker, set: &ast::ExprSet) {
|
|||
remove_member(set, index, checker.locator().contents()).map(Fix::safe_edit)
|
||||
});
|
||||
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ impl Violation for ExceptWithEmptyTuple {
|
|||
}
|
||||
|
||||
/// B029
|
||||
pub(crate) fn except_with_empty_tuple(checker: &mut Checker, except_handler: &ExceptHandler) {
|
||||
pub(crate) fn except_with_empty_tuple(checker: &Checker, except_handler: &ExceptHandler) {
|
||||
let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) =
|
||||
except_handler;
|
||||
let Some(type_) = type_ else {
|
||||
|
@ -66,7 +66,7 @@ pub(crate) fn except_with_empty_tuple(checker: &mut Checker, except_handler: &Ex
|
|||
.current_statement()
|
||||
.as_try_stmt()
|
||||
.is_some_and(|try_stmt| try_stmt.is_star);
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
ExceptWithEmptyTuple { is_star },
|
||||
except_handler.range(),
|
||||
));
|
||||
|
|
|
@ -53,10 +53,7 @@ impl Violation for ExceptWithNonExceptionClasses {
|
|||
}
|
||||
|
||||
/// B030
|
||||
pub(crate) fn except_with_non_exception_classes(
|
||||
checker: &mut Checker,
|
||||
except_handler: &ExceptHandler,
|
||||
) {
|
||||
pub(crate) fn except_with_non_exception_classes(checker: &Checker, except_handler: &ExceptHandler) {
|
||||
let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { type_, .. }) =
|
||||
except_handler;
|
||||
let Some(type_) = type_ else {
|
||||
|
@ -72,7 +69,7 @@ pub(crate) fn except_with_non_exception_classes(
|
|||
.current_statement()
|
||||
.as_try_stmt()
|
||||
.is_some_and(|try_stmt| try_stmt.is_star);
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
ExceptWithNonExceptionClasses { is_star },
|
||||
expr.range(),
|
||||
));
|
||||
|
|
|
@ -41,7 +41,7 @@ impl Violation for FStringDocstring {
|
|||
}
|
||||
|
||||
/// B021
|
||||
pub(crate) fn f_string_docstring(checker: &mut Checker, body: &[Stmt]) {
|
||||
pub(crate) fn f_string_docstring(checker: &Checker, body: &[Stmt]) {
|
||||
let Some(stmt) = body.first() else {
|
||||
return;
|
||||
};
|
||||
|
@ -51,7 +51,5 @@ pub(crate) fn f_string_docstring(checker: &mut Checker, body: &[Stmt]) {
|
|||
if !value.is_f_string_expr() {
|
||||
return;
|
||||
}
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(FStringDocstring, stmt.identifier()));
|
||||
checker.report_diagnostic(Diagnostic::new(FStringDocstring, stmt.identifier()));
|
||||
}
|
||||
|
|
|
@ -128,7 +128,7 @@ impl Visitor<'_> for ArgumentDefaultVisitor<'_, '_> {
|
|||
}
|
||||
|
||||
/// B008
|
||||
pub(crate) fn function_call_in_argument_default(checker: &mut Checker, parameters: &Parameters) {
|
||||
pub(crate) fn function_call_in_argument_default(checker: &Checker, parameters: &Parameters) {
|
||||
// Map immutable calls to (module, member) format.
|
||||
let extend_immutable_calls: Vec<QualifiedName> = checker
|
||||
.settings
|
||||
|
@ -150,6 +150,6 @@ pub(crate) fn function_call_in_argument_default(checker: &mut Checker, parameter
|
|||
}
|
||||
|
||||
for (check, range) in visitor.diagnostics {
|
||||
checker.diagnostics.push(Diagnostic::new(check, range));
|
||||
checker.report_diagnostic(Diagnostic::new(check, range));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -277,7 +277,7 @@ impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> {
|
|||
}
|
||||
|
||||
/// B023
|
||||
pub(crate) fn function_uses_loop_variable(checker: &mut Checker, node: &Node) {
|
||||
pub(crate) fn function_uses_loop_variable(checker: &Checker, node: &Node) {
|
||||
// Identify any "suspicious" variables. These are defined as variables that are
|
||||
// referenced in a function or lambda body, but aren't bound as arguments.
|
||||
let suspicious_variables = {
|
||||
|
@ -304,9 +304,8 @@ pub(crate) fn function_uses_loop_variable(checker: &mut Checker, node: &Node) {
|
|||
// loop, flag it.
|
||||
for name in suspicious_variables {
|
||||
if reassigned_in_loop.contains(&name.id.as_str()) {
|
||||
if !checker.flake8_bugbear_seen.contains(&name.range()) {
|
||||
checker.flake8_bugbear_seen.push(name.range());
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
if checker.insert_flake8_bugbear_range(name.range()) {
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
FunctionUsesLoopVariable {
|
||||
name: name.id.to_string(),
|
||||
},
|
||||
|
|
|
@ -48,12 +48,7 @@ impl AlwaysFixableViolation for GetAttrWithConstant {
|
|||
}
|
||||
|
||||
/// B009
|
||||
pub(crate) fn getattr_with_constant(
|
||||
checker: &mut Checker,
|
||||
expr: &Expr,
|
||||
func: &Expr,
|
||||
args: &[Expr],
|
||||
) {
|
||||
pub(crate) fn getattr_with_constant(checker: &Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||
let [obj, arg] = args else {
|
||||
return;
|
||||
};
|
||||
|
@ -93,5 +88,5 @@ pub(crate) fn getattr_with_constant(
|
|||
),
|
||||
expr.range(),
|
||||
)));
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
|
|
@ -53,10 +53,10 @@ impl Violation for JumpStatementInFinally {
|
|||
}
|
||||
}
|
||||
|
||||
fn walk_stmt(checker: &mut Checker, body: &[Stmt], f: fn(&Stmt) -> bool) {
|
||||
fn walk_stmt(checker: &Checker, body: &[Stmt], f: fn(&Stmt) -> bool) {
|
||||
for stmt in body {
|
||||
if f(stmt) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
JumpStatementInFinally {
|
||||
name: match stmt {
|
||||
Stmt::Break(_) => "break",
|
||||
|
@ -89,7 +89,7 @@ fn walk_stmt(checker: &mut Checker, body: &[Stmt], f: fn(&Stmt) -> bool) {
|
|||
}
|
||||
|
||||
/// B012
|
||||
pub(crate) fn jump_statement_in_finally(checker: &mut Checker, finalbody: &[Stmt]) {
|
||||
pub(crate) fn jump_statement_in_finally(checker: &Checker, finalbody: &[Stmt]) {
|
||||
walk_stmt(checker, finalbody, |stmt| {
|
||||
matches!(stmt, Stmt::Break(_) | Stmt::Continue(_) | Stmt::Return(_))
|
||||
});
|
||||
|
|
|
@ -53,7 +53,7 @@ impl Violation for LoopIteratorMutation {
|
|||
}
|
||||
|
||||
/// B909
|
||||
pub(crate) fn loop_iterator_mutation(checker: &mut Checker, stmt_for: &StmtFor) {
|
||||
pub(crate) fn loop_iterator_mutation(checker: &Checker, stmt_for: &StmtFor) {
|
||||
let StmtFor {
|
||||
target,
|
||||
iter,
|
||||
|
@ -110,9 +110,7 @@ pub(crate) fn loop_iterator_mutation(checker: &mut Checker, stmt_for: &StmtFor)
|
|||
let name = UnqualifiedName::from_expr(iter)
|
||||
.map(|name| name.to_string())
|
||||
.map(SourceCodeSnippet::new);
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(LoopIteratorMutation { name }, *mutation));
|
||||
checker.report_diagnostic(Diagnostic::new(LoopIteratorMutation { name }, *mutation));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ impl Violation for LoopVariableOverridesIterator {
|
|||
}
|
||||
|
||||
/// B020
|
||||
pub(crate) fn loop_variable_overrides_iterator(checker: &mut Checker, target: &Expr, iter: &Expr) {
|
||||
pub(crate) fn loop_variable_overrides_iterator(checker: &Checker, target: &Expr, iter: &Expr) {
|
||||
let target_names = {
|
||||
let mut target_finder = NameFinder::default();
|
||||
target_finder.visit_expr(target);
|
||||
|
@ -64,7 +64,7 @@ pub(crate) fn loop_variable_overrides_iterator(checker: &mut Checker, target: &E
|
|||
|
||||
for (name, expr) in target_names {
|
||||
if iter_names.contains_key(name) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
LoopVariableOverridesIterator {
|
||||
name: name.to_string(),
|
||||
},
|
||||
|
|
|
@ -85,7 +85,7 @@ impl Violation for MutableArgumentDefault {
|
|||
}
|
||||
|
||||
/// B006
|
||||
pub(crate) fn mutable_argument_default(checker: &mut Checker, function_def: &ast::StmtFunctionDef) {
|
||||
pub(crate) fn mutable_argument_default(checker: &Checker, function_def: &ast::StmtFunctionDef) {
|
||||
// Skip stub files
|
||||
if checker.source_type.is_stub() {
|
||||
return;
|
||||
|
@ -124,7 +124,7 @@ pub(crate) fn mutable_argument_default(checker: &mut Checker, function_def: &ast
|
|||
) {
|
||||
diagnostic.set_fix(fix);
|
||||
}
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ impl Violation for MutableContextvarDefault {
|
|||
}
|
||||
|
||||
/// B039
|
||||
pub(crate) fn mutable_contextvar_default(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn mutable_contextvar_default(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::CONTEXTVARS) {
|
||||
return;
|
||||
}
|
||||
|
@ -102,8 +102,6 @@ pub(crate) fn mutable_contextvar_default(checker: &mut Checker, call: &ast::Expr
|
|||
matches!(qualified_name.segments(), ["contextvars", "ContextVar"])
|
||||
})
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(MutableContextvarDefault, default.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(MutableContextvarDefault, default.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ impl AlwaysFixableViolation for NoExplicitStacklevel {
|
|||
}
|
||||
|
||||
/// B028
|
||||
pub(crate) fn no_explicit_stacklevel(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn no_explicit_stacklevel(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker
|
||||
.semantic()
|
||||
.resolve_qualified_name(&call.func)
|
||||
|
@ -88,5 +88,5 @@ pub(crate) fn no_explicit_stacklevel(checker: &mut Checker, call: &ast::ExprCall
|
|||
|
||||
diagnostic.set_fix(Fix::unsafe_edit(edit));
|
||||
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
|
|
|
@ -37,10 +37,8 @@ impl Violation for RaiseLiteral {
|
|||
}
|
||||
|
||||
/// B016
|
||||
pub(crate) fn raise_literal(checker: &mut Checker, expr: &Expr) {
|
||||
pub(crate) fn raise_literal(checker: &Checker, expr: &Expr) {
|
||||
if expr.is_literal_expr() {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(RaiseLiteral, expr.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(RaiseLiteral, expr.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ impl Violation for RaiseWithoutFromInsideExcept {
|
|||
|
||||
/// B904
|
||||
pub(crate) fn raise_without_from_inside_except(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
name: Option<&str>,
|
||||
body: &[Stmt],
|
||||
) {
|
||||
|
@ -106,7 +106,7 @@ pub(crate) fn raise_without_from_inside_except(
|
|||
.as_try_stmt()
|
||||
.is_some_and(|try_stmt| try_stmt.is_star);
|
||||
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
RaiseWithoutFromInsideExcept { is_star },
|
||||
range,
|
||||
));
|
||||
|
|
|
@ -56,7 +56,7 @@ impl Violation for ReSubPositionalArgs {
|
|||
}
|
||||
|
||||
/// B034
|
||||
pub(crate) fn re_sub_positional_args(checker: &mut Checker, call: &ast::ExprCall) {
|
||||
pub(crate) fn re_sub_positional_args(checker: &Checker, call: &ast::ExprCall) {
|
||||
if !checker.semantic().seen_module(Modules::RE) {
|
||||
return;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ pub(crate) fn re_sub_positional_args(checker: &mut Checker, call: &ast::ExprCall
|
|||
};
|
||||
|
||||
if call.arguments.args.len() > method.num_args() {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
ReSubPositionalArgs { method },
|
||||
call.range(),
|
||||
));
|
||||
|
|
|
@ -53,10 +53,7 @@ impl AlwaysFixableViolation for RedundantTupleInExceptionHandler {
|
|||
}
|
||||
|
||||
/// B013
|
||||
pub(crate) fn redundant_tuple_in_exception_handler(
|
||||
checker: &mut Checker,
|
||||
handlers: &[ExceptHandler],
|
||||
) {
|
||||
pub(crate) fn redundant_tuple_in_exception_handler(checker: &Checker, handlers: &[ExceptHandler]) {
|
||||
for handler in handlers {
|
||||
let ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
|
||||
type_: Some(type_),
|
||||
|
@ -103,6 +100,6 @@ pub(crate) fn redundant_tuple_in_exception_handler(
|
|||
),
|
||||
type_.range(),
|
||||
)));
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ impl Violation for ReturnInGenerator {
|
|||
}
|
||||
|
||||
/// B901
|
||||
pub(crate) fn return_in_generator(checker: &mut Checker, function_def: &StmtFunctionDef) {
|
||||
pub(crate) fn return_in_generator(checker: &Checker, function_def: &StmtFunctionDef) {
|
||||
if function_def.name.id == "__await__" {
|
||||
return;
|
||||
}
|
||||
|
@ -101,9 +101,7 @@ pub(crate) fn return_in_generator(checker: &mut Checker, function_def: &StmtFunc
|
|||
|
||||
if visitor.has_yield {
|
||||
if let Some(return_) = visitor.return_ {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ReturnInGenerator, return_));
|
||||
checker.report_diagnostic(Diagnostic::new(ReturnInGenerator, return_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -307,7 +307,7 @@ impl<'a> Visitor<'a> for GroupNameFinder<'a> {
|
|||
|
||||
/// B031
|
||||
pub(crate) fn reuse_of_groupby_generator(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
target: &Expr,
|
||||
body: &[Stmt],
|
||||
iter: &Expr,
|
||||
|
@ -339,8 +339,6 @@ pub(crate) fn reuse_of_groupby_generator(
|
|||
finder.visit_stmt(stmt);
|
||||
}
|
||||
for expr in finder.exprs {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(ReuseOfGroupbyGenerator, expr.range()));
|
||||
checker.report_diagnostic(Diagnostic::new(ReuseOfGroupbyGenerator, expr.range()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,12 +61,7 @@ fn assignment(obj: &Expr, name: &str, value: &Expr, generator: Generator) -> Str
|
|||
}
|
||||
|
||||
/// B010
|
||||
pub(crate) fn setattr_with_constant(
|
||||
checker: &mut Checker,
|
||||
expr: &Expr,
|
||||
func: &Expr,
|
||||
args: &[Expr],
|
||||
) {
|
||||
pub(crate) fn setattr_with_constant(checker: &Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||
let [obj, name, value] = args else {
|
||||
return;
|
||||
};
|
||||
|
@ -100,7 +95,7 @@ pub(crate) fn setattr_with_constant(
|
|||
assignment(obj, name.to_str(), value, checker.generator()),
|
||||
expr.range(),
|
||||
)));
|
||||
checker.diagnostics.push(diagnostic);
|
||||
checker.report_diagnostic(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ impl Violation for StarArgUnpackingAfterKeywordArg {
|
|||
|
||||
/// B026
|
||||
pub(crate) fn star_arg_unpacking_after_keyword_arg(
|
||||
checker: &mut Checker,
|
||||
checker: &Checker,
|
||||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
|
@ -71,7 +71,7 @@ pub(crate) fn star_arg_unpacking_after_keyword_arg(
|
|||
if arg.start() <= keyword.start() {
|
||||
continue;
|
||||
}
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
StarArgUnpackingAfterKeywordArg,
|
||||
arg.range(),
|
||||
));
|
||||
|
|
|
@ -47,7 +47,7 @@ impl Violation for StaticKeyDictComprehension {
|
|||
}
|
||||
|
||||
/// RUF011
|
||||
pub(crate) fn static_key_dict_comprehension(checker: &mut Checker, dict_comp: &ast::ExprDictComp) {
|
||||
pub(crate) fn static_key_dict_comprehension(checker: &Checker, dict_comp: &ast::ExprDictComp) {
|
||||
// Collect the bound names in the comprehension's generators.
|
||||
let names = {
|
||||
let mut visitor = StoredNameFinder::default();
|
||||
|
@ -58,7 +58,7 @@ pub(crate) fn static_key_dict_comprehension(checker: &mut Checker, dict_comp: &a
|
|||
};
|
||||
|
||||
if is_constant(&dict_comp.key, &names) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
checker.report_diagnostic(Diagnostic::new(
|
||||
StaticKeyDictComprehension {
|
||||
key: SourceCodeSnippet::from_str(checker.locator().slice(dict_comp.key.as_ref())),
|
||||
},
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue