Return DiagnosticGuard from Checker::report_diagnostic (#18232)

Summary
--

This PR adds a `DiagnosticGuard` type to ruff that is adapted from the
`DiagnosticGuard` and `LintDiagnosticGuard` types from ty. This guard is
returned by `Checker::report_diagnostic` and derefs to a
`ruff_diagnostics::Diagnostic` (`OldDiagnostic`), allowing methods like
`OldDiagnostic::set_fix` to be called on the result. On `Drop` the
`DiagnosticGuard` pushes its contained `OldDiagnostic` to the `Checker`.

The main motivation for this is to make a following PR adding a
`SourceFile` to each diagnostic easier. For every rule where a `Checker`
is available, this will now only require modifying
`Checker::report_diagnostic` rather than all the rules.

In the few cases where we need to create a diagnostic before we know if
we actually want to emit it, there is a `DiagnosticGuard::defuse`
method, which consumes the guard without emitting the diagnostic. I was
able to restructure about half of the rules that naively called this to
avoid calling it, but a handful of rules still need it.

One of the fairly common patterns where `defuse` was needed initially
was something like

```rust
let diagnostic = Diagnostic::new(DiagnosticKind, range);

if !checker.enabled(diagnostic.rule()) {
    return;
}
```

So I also added a `Checker::checked_report_diagnostic` method that
handles this check internally. That helped to avoid some additional
`defuse` calls. The name is a bit repetitive, so I'm definitely open to
suggestions there. I included a warning against using it in the docs
since, as we've seen, the conversion from a diagnostic to a rule is
actually pretty expensive.

Test Plan
--

Existing tests
This commit is contained in:
Brent Westbrook 2025-05-28 07:41:31 -04:00 committed by GitHub
parent b60ba75d09
commit a3ee6bb3b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
590 changed files with 2983 additions and 3790 deletions

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Fix};
use ruff_diagnostics::Fix;
use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
@ -38,92 +38,64 @@ pub(crate) fn bindings(checker: &Checker) {
.dummy_variable_rgx
.is_match(binding.name(checker.source()))
{
let mut diagnostic = Diagnostic::new(
pyflakes::rules::UnusedVariable {
name: binding.name(checker.source()).to_string(),
},
binding.range(),
);
diagnostic.try_set_fix(|| {
pyflakes::fixes::remove_exception_handler_assignment(binding, checker.locator)
checker
.report_diagnostic(
pyflakes::rules::UnusedVariable {
name: binding.name(checker.source()).to_string(),
},
binding.range(),
)
.try_set_fix(|| {
pyflakes::fixes::remove_exception_handler_assignment(
binding,
checker.locator,
)
.map(Fix::safe_edit)
});
checker.report_diagnostic(diagnostic);
});
}
}
if checker.enabled(Rule::InvalidAllFormat) {
if let Some(diagnostic) = pylint::rules::invalid_all_format(binding) {
checker.report_diagnostic(diagnostic);
}
pylint::rules::invalid_all_format(checker, binding);
}
if checker.enabled(Rule::InvalidAllObject) {
if let Some(diagnostic) = pylint::rules::invalid_all_object(binding) {
checker.report_diagnostic(diagnostic);
}
pylint::rules::invalid_all_object(checker, binding);
}
if checker.enabled(Rule::NonAsciiName) {
if let Some(diagnostic) = pylint::rules::non_ascii_name(binding, checker.locator) {
checker.report_diagnostic(diagnostic);
}
pylint::rules::non_ascii_name(checker, binding);
}
if checker.enabled(Rule::UnconventionalImportAlias) {
if let Some(diagnostic) = flake8_import_conventions::rules::unconventional_import_alias(
flake8_import_conventions::rules::unconventional_import_alias(
checker,
binding,
&checker.settings.flake8_import_conventions.aliases,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::UnaliasedCollectionsAbcSetImport) {
if let Some(diagnostic) =
flake8_pyi::rules::unaliased_collections_abc_set_import(checker, binding)
{
checker.report_diagnostic(diagnostic);
}
flake8_pyi::rules::unaliased_collections_abc_set_import(checker, binding);
}
if !checker.source_type.is_stub() && checker.enabled(Rule::UnquotedTypeAlias) {
flake8_type_checking::rules::unquoted_type_alias(checker, binding);
}
if checker.enabled(Rule::UnsortedDunderSlots) {
if let Some(diagnostic) = ruff::rules::sort_dunder_slots(checker, binding) {
checker.report_diagnostic(diagnostic);
}
ruff::rules::sort_dunder_slots(checker, binding);
}
if checker.enabled(Rule::UsedDummyVariable) {
if let Some(diagnostic) = ruff::rules::used_dummy_variable(checker, binding, binding_id)
{
checker.report_diagnostic(diagnostic);
}
ruff::rules::used_dummy_variable(checker, binding, binding_id);
}
if checker.enabled(Rule::AssignmentInAssert) {
if let Some(diagnostic) = ruff::rules::assignment_in_assert(checker, binding) {
checker.report_diagnostic(diagnostic);
}
ruff::rules::assignment_in_assert(checker, binding);
}
if checker.enabled(Rule::PytestUnittestRaisesAssertion) {
if let Some(diagnostic) =
flake8_pytest_style::rules::unittest_raises_assertion_binding(checker, binding)
{
checker.report_diagnostic(diagnostic);
}
flake8_pytest_style::rules::unittest_raises_assertion_binding(checker, binding);
}
if checker.enabled(Rule::ForLoopWrites) {
if let Some(diagnostic) = refurb::rules::for_loop_writes_binding(checker, binding) {
checker.report_diagnostic(diagnostic);
}
refurb::rules::for_loop_writes_binding(checker, binding);
}
if checker.enabled(Rule::CustomTypeVarForSelf) {
if let Some(diagnostic) =
flake8_pyi::rules::custom_type_var_instead_of_self(checker, binding)
{
checker.report_diagnostic(diagnostic);
}
flake8_pyi::rules::custom_type_var_instead_of_self(checker, binding);
}
if checker.enabled(Rule::PrivateTypeParameter) {
if let Some(diagnostic) = pyupgrade::rules::private_type_parameter(checker, binding) {
checker.report_diagnostic(diagnostic);
}
pyupgrade::rules::private_type_parameter(checker, binding);
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Fix};
use ruff_diagnostics::Fix;
use ruff_python_semantic::analyze::visibility;
use ruff_python_semantic::{Binding, BindingKind, Imported, ResolvedReference, ScopeKind};
use ruff_text_size::Ranged;
@ -112,12 +112,12 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
.map(|id| checker.semantic.reference(*id))
.all(ResolvedReference::is_load)
{
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pylint::rules::GlobalVariableNotAssigned {
name: (*name).to_string(),
},
binding.range(),
));
);
}
}
}
@ -146,12 +146,12 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
if scope.kind.is_generator() {
continue;
}
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pylint::rules::RedefinedArgumentFromLocal {
name: name.to_string(),
},
binding.range(),
));
);
}
}
}
@ -186,13 +186,13 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
continue;
}
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pyflakes::rules::ImportShadowedByLoopVar {
name: name.to_string(),
row: checker.compute_source_row(shadowed.start()),
},
binding.range(),
));
);
}
}
}
@ -331,7 +331,7 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
// Create diagnostics for each statement.
for (source, entries) in &redefinitions {
for (shadowed, binding) in entries {
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
pyflakes::rules::RedefinedWhileUnused {
name: binding.name(checker.source()).to_string(),
row: checker.compute_source_row(shadowed.start()),
@ -346,8 +346,6 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
if let Some(fix) = source.as_ref().and_then(|source| fixes.get(source)) {
diagnostic.set_fix(fix.clone());
}
checker.report_diagnostic(diagnostic);
}
}
}

View file

@ -17,14 +17,7 @@ pub(crate) fn except_handler(except_handler: &ExceptHandler, checker: &Checker)
range: _,
}) => {
if checker.enabled(Rule::BareExcept) {
if let Some(diagnostic) = pycodestyle::rules::bare_except(
type_.as_deref(),
body,
except_handler,
checker.locator,
) {
checker.report_diagnostic(diagnostic);
}
pycodestyle::rules::bare_except(checker, type_.as_deref(), body, except_handler);
}
if checker.enabled(Rule::RaiseWithoutFromInsideExcept) {
flake8_bugbear::rules::raise_without_from_inside_except(

View file

@ -1,8 +1,6 @@
use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Operator};
use ruff_python_literal::cformat::{CFormatError, CFormatErrorType};
use ruff_diagnostics::Diagnostic;
use ruff_python_ast::types::Node;
use ruff_python_semantic::ScopeKind;
use ruff_python_semantic::analyze::typing;
@ -195,14 +193,13 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
let check_too_many_expressions = checker.enabled(Rule::ExpressionsInStarAssignment);
let check_two_starred_expressions =
checker.enabled(Rule::MultipleStarredExpressions);
if let Some(diagnostic) = pyflakes::rules::starred_expressions(
pyflakes::rules::starred_expressions(
checker,
elts,
check_too_many_expressions,
check_two_starred_expressions,
expr.range(),
) {
checker.report_diagnostic(diagnostic);
}
);
}
}
Expr::Name(ast::ExprName { id, ctx, range }) => {
@ -527,12 +524,12 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
match pyflakes::format::FormatSummary::try_from(string_value.to_str()) {
Err(e) => {
if checker.enabled(Rule::StringDotFormatInvalidFormat) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pyflakes::rules::StringDotFormatInvalidFormat {
message: pyflakes::format::error_to_string(&e),
},
location,
));
);
}
}
Ok(summary) => {
@ -936,9 +933,7 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
pylint::rules::repeated_keyword_argument(checker, call);
}
if checker.enabled(Rule::PytestPatchWithLambda) {
if let Some(diagnostic) = flake8_pytest_style::rules::patch_with_lambda(call) {
checker.report_diagnostic(diagnostic);
}
flake8_pytest_style::rules::patch_with_lambda(checker, call);
}
if checker.any_enabled(&[
Rule::PytestParametrizeNamesWrongType,
@ -1286,22 +1281,22 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
..
}) => {
if checker.enabled(Rule::PercentFormatUnsupportedFormatCharacter) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pyflakes::rules::PercentFormatUnsupportedFormatCharacter {
char: c,
},
location,
));
);
}
}
Err(e) => {
if checker.enabled(Rule::PercentFormatInvalidFormat) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pyflakes::rules::PercentFormatInvalidFormat {
message: e.to_string(),
},
location,
));
);
}
}
Ok(summary) => {
@ -1365,10 +1360,7 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
op: Operator::Add, ..
}) => {
if checker.enabled(Rule::ExplicitStringConcatenation) {
if let Some(diagnostic) = flake8_implicit_str_concat::rules::explicit(expr, checker)
{
checker.report_diagnostic(diagnostic);
}
flake8_implicit_str_concat::rules::explicit(checker, expr);
}
if checker.enabled(Rule::CollectionLiteralConcatenation) {
ruff::rules::collection_literal_concatenation(checker, expr);

View file

@ -1,4 +1,3 @@
use ruff_diagnostics::Diagnostic;
use ruff_python_ast::helpers;
use ruff_python_ast::types::Node;
use ruff_python_ast::{self as ast, Expr, Stmt};
@ -39,12 +38,12 @@ 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.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pylint::rules::NonlocalWithoutBinding {
name: name.to_string(),
},
name.range(),
));
);
}
}
}
@ -55,22 +54,20 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
}
Stmt::Break(_) => {
if checker.enabled(Rule::BreakOutsideLoop) {
if let Some(diagnostic) = pyflakes::rules::break_outside_loop(
pyflakes::rules::break_outside_loop(
checker,
stmt,
&mut checker.semantic.current_statements().skip(1),
) {
checker.report_diagnostic(diagnostic);
}
);
}
}
Stmt::Continue(_) => {
if checker.enabled(Rule::ContinueOutsideLoop) {
if let Some(diagnostic) = pyflakes::rules::continue_outside_loop(
pyflakes::rules::continue_outside_loop(
checker,
stmt,
&mut checker.semantic.current_statements().skip(1),
) {
checker.report_diagnostic(diagnostic);
}
);
}
}
Stmt::FunctionDef(
@ -98,9 +95,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
fastapi::rules::fastapi_unused_path_parameter(checker, function_def);
}
if checker.enabled(Rule::AmbiguousFunctionName) {
if let Some(diagnostic) = pycodestyle::rules::ambiguous_function_name(name) {
checker.report_diagnostic(diagnostic);
}
pycodestyle::rules::ambiguous_function_name(checker, name);
}
if checker.enabled(Rule::InvalidBoolReturnType) {
pylint::rules::invalid_bool_return(checker, function_def);
@ -121,15 +116,14 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
pylint::rules::invalid_str_return(checker, function_def);
}
if checker.enabled(Rule::InvalidFunctionName) {
if let Some(diagnostic) = pep8_naming::rules::invalid_function_name(
pep8_naming::rules::invalid_function_name(
checker,
stmt,
name,
decorator_list,
&checker.settings.pep8_naming.ignore_names,
&checker.semantic,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.source_type.is_stub() {
if checker.enabled(Rule::PassStatementStubBody) {
@ -179,14 +173,13 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
flake8_pyi::rules::pep_484_positional_parameter(checker, function_def);
}
if checker.enabled(Rule::DunderFunctionName) {
if let Some(diagnostic) = pep8_naming::rules::dunder_function_name(
pep8_naming::rules::dunder_function_name(
checker,
checker.semantic.current_scope(),
stmt,
name,
&checker.settings.pep8_naming.ignore_names,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::GlobalStatement) {
pylint::rules::global_statement(checker, name);
@ -231,14 +224,13 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
);
}
if checker.enabled(Rule::ComplexStructure) {
if let Some(diagnostic) = mccabe::rules::function_is_too_complex(
mccabe::rules::function_is_too_complex(
checker,
stmt,
name,
body,
checker.settings.mccabe.max_complexity,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::HardcodedPasswordDefault) {
flake8_bandit::rules::hardcoded_password_default(checker, parameters);
@ -258,31 +250,28 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
pylint::rules::too_many_positional_arguments(checker, function_def);
}
if checker.enabled(Rule::TooManyReturnStatements) {
if let Some(diagnostic) = pylint::rules::too_many_return_statements(
pylint::rules::too_many_return_statements(
checker,
stmt,
body,
checker.settings.pylint.max_returns,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::TooManyBranches) {
if let Some(diagnostic) = pylint::rules::too_many_branches(
pylint::rules::too_many_branches(
checker,
stmt,
body,
checker.settings.pylint.max_branches,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::TooManyStatements) {
if let Some(diagnostic) = pylint::rules::too_many_statements(
pylint::rules::too_many_statements(
checker,
stmt,
body,
checker.settings.pylint.max_statements,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.any_enabled(&[
Rule::PytestFixtureIncorrectParenthesesStyle,
@ -451,28 +440,24 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
pyupgrade::rules::unnecessary_class_parentheses(checker, class_def);
}
if checker.enabled(Rule::AmbiguousClassName) {
if let Some(diagnostic) = pycodestyle::rules::ambiguous_class_name(name) {
checker.report_diagnostic(diagnostic);
}
pycodestyle::rules::ambiguous_class_name(checker, name);
}
if checker.enabled(Rule::InvalidClassName) {
if let Some(diagnostic) = pep8_naming::rules::invalid_class_name(
pep8_naming::rules::invalid_class_name(
checker,
stmt,
name,
&checker.settings.pep8_naming.ignore_names,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::ErrorSuffixOnExceptionName) {
if let Some(diagnostic) = pep8_naming::rules::error_suffix_on_exception_name(
pep8_naming::rules::error_suffix_on_exception_name(
checker,
stmt,
arguments.as_deref(),
name,
&checker.settings.pep8_naming.ignore_names,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if !checker.source_type.is_stub() {
if checker.any_enabled(&[
@ -611,11 +596,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
}
if checker.enabled(Rule::Debugger) {
if let Some(diagnostic) =
flake8_debugger::rules::debugger_import(stmt, None, &alias.name)
{
checker.report_diagnostic(diagnostic);
}
flake8_debugger::rules::debugger_import(checker, stmt, None, &alias.name);
}
if checker.enabled(Rule::BannedApi) {
flake8_tidy_imports::rules::banned_api(
@ -638,94 +619,74 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
pylint::rules::manual_from_import(checker, stmt, alias, names);
}
if checker.enabled(Rule::ImportSelf) {
if let Some(diagnostic) =
pylint::rules::import_self(alias, checker.module.qualified_name())
{
checker.report_diagnostic(diagnostic);
}
pylint::rules::import_self(checker, alias, checker.module.qualified_name());
}
if let Some(asname) = &alias.asname {
let name = alias.name.split('.').next_back().unwrap();
if checker.enabled(Rule::ConstantImportedAsNonConstant) {
if let Some(diagnostic) =
pep8_naming::rules::constant_imported_as_non_constant(
name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
)
{
checker.report_diagnostic(diagnostic);
}
}
if checker.enabled(Rule::LowercaseImportedAsNonLowercase) {
if let Some(diagnostic) =
pep8_naming::rules::lowercase_imported_as_non_lowercase(
name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
)
{
checker.report_diagnostic(diagnostic);
}
}
if checker.enabled(Rule::CamelcaseImportedAsLowercase) {
if let Some(diagnostic) =
pep8_naming::rules::camelcase_imported_as_lowercase(
name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
)
{
checker.report_diagnostic(diagnostic);
}
}
if checker.enabled(Rule::CamelcaseImportedAsConstant) {
if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_constant(
pep8_naming::rules::constant_imported_as_non_constant(
checker,
name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::LowercaseImportedAsNonLowercase) {
pep8_naming::rules::lowercase_imported_as_non_lowercase(
checker,
name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
);
}
if checker.enabled(Rule::CamelcaseImportedAsLowercase) {
pep8_naming::rules::camelcase_imported_as_lowercase(
checker,
name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
);
}
if checker.enabled(Rule::CamelcaseImportedAsConstant) {
pep8_naming::rules::camelcase_imported_as_constant(
checker,
name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
);
}
if checker.enabled(Rule::CamelcaseImportedAsAcronym) {
if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_acronym(
pep8_naming::rules::camelcase_imported_as_acronym(
name, asname, alias, stmt, checker,
) {
checker.report_diagnostic(diagnostic);
}
);
}
}
if checker.enabled(Rule::BannedImportAlias) {
if let Some(asname) = &alias.asname {
if let Some(diagnostic) =
flake8_import_conventions::rules::banned_import_alias(
stmt,
&alias.name,
asname,
&checker.settings.flake8_import_conventions.banned_aliases,
)
{
checker.report_diagnostic(diagnostic);
}
flake8_import_conventions::rules::banned_import_alias(
checker,
stmt,
&alias.name,
asname,
&checker.settings.flake8_import_conventions.banned_aliases,
);
}
}
if checker.enabled(Rule::PytestIncorrectPytestImport) {
if let Some(diagnostic) = flake8_pytest_style::rules::import(
flake8_pytest_style::rules::import(
checker,
stmt,
&alias.name,
alias.asname.as_deref(),
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::BuiltinImportShadowing) {
flake8_builtins::rules::builtin_import_shadowing(checker, alias);
@ -837,11 +798,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
}
if checker.enabled(Rule::PytestIncorrectPytestImport) {
if let Some(diagnostic) =
flake8_pytest_style::rules::import_from(stmt, module, level)
{
checker.report_diagnostic(diagnostic);
}
flake8_pytest_style::rules::import_from(checker, stmt, module, level);
}
if checker.source_type.is_stub() {
if checker.enabled(Rule::FutureAnnotationsInStub) {
@ -856,119 +813,98 @@ 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.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pyflakes::rules::UndefinedLocalWithNestedImportStarUsage {
name: helpers::format_import_from(level, module).to_string(),
},
stmt.range(),
));
);
}
}
if checker.enabled(Rule::UndefinedLocalWithImportStar) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pyflakes::rules::UndefinedLocalWithImportStar {
name: helpers::format_import_from(level, module).to_string(),
},
stmt.range(),
));
);
}
}
if checker.enabled(Rule::RelativeImports) {
if let Some(diagnostic) = flake8_tidy_imports::rules::banned_relative_import(
flake8_tidy_imports::rules::banned_relative_import(
checker,
stmt,
level,
module,
checker.module.qualified_name(),
checker.settings.flake8_tidy_imports.ban_relative_imports,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::Debugger) {
if let Some(diagnostic) =
flake8_debugger::rules::debugger_import(stmt, module, &alias.name)
{
checker.report_diagnostic(diagnostic);
}
flake8_debugger::rules::debugger_import(checker, stmt, module, &alias.name);
}
if checker.enabled(Rule::BannedImportAlias) {
if let Some(asname) = &alias.asname {
let qualified_name =
helpers::format_import_from_member(level, module, &alias.name);
if let Some(diagnostic) =
flake8_import_conventions::rules::banned_import_alias(
stmt,
&qualified_name,
asname,
&checker.settings.flake8_import_conventions.banned_aliases,
)
{
checker.report_diagnostic(diagnostic);
}
flake8_import_conventions::rules::banned_import_alias(
checker,
stmt,
&qualified_name,
asname,
&checker.settings.flake8_import_conventions.banned_aliases,
);
}
}
if let Some(asname) = &alias.asname {
if checker.enabled(Rule::ConstantImportedAsNonConstant) {
if let Some(diagnostic) =
pep8_naming::rules::constant_imported_as_non_constant(
&alias.name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
)
{
checker.report_diagnostic(diagnostic);
}
}
if checker.enabled(Rule::LowercaseImportedAsNonLowercase) {
if let Some(diagnostic) =
pep8_naming::rules::lowercase_imported_as_non_lowercase(
&alias.name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
)
{
checker.report_diagnostic(diagnostic);
}
}
if checker.enabled(Rule::CamelcaseImportedAsLowercase) {
if let Some(diagnostic) =
pep8_naming::rules::camelcase_imported_as_lowercase(
&alias.name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
)
{
checker.report_diagnostic(diagnostic);
}
}
if checker.enabled(Rule::CamelcaseImportedAsConstant) {
if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_constant(
pep8_naming::rules::constant_imported_as_non_constant(
checker,
&alias.name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::LowercaseImportedAsNonLowercase) {
pep8_naming::rules::lowercase_imported_as_non_lowercase(
checker,
&alias.name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
);
}
if checker.enabled(Rule::CamelcaseImportedAsLowercase) {
pep8_naming::rules::camelcase_imported_as_lowercase(
checker,
&alias.name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
);
}
if checker.enabled(Rule::CamelcaseImportedAsConstant) {
pep8_naming::rules::camelcase_imported_as_constant(
checker,
&alias.name,
asname,
alias,
stmt,
&checker.settings.pep8_naming.ignore_names,
);
}
if checker.enabled(Rule::CamelcaseImportedAsAcronym) {
if let Some(diagnostic) = pep8_naming::rules::camelcase_imported_as_acronym(
pep8_naming::rules::camelcase_imported_as_acronym(
&alias.name,
asname,
alias,
stmt,
checker,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if !checker.source_type.is_stub() {
if checker.enabled(Rule::UselessImportAlias) {
@ -981,23 +917,21 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
}
}
if checker.enabled(Rule::ImportSelf) {
if let Some(diagnostic) = pylint::rules::import_from_self(
pylint::rules::import_from_self(
checker,
level,
module,
names,
checker.module.qualified_name(),
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::BannedImportFrom) {
if let Some(diagnostic) = flake8_import_conventions::rules::banned_import_from(
flake8_import_conventions::rules::banned_import_from(
checker,
stmt,
&helpers::format_import_from(level, module),
&checker.settings.flake8_import_conventions.banned_from,
) {
checker.report_diagnostic(diagnostic);
}
);
}
if checker.enabled(Rule::ByteStringUsage) {
flake8_pyi::rules::bytestring_import(checker, import_from);
@ -1212,7 +1146,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
) => {
if !checker.semantic.in_type_checking_block() {
if checker.enabled(Rule::Assert) {
checker.report_diagnostic(flake8_bandit::rules::assert_used(stmt));
flake8_bandit::rules::assert_used(checker, stmt);
}
}
if checker.enabled(Rule::AssertTuple) {
@ -1409,11 +1343,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
}
}
if checker.enabled(Rule::DefaultExceptNotLast) {
if let Some(diagnostic) =
pyflakes::rules::default_except_not_last(handlers, checker.locator)
{
checker.report_diagnostic(diagnostic);
}
pyflakes::rules::default_except_not_last(checker, handlers, checker.locator);
}
if checker.any_enabled(&[
Rule::DuplicateHandlerException,
@ -1508,9 +1438,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.report_diagnostic(diagnostic);
}
pandas_vet::rules::assignment_to_df(checker, targets);
}
if checker
.settings
@ -1704,11 +1632,7 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
pylint::rules::named_expr_without_context(checker, value);
}
if checker.enabled(Rule::AsyncioDanglingTask) {
if let Some(diagnostic) =
ruff::rules::asyncio_dangling_task(value, checker.semantic())
{
checker.report_diagnostic(diagnostic);
}
ruff::rules::asyncio_dangling_task(checker, value, checker.semantic());
}
if checker.enabled(Rule::RepeatedAppend) {
refurb::rules::repeated_append(checker, stmt);

View file

@ -1,4 +1,3 @@
use ruff_diagnostics::Diagnostic;
use ruff_python_semantic::Exceptions;
use ruff_python_stdlib::builtins::version_builtin_was_added;
@ -15,12 +14,12 @@ pub(crate) fn unresolved_references(checker: &Checker) {
for reference in checker.semantic.unresolved_references() {
if reference.is_wildcard_import() {
if checker.enabled(Rule::UndefinedLocalWithImportStarUsage) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pyflakes::rules::UndefinedLocalWithImportStarUsage {
name: reference.name(checker.source()).to_string(),
},
reference.range(),
));
);
}
} else {
if checker.enabled(Rule::UndefinedName) {
@ -42,13 +41,13 @@ pub(crate) fn unresolved_references(checker: &Checker) {
let symbol_name = reference.name(checker.source());
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
pyflakes::rules::UndefinedName {
name: symbol_name.to_string(),
minor_version_builtin_added: version_builtin_was_added(symbol_name),
},
reference.range(),
));
);
}
}
}

View file

@ -31,7 +31,7 @@ use ruff_python_parser::semantic_errors::{
};
use rustc_hash::{FxHashMap, FxHashSet};
use ruff_diagnostics::{Diagnostic, Edit, IsolationLevel};
use ruff_diagnostics::{Diagnostic, Edit, IsolationLevel, Violation};
use ruff_notebook::{CellOffsets, NotebookIndex};
use ruff_python_ast::helpers::{collect_import_from_member, is_docstring_stmt, to_module_path};
use ruff_python_ast::identifier::Identifier;
@ -66,7 +66,7 @@ use crate::importer::{ImportRequest, Importer, ResolutionError};
use crate::noqa::NoqaMapping;
use crate::package::PackageRoot;
use crate::preview::{is_semantic_errors_enabled, is_undefined_export_in_dunder_init_enabled};
use crate::registry::Rule;
use crate::registry::{AsRule, Rule};
use crate::rules::pyflakes::rules::{
LateFutureImport, ReturnOutsideFunction, YieldOutsideFunction,
};
@ -379,10 +379,40 @@ 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);
/// Return a [`DiagnosticGuard`] for reporting a diagnostic.
///
/// The guard derefs to a [`Diagnostic`], so it can be used to further modify the diagnostic
/// before it is added to the collection in the checker on `Drop`.
pub(crate) fn report_diagnostic<'chk, T: Violation>(
&'chk self,
kind: T,
range: TextRange,
) -> DiagnosticGuard<'chk, 'a> {
DiagnosticGuard {
checker: self,
diagnostic: Some(Diagnostic::new(kind, range)),
}
}
/// Return a [`DiagnosticGuard`] for reporting a diagnostic if the corresponding rule is
/// enabled.
///
/// Prefer [`Checker::report_diagnostic`] in general because the conversion from a `Diagnostic`
/// to a `Rule` is somewhat expensive.
pub(crate) fn report_diagnostic_if_enabled<'chk, T: Violation>(
&'chk self,
kind: T,
range: TextRange,
) -> Option<DiagnosticGuard<'chk, 'a>> {
let diagnostic = Diagnostic::new(kind, range);
if self.enabled(diagnostic.rule()) {
Some(DiagnosticGuard {
checker: self,
diagnostic: Some(diagnostic),
})
} else {
None
}
}
/// Adds a [`TextRange`] to the set of ranges of variable names
@ -508,9 +538,9 @@ impl<'a> Checker<'a> {
}
/// Push `diagnostic` if the checker is not in a `@no_type_check` context.
pub(crate) fn report_type_diagnostic(&self, diagnostic: Diagnostic) {
pub(crate) fn report_type_diagnostic<T: Violation>(&self, kind: T, range: TextRange) {
if !self.semantic.in_no_type_check() {
self.report_diagnostic(diagnostic);
self.report_diagnostic(kind, range);
}
}
@ -595,7 +625,7 @@ impl SemanticSyntaxContext for Checker<'_> {
match error.kind {
SemanticSyntaxErrorKind::LateFutureImport => {
if self.settings.rules.enabled(Rule::LateFutureImport) {
self.report_diagnostic(Diagnostic::new(LateFutureImport, error.range));
self.report_diagnostic(LateFutureImport, error.range);
}
}
SemanticSyntaxErrorKind::LoadBeforeGlobalDeclaration { name, start } => {
@ -604,31 +634,28 @@ impl SemanticSyntaxContext for Checker<'_> {
.rules
.enabled(Rule::LoadBeforeGlobalDeclaration)
{
self.report_diagnostic(Diagnostic::new(
self.report_diagnostic(
LoadBeforeGlobalDeclaration {
name,
row: self.compute_source_row(start),
},
error.range,
));
);
}
}
SemanticSyntaxErrorKind::YieldOutsideFunction(kind) => {
if self.settings.rules.enabled(Rule::YieldOutsideFunction) {
self.report_diagnostic(Diagnostic::new(
YieldOutsideFunction::new(kind),
error.range,
));
self.report_diagnostic(YieldOutsideFunction::new(kind), error.range);
}
}
SemanticSyntaxErrorKind::ReturnOutsideFunction => {
if self.settings.rules.enabled(Rule::ReturnOutsideFunction) {
self.report_diagnostic(Diagnostic::new(ReturnOutsideFunction, error.range));
self.report_diagnostic(ReturnOutsideFunction, error.range);
}
}
SemanticSyntaxErrorKind::AwaitOutsideAsyncFunction(_) => {
if self.settings.rules.enabled(Rule::AwaitOutsideAsync) {
self.report_diagnostic(Diagnostic::new(AwaitOutsideAsync, error.range));
self.report_diagnostic(AwaitOutsideAsync, error.range);
}
}
SemanticSyntaxErrorKind::ReboundComprehensionVariable
@ -2717,12 +2744,12 @@ impl<'a> Checker<'a> {
self.semantic.restore(snapshot);
if self.enabled(Rule::ForwardAnnotationSyntaxError) {
self.report_type_diagnostic(Diagnostic::new(
self.report_type_diagnostic(
pyflakes::rules::ForwardAnnotationSyntaxError {
parse_error: parse_error.error.to_string(),
},
string_expr.range(),
));
);
}
}
}
@ -3020,3 +3047,59 @@ pub(crate) fn check_ast(
(diagnostics.into_inner(), semantic_errors.into_inner())
}
/// An abstraction for mutating a diagnostic.
///
/// Callers can build this guard by starting with `Checker::report_diagnostic`.
///
/// The primary function of this guard is to add the underlying diagnostic to the `Checker`'s list
/// of diagnostics on `Drop`, while dereferencing to the underlying diagnostic for mutations like
/// adding fixes or parent ranges.
pub(crate) struct DiagnosticGuard<'a, 'b> {
/// The parent checker that will receive the diagnostic on `Drop`.
checker: &'a Checker<'b>,
/// The diagnostic that we want to report.
///
/// This is always `Some` until the `Drop` (or `defuse`) call.
diagnostic: Option<Diagnostic>,
}
impl DiagnosticGuard<'_, '_> {
/// Consume the underlying `Diagnostic` without emitting it.
///
/// In general you should avoid constructing diagnostics that may not be emitted, but this
/// method can be used where this is unavoidable.
pub(crate) fn defuse(mut self) {
self.diagnostic = None;
}
}
impl std::ops::Deref for DiagnosticGuard<'_, '_> {
type Target = Diagnostic;
fn deref(&self) -> &Diagnostic {
// OK because `self.diagnostic` is only `None` within `Drop`.
self.diagnostic.as_ref().unwrap()
}
}
/// Return a mutable borrow of the diagnostic in this guard.
impl std::ops::DerefMut for DiagnosticGuard<'_, '_> {
fn deref_mut(&mut self) -> &mut Diagnostic {
// OK because `self.diagnostic` is only `None` within `Drop`.
self.diagnostic.as_mut().unwrap()
}
}
impl Drop for DiagnosticGuard<'_, '_> {
fn drop(&mut self) {
if std::thread::panicking() {
// Don't submit diagnostics when panicking because they might be incomplete.
return;
}
if let Some(diagnostic) = self.diagnostic.take() {
self.checker.diagnostics.borrow_mut().push(diagnostic);
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::Expr;
use ruff_python_ast::{self as ast};
@ -86,6 +86,5 @@ pub(crate) fn dag_no_schedule_argument(checker: &Checker, expr: &Expr) {
}
// Produce a diagnostic when the `schedule` keyword argument is not found.
let diagnostic = Diagnostic::new(AirflowDagNoScheduleArgument, expr.range());
checker.report_diagnostic(diagnostic);
checker.report_diagnostic(AirflowDagNoScheduleArgument, expr.range());
}

View file

@ -1,7 +1,8 @@
use crate::importer::ImportRequest;
use crate::rules::airflow::helpers::{ProviderReplacement, is_guarded_by_try_except};
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::QualifiedName;
use ruff_python_ast::{Expr, ExprAttribute};
use ruff_python_semantic::Modules;
use ruff_text_size::Ranged;
@ -28,12 +29,12 @@ use crate::checkers::ast::Checker;
/// from airflow.providers.fab.auth_manager.fab_auth_manage import FabAuthManager
/// ```
#[derive(ViolationMetadata)]
pub(crate) struct Airflow3MovedToProvider {
deprecated: String,
pub(crate) struct Airflow3MovedToProvider<'a> {
deprecated: QualifiedName<'a>,
replacement: ProviderReplacement,
}
impl Violation for Airflow3MovedToProvider {
impl Violation for Airflow3MovedToProvider<'_> {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
#[derive_message_formats]
@ -1197,34 +1198,42 @@ fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRan
_ => return,
};
let mut diagnostic = Diagnostic::new(
Airflow3MovedToProvider {
deprecated: qualified_name.to_string(),
replacement: replacement.clone(),
},
ranged.range(),
);
let semantic = checker.semantic();
if let Some((module, name)) = match &replacement {
ProviderReplacement::AutoImport { module, name, .. } => Some((module, *name)),
let (module, name) = match &replacement {
ProviderReplacement::AutoImport { module, name, .. } => (module, *name),
ProviderReplacement::SourceModuleMovedToProvider { module, name, .. } => {
Some((module, name.as_str()))
(module, name.as_str())
}
ProviderReplacement::None => None,
} {
if is_guarded_by_try_except(expr, module, name, semantic) {
ProviderReplacement::None => {
checker.report_diagnostic(
Airflow3MovedToProvider {
deprecated: qualified_name,
replacement,
},
ranged,
);
return;
}
diagnostic.try_set_fix(|| {
};
if is_guarded_by_try_except(expr, module, name, checker.semantic()) {
return;
}
checker
.report_diagnostic(
Airflow3MovedToProvider {
deprecated: qualified_name,
replacement: replacement.clone(),
},
ranged,
)
.try_set_fix(|| {
let (import_edit, binding) = checker.importer().get_or_import_symbol(
&ImportRequest::import_from(module, name),
expr.start(),
checker.semantic(),
)?;
let replacement_edit = Edit::range_replacement(binding, ranged.range());
let replacement_edit = Edit::range_replacement(binding, ranged);
Ok(Fix::safe_edits(import_edit, [replacement_edit]))
});
}
checker.report_diagnostic(diagnostic);
}

View file

@ -3,7 +3,7 @@ use crate::importer::ImportRequest;
use crate::rules::airflow::helpers::{
Replacement, is_airflow_builtin_or_provider, is_guarded_by_try_except,
};
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::map_callable;
use ruff_python_ast::{
@ -166,13 +166,13 @@ fn check_function_parameters(checker: &Checker, function_def: &StmtFunctionDef)
for param in function_def.parameters.iter_non_variadic_params() {
let param_name = param.name();
if REMOVED_CONTEXT_KEYS.contains(&param_name.as_str()) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
Airflow3Removal {
deprecated: param_name.to_string(),
replacement: Replacement::None,
},
param_name.range(),
));
);
}
}
}
@ -200,7 +200,7 @@ fn check_call_arguments(checker: &Checker, qualified_name: &QualifiedName, argum
segments => {
if is_airflow_auth_manager(segments) {
if !arguments.is_empty() {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
Airflow3Removal {
deprecated: String::from("appbuilder"),
replacement: Replacement::Message(
@ -208,7 +208,7 @@ fn check_call_arguments(checker: &Checker, qualified_name: &QualifiedName, argum
),
},
arguments.range(),
));
);
}
} else if is_airflow_task_handler(segments) {
diagnostic_for_argument(checker, arguments, "filename_template", None);
@ -305,7 +305,7 @@ fn check_class_attribute(checker: &Checker, attribute_expr: &ExprAttribute) {
} else {
None
};
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
Airflow3Removal {
deprecated: attr.to_string(),
replacement,
@ -315,7 +315,6 @@ fn check_class_attribute(checker: &Checker, attribute_expr: &ExprAttribute) {
if let Some(fix) = fix {
diagnostic.set_fix(fix);
}
checker.report_diagnostic(diagnostic);
}
/// Checks whether an Airflow 3.0removed context key is used in a function decorated with `@task`.
@ -382,13 +381,13 @@ fn check_context_key_usage_in_call(checker: &Checker, call_expr: &ExprCall) {
continue;
};
if value == removed_key {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
Airflow3Removal {
deprecated: removed_key.to_string(),
replacement: Replacement::None,
},
*range,
));
);
}
}
}
@ -423,13 +422,13 @@ fn check_context_key_usage_in_subscript(checker: &Checker, subscript: &ExprSubsc
}
if REMOVED_CONTEXT_KEYS.contains(&key.to_str()) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
Airflow3Removal {
deprecated: key.to_string(),
replacement: Replacement::None,
},
slice.range(),
));
);
}
}
@ -537,7 +536,7 @@ fn check_method(checker: &Checker, call_expr: &ExprCall) {
None
};
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
Airflow3Removal {
deprecated: attr.to_string(),
replacement,
@ -547,7 +546,6 @@ fn check_method(checker: &Checker, call_expr: &ExprCall) {
if let Some(fix) = fix {
diagnostic.set_fix(fix);
}
checker.report_diagnostic(diagnostic);
}
/// Check whether a removed Airflow name is used.
@ -966,26 +964,36 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) {
_ => return,
};
let mut diagnostic = Diagnostic::new(
Airflow3Removal {
deprecated: qualified_name.to_string(),
replacement: replacement.clone(),
},
range,
);
let semantic = checker.semantic();
if let Some((module, name)) = match &replacement {
Replacement::AutoImport { module, name } => Some((module, *name)),
Replacement::SourceModuleMoved { module, name } => Some((module, name.as_str())),
_ => None,
} {
if is_guarded_by_try_except(expr, module, name, semantic) {
let (module, name) = match &replacement {
Replacement::AutoImport { module, name } => (module, *name),
Replacement::SourceModuleMoved { module, name } => (module, name.as_str()),
_ => {
checker.report_diagnostic(
Airflow3Removal {
deprecated: qualified_name.to_string(),
replacement: replacement.clone(),
},
range,
);
return;
}
};
let import_target = name.split('.').next().unwrap_or(name);
if is_guarded_by_try_except(expr, module, name, checker.semantic()) {
return;
}
diagnostic.try_set_fix(|| {
let import_target = name.split('.').next().unwrap_or(name);
checker
.report_diagnostic(
Airflow3Removal {
deprecated: qualified_name.to_string(),
replacement: replacement.clone(),
},
range,
)
.try_set_fix(|| {
let (import_edit, _) = checker.importer().get_or_import_symbol(
&ImportRequest::import_from(module, import_target),
expr.start(),
@ -994,9 +1002,6 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) {
let replacement_edit = Edit::range_replacement(name.to_string(), range);
Ok(Fix::safe_edits(import_edit, [replacement_edit]))
});
}
checker.report_diagnostic(diagnostic);
}
/// Check whether a customized Airflow plugin contains removed extensions.
@ -1028,7 +1033,7 @@ fn check_airflow_plugin_extension(
)
})
}) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
Airflow3Removal {
deprecated: name.to_string(),
replacement: Replacement::Message(
@ -1036,7 +1041,7 @@ fn check_airflow_plugin_extension(
),
},
expr.range(),
));
);
}
}
}
@ -1052,7 +1057,11 @@ fn diagnostic_for_argument(
let Some(keyword) = arguments.find_keyword(deprecated) else {
return;
};
let mut diagnostic = Diagnostic::new(
let range = keyword
.arg
.as_ref()
.map_or_else(|| keyword.range(), Ranged::range);
let mut diagnostic = checker.report_diagnostic(
Airflow3Removal {
deprecated: deprecated.to_string(),
replacement: match replacement {
@ -1060,20 +1069,15 @@ fn diagnostic_for_argument(
None => Replacement::None,
},
},
keyword
.arg
.as_ref()
.map_or_else(|| keyword.range(), Ranged::range),
range,
);
if let Some(replacement) = replacement {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
replacement.to_string(),
diagnostic.range,
range,
)));
}
checker.report_diagnostic(diagnostic);
}
/// Check whether the symbol is coming from the `secrets` builtin or provider module which ends

View file

@ -1,8 +1,9 @@
use crate::importer::ImportRequest;
use crate::rules::airflow::helpers::{ProviderReplacement, is_guarded_by_try_except};
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::QualifiedName;
use ruff_python_ast::{Expr, ExprAttribute};
use ruff_python_semantic::Modules;
use ruff_text_size::Ranged;
@ -30,12 +31,12 @@ use crate::checkers::ast::Checker;
/// from airflow.providers.standard.operators.python import PythonOperator
/// ```
#[derive(ViolationMetadata)]
pub(crate) struct Airflow3SuggestedToMoveToProvider {
deprecated: String,
pub(crate) struct Airflow3SuggestedToMoveToProvider<'a> {
deprecated: QualifiedName<'a>,
replacement: ProviderReplacement,
}
impl Violation for Airflow3SuggestedToMoveToProvider {
impl Violation for Airflow3SuggestedToMoveToProvider<'_> {
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
#[derive_message_formats]
fn message(&self) -> String {
@ -281,26 +282,36 @@ fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRan
_ => return,
};
let mut diagnostic = Diagnostic::new(
Airflow3SuggestedToMoveToProvider {
deprecated: qualified_name.to_string(),
replacement: replacement.clone(),
},
ranged.range(),
);
let semantic = checker.semantic();
if let Some((module, name)) = match &replacement {
ProviderReplacement::AutoImport { module, name, .. } => Some((module, *name)),
let (module, name) = match &replacement {
ProviderReplacement::AutoImport { module, name, .. } => (module, *name),
ProviderReplacement::SourceModuleMovedToProvider { module, name, .. } => {
Some((module, name.as_str()))
(module, name.as_str())
}
ProviderReplacement::None => None,
} {
if is_guarded_by_try_except(expr, module, name, semantic) {
ProviderReplacement::None => {
checker.report_diagnostic(
Airflow3SuggestedToMoveToProvider {
deprecated: qualified_name,
replacement: replacement.clone(),
},
ranged.range(),
);
return;
}
diagnostic.try_set_fix(|| {
};
if is_guarded_by_try_except(expr, module, name, checker.semantic()) {
return;
}
checker
.report_diagnostic(
Airflow3SuggestedToMoveToProvider {
deprecated: qualified_name,
replacement: replacement.clone(),
},
ranged.range(),
)
.try_set_fix(|| {
let (import_edit, binding) = checker.importer().get_or_import_symbol(
&ImportRequest::import_from(module, name),
expr.start(),
@ -309,7 +320,4 @@ fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRan
let replacement_edit = Edit::range_replacement(binding, ranged.range());
Ok(Fix::safe_edits(import_edit, [replacement_edit]))
});
}
checker.report_diagnostic(diagnostic);
}

View file

@ -3,7 +3,7 @@ use crate::importer::ImportRequest;
use crate::rules::airflow::helpers::{
Replacement, is_airflow_builtin_or_provider, is_guarded_by_try_except,
};
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{Arguments, Expr, ExprAttribute, ExprCall, ExprName, name::QualifiedName};
use ruff_python_semantic::Modules;
@ -120,7 +120,11 @@ fn diagnostic_for_argument(
let Some(keyword) = arguments.find_keyword(deprecated) else {
return;
};
let mut diagnostic = Diagnostic::new(
let range = keyword
.arg
.as_ref()
.map_or_else(|| keyword.range(), Ranged::range);
let mut diagnostic = checker.report_diagnostic(
Airflow3SuggestedUpdate {
deprecated: deprecated.to_string(),
replacement: match replacement {
@ -128,20 +132,15 @@ fn diagnostic_for_argument(
None => Replacement::None,
},
},
keyword
.arg
.as_ref()
.map_or_else(|| keyword.range(), Ranged::range),
range,
);
if let Some(replacement) = replacement {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
replacement.to_string(),
diagnostic.range,
range,
)));
}
checker.report_diagnostic(diagnostic);
}
/// Check whether a removed Airflow argument is passed.
///
@ -284,24 +283,34 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) {
_ => return,
};
let mut diagnostic = Diagnostic::new(
Airflow3SuggestedUpdate {
deprecated: qualified_name.to_string(),
replacement: replacement.clone(),
},
range,
);
let semantic = checker.semantic();
if let Some((module, name)) = match &replacement {
Replacement::AutoImport { module, name } => Some((module, *name)),
Replacement::SourceModuleMoved { module, name } => Some((module, name.as_str())),
_ => None,
} {
if is_guarded_by_try_except(expr, module, name, semantic) {
let (module, name) = match &replacement {
Replacement::AutoImport { module, name } => (module, *name),
Replacement::SourceModuleMoved { module, name } => (module, name.as_str()),
_ => {
checker.report_diagnostic(
Airflow3SuggestedUpdate {
deprecated: qualified_name.to_string(),
replacement: replacement.clone(),
},
range,
);
return;
}
diagnostic.try_set_fix(|| {
};
if is_guarded_by_try_except(expr, module, name, checker.semantic()) {
return;
}
checker
.report_diagnostic(
Airflow3SuggestedUpdate {
deprecated: qualified_name.to_string(),
replacement: replacement.clone(),
},
range,
)
.try_set_fix(|| {
let (import_edit, binding) = checker.importer().get_or_import_symbol(
&ImportRequest::import_from(module, name),
expr.start(),
@ -310,7 +319,4 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) {
let replacement_edit = Edit::range_replacement(binding, range);
Ok(Fix::safe_edits(import_edit, [replacement_edit]))
});
}
checker.report_diagnostic(diagnostic);
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_python_ast::Expr;
@ -110,11 +110,10 @@ pub(crate) fn variable_name_task_id(checker: &Checker, targets: &[Expr], value:
return;
}
let diagnostic = Diagnostic::new(
checker.report_diagnostic(
AirflowVariableNameTaskIdMismatch {
task_id: task_id.to_string(),
},
target.range(),
);
checker.report_diagnostic(diagnostic);
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_python_ast::helpers::map_callable;
@ -237,7 +237,7 @@ fn create_diagnostic(
return seen_default;
};
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
FastApiNonAnnotatedDependency {
py_version: checker.target_version(),
},
@ -308,7 +308,5 @@ fn create_diagnostic(
}
diagnostic.try_set_optional_fix(|| fix);
checker.report_diagnostic(diagnostic);
seen_default
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Fix};
use ruff_diagnostics::{AlwaysFixableViolation, Fix};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{Decorator, Expr, ExprCall, Keyword, StmtFunctionDef};
use ruff_python_semantic::{Modules, SemanticModel};
@ -85,7 +85,7 @@ pub(crate) fn fastapi_redundant_response_model(checker: &Checker, function_def:
continue;
};
let mut diagnostic =
Diagnostic::new(FastApiRedundantResponseModel, response_model_arg.range());
checker.report_diagnostic(FastApiRedundantResponseModel, response_model_arg.range());
diagnostic.try_set_fix(|| {
remove_argument(
response_model_arg,
@ -95,7 +95,6 @@ pub(crate) fn fastapi_redundant_response_model(checker: &Checker, function_def:
)
.map(Fix::unsafe_edit)
});
checker.report_diagnostic(diagnostic);
}
}

View file

@ -3,7 +3,7 @@ use std::ops::Range;
use std::str::CharIndices;
use ruff_diagnostics::Fix;
use ruff_diagnostics::{Diagnostic, FixAvailability, Violation};
use ruff_diagnostics::{FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_python_ast::{Arguments, Expr, ExprCall, ExprSubscript, Parameter, ParameterWithDefault};
@ -186,7 +186,7 @@ pub(crate) fn fastapi_unused_path_parameter(
.iter()
.any(|param| param.name() == path_param);
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
FastApiUnusedPathParameter {
arg_name: path_param.to_string(),
function_name: function_def.name.to_string(),
@ -204,7 +204,6 @@ pub(crate) fn fastapi_unused_path_parameter(
checker.locator().contents(),
)));
}
checker.report_diagnostic(diagnostic);
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, CmpOp, Expr};
use ruff_text_size::Ranged;
@ -254,12 +254,12 @@ pub(crate) fn compare(checker: &Checker, left: &Expr, ops: &[CmpOp], comparators
) = (ops, comparators)
{
if *n == 3 && checker.enabled(Rule::SysVersionInfo0Eq3) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
SysVersionInfo0Eq3 {
eq: matches!(*operator, CmpOp::Eq),
},
left.range(),
));
);
}
}
} else if *i == 1 {
@ -274,10 +274,7 @@ pub(crate) fn compare(checker: &Checker, left: &Expr, ops: &[CmpOp], comparators
) = (ops, comparators)
{
if checker.enabled(Rule::SysVersionInfo1CmpInt) {
checker.report_diagnostic(Diagnostic::new(
SysVersionInfo1CmpInt,
left.range(),
));
checker.report_diagnostic(SysVersionInfo1CmpInt, left.range());
}
}
}
@ -298,10 +295,7 @@ pub(crate) fn compare(checker: &Checker, left: &Expr, ops: &[CmpOp], comparators
) = (ops, comparators)
{
if checker.enabled(Rule::SysVersionInfoMinorCmpInt) {
checker.report_diagnostic(Diagnostic::new(
SysVersionInfoMinorCmpInt,
left.range(),
));
checker.report_diagnostic(SysVersionInfoMinorCmpInt, left.range());
}
}
}
@ -317,10 +311,10 @@ pub(crate) fn compare(checker: &Checker, left: &Expr, ops: &[CmpOp], comparators
{
if value.len() == 1 {
if checker.enabled(Rule::SysVersionCmpStr10) {
checker.report_diagnostic(Diagnostic::new(SysVersionCmpStr10, left.range()));
checker.report_diagnostic(SysVersionCmpStr10, left.range());
}
} else if checker.enabled(Rule::SysVersionCmpStr3) {
checker.report_diagnostic(Diagnostic::new(SysVersionCmpStr3, left.range()));
checker.report_diagnostic(SysVersionCmpStr3, left.range());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::Expr;
use ruff_python_semantic::Modules;
@ -56,6 +56,6 @@ pub(crate) fn name_or_attribute(checker: &Checker, expr: &Expr) {
.resolve_qualified_name(expr)
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["six", "PY3"]))
{
checker.report_diagnostic(Diagnostic::new(SixPY3, expr.range()));
checker.report_diagnostic(SixPY3, expr.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;
@ -183,9 +183,9 @@ pub(crate) fn subscript(checker: &Checker, value: &Expr, slice: &Expr) {
}) = upper.as_ref()
{
if *i == 1 && checker.enabled(Rule::SysVersionSlice1) {
checker.report_diagnostic(Diagnostic::new(SysVersionSlice1, value.range()));
checker.report_diagnostic(SysVersionSlice1, value.range());
} else if *i == 3 && checker.enabled(Rule::SysVersionSlice3) {
checker.report_diagnostic(Diagnostic::new(SysVersionSlice3, value.range()));
checker.report_diagnostic(SysVersionSlice3, value.range());
}
}
}
@ -195,9 +195,9 @@ pub(crate) fn subscript(checker: &Checker, value: &Expr, slice: &Expr) {
..
}) => {
if *i == 2 && checker.enabled(Rule::SysVersion2) {
checker.report_diagnostic(Diagnostic::new(SysVersion2, value.range()));
checker.report_diagnostic(SysVersion2, value.range());
} else if *i == 0 && checker.enabled(Rule::SysVersion0) {
checker.report_diagnostic(Diagnostic::new(SysVersion0, value.range()));
checker.report_diagnostic(SysVersion0, value.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::ReturnStatementVisitor;
use ruff_python_ast::identifier::Identifier;
@ -9,7 +9,7 @@ use ruff_python_semantic::analyze::visibility;
use ruff_python_stdlib::typing::simple_magic_return_type;
use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
use crate::checkers::ast::{Checker, DiagnosticGuard};
use crate::registry::Rule;
use crate::rules::flake8_annotations::helpers::auto_return_type;
use crate::rules::ruff::typing::type_hint_resolves_to_any;
@ -529,11 +529,11 @@ fn is_none_returning(body: &[Stmt]) -> bool {
}
/// ANN401
fn check_dynamically_typed<F>(
checker: &Checker,
fn check_dynamically_typed<'a, 'b, F>(
checker: &'a Checker<'b>,
annotation: &Expr,
func: F,
diagnostics: &mut Vec<Diagnostic>,
diagnostics: &mut Vec<DiagnosticGuard<'a, 'b>>,
) where
F: FnOnce() -> String,
{
@ -545,18 +545,14 @@ fn check_dynamically_typed<F>(
checker,
checker.target_version(),
) {
diagnostics.push(Diagnostic::new(
AnyType { name: func() },
annotation.range(),
));
diagnostics
.push(checker.report_diagnostic(AnyType { name: func() }, annotation.range()));
}
}
} else {
if type_hint_resolves_to_any(annotation, checker, checker.target_version()) {
diagnostics.push(Diagnostic::new(
AnyType { name: func() },
annotation.range(),
));
diagnostics
.push(checker.report_diagnostic(AnyType { name: func() }, annotation.range()));
}
}
}
@ -655,7 +651,7 @@ pub(crate) fn definition(
.is_match(parameter.name()))
{
if checker.enabled(Rule::MissingTypeFunctionArgument) {
diagnostics.push(Diagnostic::new(
diagnostics.push(checker.report_diagnostic(
MissingTypeFunctionArgument {
name: parameter.name().to_string(),
},
@ -681,7 +677,7 @@ pub(crate) fn definition(
&& checker.settings.dummy_variable_rgx.is_match(&arg.name))
{
if checker.enabled(Rule::MissingTypeArgs) {
diagnostics.push(Diagnostic::new(
diagnostics.push(checker.report_diagnostic(
MissingTypeArgs {
name: arg.name.to_string(),
},
@ -712,7 +708,7 @@ pub(crate) fn definition(
&& checker.settings.dummy_variable_rgx.is_match(&arg.name))
{
if checker.enabled(Rule::MissingTypeKwargs) {
diagnostics.push(Diagnostic::new(
diagnostics.push(checker.report_diagnostic(
MissingTypeKwargs {
name: arg.name.to_string(),
},
@ -745,7 +741,7 @@ pub(crate) fn definition(
})
.map(|(return_type, edits)| (checker.generator().expr(&return_type), edits))
};
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
MissingReturnTypeClassMethod {
name: name.to_string(),
annotation: return_type.clone().map(|(return_type, ..)| return_type),
@ -771,7 +767,7 @@ pub(crate) fn definition(
})
.map(|(return_type, edits)| (checker.generator().expr(&return_type), edits))
};
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
MissingReturnTypeStaticMethod {
name: name.to_string(),
annotation: return_type.clone().map(|(return_type, ..)| return_type),
@ -791,7 +787,7 @@ pub(crate) fn definition(
// least one argument is typed.
if checker.enabled(Rule::MissingReturnTypeSpecialMethod) {
if !(checker.settings.flake8_annotations.mypy_init_return && has_any_typed_arg) {
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
MissingReturnTypeSpecialMethod {
name: name.to_string(),
annotation: Some("None".to_string()),
@ -808,7 +804,7 @@ pub(crate) fn definition(
} else if is_method && visibility::is_magic(name) {
if checker.enabled(Rule::MissingReturnTypeSpecialMethod) {
let return_type = simple_magic_return_type(name);
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
MissingReturnTypeSpecialMethod {
name: name.to_string(),
annotation: return_type.map(ToString::to_string),
@ -839,7 +835,7 @@ pub(crate) fn definition(
(checker.generator().expr(&return_type), edits)
})
};
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
MissingReturnTypeUndocumentedPublicFunction {
name: name.to_string(),
annotation: return_type
@ -874,7 +870,7 @@ pub(crate) fn definition(
(checker.generator().expr(&return_type), edits)
})
};
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
MissingReturnTypePrivateFunction {
name: name.to_string(),
annotation: return_type
@ -901,7 +897,7 @@ pub(crate) fn definition(
// If settings say so, don't report any of the
// diagnostics gathered here if there were no type annotations at all.
if !checker.settings.flake8_annotations.ignore_fully_untyped
let diagnostics_enabled = !checker.settings.flake8_annotations.ignore_fully_untyped
|| has_any_typed_arg
|| has_typed_return
|| (is_method
@ -910,10 +906,11 @@ pub(crate) fn definition(
.posonlyargs
.first()
.or_else(|| parameters.args.first())
.is_some_and(|first_param| first_param.annotation().is_some()))
{
.is_some_and(|first_param| first_param.annotation().is_some()));
if !diagnostics_enabled {
for diagnostic in diagnostics {
checker.report_diagnostic(diagnostic);
diagnostic.defuse();
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr, Stmt};
use ruff_text_size::Ranged;
@ -74,11 +74,11 @@ pub(crate) fn async_busy_wait(checker: &Checker, while_stmt: &ast::StmtWhile) {
qualified_name.segments(),
["trio" | "anyio", "sleep" | "sleep_until"] | ["asyncio", "sleep"]
) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
AsyncBusyWait {
module: AsyncModule::try_from(&qualified_name).unwrap(),
},
while_stmt.range(),
));
);
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_python_semantic::Modules;
@ -112,8 +112,5 @@ pub(crate) fn async_function_with_timeout(checker: &Checker, function_def: &ast:
return;
}
checker.report_diagnostic(Diagnostic::new(
AsyncFunctionWithTimeout { module },
timeout.range(),
));
checker.report_diagnostic(AsyncFunctionWithTimeout { module }, timeout.range());
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_diagnostics::{AlwaysFixableViolation, Edit, Fix};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr, ExprCall, Int, Number};
use ruff_python_semantic::Modules;
@ -109,7 +109,7 @@ pub(crate) fn async_zero_sleep(checker: &Checker, call: &ExprCall) {
return;
}
let mut diagnostic = Diagnostic::new(AsyncZeroSleep { module }, call.range());
let mut diagnostic = checker.report_diagnostic(AsyncZeroSleep { module }, call.range());
diagnostic.try_set_fix(|| {
let (import_edit, binding) = checker.importer().get_or_import_symbol(
&ImportRequest::import_from(&module.to_string(), "lowlevel"),
@ -121,6 +121,5 @@ pub(crate) fn async_zero_sleep(checker: &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.report_diagnostic(diagnostic);
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::ExprCall;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::QualifiedName;
use ruff_text_size::Ranged;
@ -70,10 +70,7 @@ pub(crate) fn blocking_http_call(checker: &Checker, call: &ExprCall) {
.as_ref()
.is_some_and(is_blocking_http_call)
{
checker.report_diagnostic(Diagnostic::new(
BlockingHttpCallInAsyncFunction,
call.func.range(),
));
checker.report_diagnostic(BlockingHttpCallInAsyncFunction, call.func.range());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_python_semantic::{SemanticModel, analyze};
@ -52,10 +52,7 @@ pub(crate) fn blocking_open_call(checker: &Checker, call: &ast::ExprCall) {
if is_open_call(&call.func, checker.semantic())
|| is_open_call_from_pathlib(call.func.as_ref(), checker.semantic())
{
checker.report_diagnostic(Diagnostic::new(
BlockingOpenCallInAsyncFunction,
call.func.range(),
));
checker.report_diagnostic(BlockingOpenCallInAsyncFunction, call.func.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_python_semantic::SemanticModel;
@ -6,7 +6,6 @@ use ruff_python_semantic::analyze::typing::find_assigned_value;
use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
/// ## What it does
/// Checks that async functions do not create subprocesses with blocking methods.
@ -125,17 +124,17 @@ pub(crate) fn blocking_process_invocation(checker: &Checker, call: &ast::ExprCal
};
let range = call.func.range();
let diagnostic = match qualified_name.segments() {
match qualified_name.segments() {
["subprocess", "Popen"] | ["os", "popen"] => {
Diagnostic::new(CreateSubprocessInAsyncFunction, range)
checker.report_diagnostic_if_enabled(CreateSubprocessInAsyncFunction, range)
}
["os", "system" | "posix_spawn" | "posix_spawnp"]
| [
"subprocess",
"run" | "call" | "check_call" | "check_output" | "getoutput" | "getstatusoutput",
] => Diagnostic::new(RunProcessInAsyncFunction, range),
] => checker.report_diagnostic_if_enabled(RunProcessInAsyncFunction, range),
["os", "wait" | "wait3" | "wait4" | "waitid" | "waitpid"] => {
Diagnostic::new(WaitForProcessInAsyncFunction, range)
checker.report_diagnostic_if_enabled(WaitForProcessInAsyncFunction, range)
}
[
"os",
@ -143,17 +142,13 @@ pub(crate) fn blocking_process_invocation(checker: &Checker, call: &ast::ExprCal
| "spawnvpe",
] => {
if is_p_wait(call, checker.semantic()) {
Diagnostic::new(RunProcessInAsyncFunction, range)
checker.report_diagnostic_if_enabled(RunProcessInAsyncFunction, range)
} else {
Diagnostic::new(CreateSubprocessInAsyncFunction, range)
checker.report_diagnostic_if_enabled(CreateSubprocessInAsyncFunction, range)
}
}
_ => return,
};
if checker.enabled(diagnostic.rule()) {
checker.report_diagnostic(diagnostic);
}
}
fn is_p_wait(call: &ast::ExprCall, semantic: &SemanticModel) -> bool {

View file

@ -1,6 +1,6 @@
use ruff_python_ast::ExprCall;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::QualifiedName;
use ruff_text_size::Ranged;
@ -51,10 +51,7 @@ pub(crate) fn blocking_sleep(checker: &Checker, call: &ExprCall) {
.as_ref()
.is_some_and(is_blocking_sleep)
{
checker.report_diagnostic(Diagnostic::new(
BlockingSleepInAsyncFunction,
call.func.range(),
));
checker.report_diagnostic(BlockingSleepInAsyncFunction, call.func.range());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::{AwaitVisitor, any_over_body};
use ruff_python_ast::visitor::Visitor;
@ -100,8 +100,5 @@ pub(crate) fn cancel_scope_no_checkpoint(
return;
}
checker.report_diagnostic(Diagnostic::new(
CancelScopeNoCheckpoint { method_name },
with_stmt.range,
));
checker.report_diagnostic(CancelScopeNoCheckpoint { method_name }, with_stmt.range);
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{Expr, ExprCall, ExprNumberLiteral, Number};
use ruff_python_semantic::Modules;
@ -137,7 +137,7 @@ pub(crate) fn long_sleep_not_forever(checker: &Checker, call: &ExprCall) {
return;
}
let mut diagnostic = Diagnostic::new(LongSleepNotForever { module }, call.range());
let mut diagnostic = checker.report_diagnostic(LongSleepNotForever { module }, call.range());
let replacement_function = "sleep_forever";
diagnostic.try_set_fix(|| {
let (import_edit, binding) = checker.importer().get_or_import_symbol(
@ -149,5 +149,4 @@ pub(crate) fn long_sleep_not_forever(checker: &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.report_diagnostic(diagnostic);
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{Expr, ExprCall};
use ruff_python_semantic::Modules;
@ -80,7 +80,7 @@ pub(crate) fn sync_call(checker: &Checker, call: &ExprCall) {
return;
}
let mut diagnostic = Diagnostic::new(TrioSyncCall { method_name }, call.range);
let mut diagnostic = checker.report_diagnostic(TrioSyncCall { method_name }, call.range);
if checker.semantic().in_async_context() {
diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion(
pad(
@ -91,5 +91,4 @@ pub(crate) fn sync_call(checker: &Checker, call: &ExprCall) {
call.func.start(),
)));
}
checker.report_diagnostic(diagnostic);
}

View file

@ -1,10 +1,12 @@
use ruff_python_ast::Stmt;
use ruff_text_size::{TextLen, TextRange};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
/// ## What it does
/// Checks for uses of the `assert` keyword.
///
@ -41,6 +43,6 @@ impl Violation for Assert {
}
/// S101
pub(crate) fn assert_used(stmt: &Stmt) -> Diagnostic {
Diagnostic::new(Assert, TextRange::at(stmt.start(), "assert".text_len()))
pub(crate) fn assert_used(checker: &Checker, stmt: &Stmt) {
checker.report_diagnostic(Assert, TextRange::at(stmt.start(), "assert".text_len()));
}

View file

@ -1,6 +1,6 @@
use anyhow::Result;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::QualifiedName;
use ruff_python_ast::{self as ast, Expr, Operator};
@ -78,22 +78,22 @@ pub(crate) fn bad_file_permissions(checker: &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.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
BadFilePermissions {
reason: Reason::Permissive(mask),
},
mode_arg.range(),
));
);
}
}
// The mask is an invalid integer value (i.e., it's out of range).
Err(_) => {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
BadFilePermissions {
reason: Reason::Invalid,
},
mode_arg.range(),
));
);
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr, ExprAttribute};
use ruff_text_size::Ranged;
@ -54,7 +54,7 @@ pub(crate) fn django_extra(checker: &Checker, call: &ast::ExprCall) {
}
if is_call_insecure(call) {
checker.report_diagnostic(Diagnostic::new(DjangoExtra, call.arguments.range()));
checker.report_diagnostic(DjangoExtra, call.arguments.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_python_semantic::Modules;
@ -55,7 +55,7 @@ pub(crate) fn django_raw_sql(checker: &Checker, call: &ast::ExprCall) {
.find_argument_value("sql", 0)
.is_some_and(Expr::is_string_literal_expr)
{
checker.report_diagnostic(Diagnostic::new(DjangoRawSql, call.func.range()));
checker.report_diagnostic(DjangoRawSql, call.func.range());
}
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::Expr;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -34,6 +34,6 @@ impl Violation for ExecBuiltin {
/// S102
pub(crate) fn exec_used(checker: &Checker, func: &Expr) {
if checker.semantic().match_builtin_expr(func, "exec") {
checker.report_diagnostic(Diagnostic::new(ExecBuiltin, func.range()));
checker.report_diagnostic(ExecBuiltin, func.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_const_true;
use ruff_python_ast::{Expr, ExprAttribute, ExprCall};
@ -67,6 +67,6 @@ pub(crate) fn flask_debug_true(checker: &Checker, call: &ExprCall) {
if typing::resolve_assignment(value, checker.semantic())
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["flask", "Flask"]))
{
checker.report_diagnostic(Diagnostic::new(FlaskDebugTrue, debug_argument.range()));
checker.report_diagnostic(FlaskDebugTrue, debug_argument.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, StringLike};
use ruff_text_size::Ranged;
@ -41,8 +41,7 @@ pub(crate) fn hardcoded_bind_all_interfaces(checker: &Checker, string: StringLik
match string {
StringLike::String(ast::ExprStringLiteral { value, .. }) => {
if value == "0.0.0.0" {
checker
.report_diagnostic(Diagnostic::new(HardcodedBindAllInterfaces, string.range()));
checker.report_diagnostic(HardcodedBindAllInterfaces, string.range());
}
}
StringLike::FString(ast::ExprFString { value, .. }) => {
@ -50,19 +49,14 @@ pub(crate) fn hardcoded_bind_all_interfaces(checker: &Checker, string: StringLik
match part {
ast::FStringPart::Literal(literal) => {
if &**literal == "0.0.0.0" {
checker.report_diagnostic(Diagnostic::new(
HardcodedBindAllInterfaces,
literal.range(),
));
checker.report_diagnostic(HardcodedBindAllInterfaces, literal.range());
}
}
ast::FStringPart::FString(f_string) => {
for literal in f_string.elements.literals() {
if &**literal == "0.0.0.0" {
checker.report_diagnostic(Diagnostic::new(
HardcodedBindAllInterfaces,
literal.range(),
));
checker
.report_diagnostic(HardcodedBindAllInterfaces, literal.range());
}
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{Expr, Parameter, Parameters};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -54,18 +54,20 @@ impl Violation for HardcodedPasswordDefault {
}
}
fn check_password_kwarg(parameter: &Parameter, default: &Expr) -> Option<Diagnostic> {
string_literal(default).filter(|string| !string.is_empty())?;
fn check_password_kwarg(checker: &Checker, parameter: &Parameter, default: &Expr) {
if string_literal(default).is_none_or(str::is_empty) {
return;
}
let kwarg_name = &parameter.name;
if !matches_password_name(kwarg_name) {
return None;
return;
}
Some(Diagnostic::new(
checker.report_diagnostic(
HardcodedPasswordDefault {
name: kwarg_name.to_string(),
},
default.range(),
))
);
}
/// S107
@ -74,8 +76,6 @@ pub(crate) fn hardcoded_password_default(checker: &Checker, parameters: &Paramet
let Some(default) = parameter.default() else {
continue;
};
if let Some(diagnostic) = check_password_kwarg(&parameter.parameter, default) {
checker.report_diagnostic(diagnostic);
}
check_password_kwarg(checker, &parameter.parameter, default);
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::Keyword;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -62,11 +62,11 @@ pub(crate) fn hardcoded_password_func_arg(checker: &Checker, keywords: &[Keyword
if !matches_password_name(arg) {
continue;
}
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
HardcodedPasswordFuncArg {
name: arg.to_string(),
},
keyword.range(),
));
);
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;
@ -83,12 +83,12 @@ pub(crate) fn compare_to_hardcoded_password_string(
let Some(name) = password_target(left) else {
continue;
};
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
HardcodedPasswordString {
name: name.to_string(),
},
comp.range(),
));
);
}
}
@ -100,12 +100,12 @@ pub(crate) fn assign_hardcoded_password_string(checker: &Checker, value: &Expr,
{
for target in targets {
if let Some(name) = password_target(target) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
HardcodedPasswordString {
name: name.to_string(),
},
value.range(),
));
);
return;
}
}

View file

@ -2,7 +2,7 @@ use std::sync::LazyLock;
use regex::Regex;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::str::raw_contents;
use ruff_python_ast::{self as ast, Expr, Operator};
@ -113,7 +113,7 @@ pub(crate) fn hardcoded_sql_expression(checker: &Checker, expr: &Expr) {
};
if SQL_REGEX.is_match(&content) {
checker.report_diagnostic(Diagnostic::new(HardcodedSQLExpression, expr.range()));
checker.report_diagnostic(HardcodedSQLExpression, expr.range());
}
}

View file

@ -1,7 +1,7 @@
use ruff_python_ast::{self as ast, Expr, StringLike};
use ruff_text_size::{Ranged, TextRange};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use crate::checkers::ast::Checker;
@ -102,10 +102,10 @@ fn check(checker: &Checker, value: &str, range: TextRange) {
}
}
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
HardcodedTempFile {
string: value.to_string(),
},
range,
));
);
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_const_false;
use ruff_python_ast::{self as ast, Arguments};
@ -141,23 +141,23 @@ fn detect_insecure_hashlib_calls(
hash_func_name.to_ascii_lowercase().as_str(),
"md4" | "md5" | "sha" | "sha1"
) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
HashlibInsecureHashFunction {
library: "hashlib".to_string(),
string: hash_func_name.to_string(),
},
name_arg.range(),
));
);
}
}
HashlibCall::WeakHash(func_name) => {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
HashlibInsecureHashFunction {
library: "hashlib".to_string(),
string: (*func_name).to_string(),
},
call.func.range(),
));
);
}
}
}
@ -186,13 +186,13 @@ fn detect_insecure_crypt_calls(checker: &Checker, call: &ast::ExprCall) {
qualified_name.segments(),
["crypt", "METHOD_CRYPT" | "METHOD_MD5" | "METHOD_BLOWFISH"]
) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
HashlibInsecureHashFunction {
library: "crypt".to_string(),
string: qualified_name.to_string(),
},
method.range(),
));
);
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;
@ -70,23 +70,20 @@ pub(crate) fn jinja2_autoescape_false(checker: &Checker, call: &ast::ExprCall) {
Expr::Call(ast::ExprCall { func, .. }) => {
if let Expr::Name(ast::ExprName { id, .. }) = func.as_ref() {
if id != "select_autoescape" {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
Jinja2AutoescapeFalse { value: true },
keyword.range(),
));
);
}
}
}
_ => checker.report_diagnostic(Diagnostic::new(
Jinja2AutoescapeFalse { value: true },
keyword.range(),
)),
_ => {
checker
.report_diagnostic(Jinja2AutoescapeFalse { value: true }, keyword.range());
}
}
} else {
checker.report_diagnostic(Diagnostic::new(
Jinja2AutoescapeFalse { value: false },
call.func.range(),
));
checker.report_diagnostic(Jinja2AutoescapeFalse { value: false }, call.func.range());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast};
use ruff_python_semantic::Modules;
@ -51,9 +51,6 @@ pub(crate) fn logging_config_insecure_listen(checker: &Checker, call: &ast::Expr
return;
}
checker.report_diagnostic(Diagnostic::new(
LoggingConfigInsecureListen,
call.func.range(),
));
checker.report_diagnostic(LoggingConfigInsecureListen, call.func.range());
}
}

View file

@ -1,5 +1,5 @@
use crate::checkers::ast::Checker;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast};
use ruff_text_size::Ranged;
@ -50,6 +50,6 @@ pub(crate) fn mako_templates(checker: &Checker, call: &ast::ExprCall) {
matches!(qualified_name.segments(), ["mako", "template", "Template"])
})
{
checker.report_diagnostic(Diagnostic::new(MakoTemplates, call.func.range()));
checker.report_diagnostic(MakoTemplates, call.func.range());
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::Expr;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -45,6 +45,6 @@ pub(crate) fn paramiko_call(checker: &Checker, func: &Expr) {
matches!(qualified_name.segments(), ["paramiko", "exec_command"])
})
{
checker.report_diagnostic(Diagnostic::new(ParamikoCall, func.range()));
checker.report_diagnostic(ParamikoCall, func.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_python_ast::helpers::is_const_false;
@ -65,12 +65,12 @@ pub(crate) fn request_with_no_cert_validation(checker: &Checker, call: &ast::Exp
{
if let Some(keyword) = call.arguments.find_keyword("verify") {
if is_const_false(&keyword.value) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
RequestWithNoCertValidation {
string: target.to_string(),
},
keyword.range(),
));
);
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
@ -70,22 +70,22 @@ pub(crate) fn request_without_timeout(checker: &Checker, call: &ast::ExprCall) {
{
if let Some(keyword) = call.arguments.find_keyword("timeout") {
if keyword.value.is_none_literal_expr() {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
RequestWithoutTimeout {
implicit: false,
module: module.to_string(),
},
keyword.range(),
));
);
}
} else if module == "requests" {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
RequestWithoutTimeout {
implicit: true,
module: module.to_string(),
},
call.func.range(),
));
);
}
}
}

View file

@ -1,7 +1,7 @@
//! Checks relating to shell injection.
use crate::preview::is_shell_injection_only_trusted_input_enabled;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::Truthiness;
use ruff_python_ast::{self as ast, Arguments, Expr};
@ -314,13 +314,13 @@ pub(crate) fn shell_injection(checker: &Checker, call: &ast::ExprCall) {
truthiness: truthiness @ (Truthiness::True | Truthiness::Truthy),
}) => {
if checker.enabled(Rule::SubprocessPopenWithShellEqualsTrue) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
SubprocessPopenWithShellEqualsTrue {
safety: Safety::from(arg),
is_exact: matches!(truthiness, Truthiness::True),
},
call.func.range(),
));
);
}
}
// S603
@ -329,10 +329,10 @@ pub(crate) fn shell_injection(checker: &Checker, call: &ast::ExprCall) {
|| !is_shell_injection_only_trusted_input_enabled(checker.settings)
{
if checker.enabled(Rule::SubprocessWithoutShellEqualsTrue) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
SubprocessWithoutShellEqualsTrue,
call.func.range(),
));
);
}
}
}
@ -344,12 +344,12 @@ pub(crate) fn shell_injection(checker: &Checker, call: &ast::ExprCall) {
{
// S604
if checker.enabled(Rule::CallWithShellEqualsTrue) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
CallWithShellEqualsTrue {
is_exact: matches!(truthiness, Truthiness::True),
},
call.func.range(),
));
);
}
}
@ -357,12 +357,12 @@ pub(crate) fn shell_injection(checker: &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.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
StartProcessWithAShell {
safety: Safety::from(arg),
},
call.func.range(),
));
);
}
}
}
@ -370,7 +370,7 @@ pub(crate) fn shell_injection(checker: &Checker, call: &ast::ExprCall) {
// S606
if checker.enabled(Rule::StartProcessWithNoShell) {
if matches!(call_kind, Some(CallKind::NoShell)) {
checker.report_diagnostic(Diagnostic::new(StartProcessWithNoShell, call.func.range()));
checker.report_diagnostic(StartProcessWithNoShell, call.func.range());
}
}
@ -379,10 +379,7 @@ pub(crate) fn shell_injection(checker: &Checker, call: &ast::ExprCall) {
if call_kind.is_some() {
if let Some(arg) = call.arguments.args.first() {
if is_partial_path(arg) {
checker.report_diagnostic(Diagnostic::new(
StartProcessWithPartialPath,
arg.range(),
));
checker.report_diagnostic(StartProcessWithPartialPath, arg.range());
}
}
}
@ -403,10 +400,7 @@ pub(crate) fn shell_injection(checker: &Checker, call: &ast::ExprCall) {
{
if let Some(arg) = call.arguments.args.first() {
if is_wildcard_command(arg) {
checker.report_diagnostic(Diagnostic::new(
UnixCommandWildcardInjection,
arg.range(),
));
checker.report_diagnostic(UnixCommandWildcardInjection, arg.range());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr, Int};
use ruff_text_size::Ranged;
@ -60,7 +60,7 @@ pub(crate) fn snmp_insecure_version(checker: &Checker, call: &ast::ExprCall) {
..
})
) {
checker.report_diagnostic(Diagnostic::new(SnmpInsecureVersion, keyword.range()));
checker.report_diagnostic(SnmpInsecureVersion, keyword.range());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast};
use ruff_text_size::Ranged;
@ -52,7 +52,7 @@ pub(crate) fn snmp_weak_cryptography(checker: &Checker, call: &ast::ExprCall) {
)
})
{
checker.report_diagnostic(Diagnostic::new(SnmpWeakCryptography, call.func.range()));
checker.report_diagnostic(SnmpWeakCryptography, call.func.range());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::map_callable;
use ruff_python_ast::{Expr, ExprAttribute, ExprCall};
@ -78,9 +78,6 @@ pub(crate) fn ssh_no_host_key_verification(checker: &Checker, call: &ExprCall) {
["paramiko", "client", "SSHClient"] | ["paramiko", "SSHClient"]
)
}) {
checker.report_diagnostic(Diagnostic::new(
SSHNoHostKeyVerification,
policy_argument.range(),
));
checker.report_diagnostic(SSHNoHostKeyVerification, policy_argument.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr, ExprCall};
use ruff_text_size::Ranged;
@ -68,22 +68,22 @@ pub(crate) fn ssl_insecure_version(checker: &Checker, call: &ExprCall) {
match &keyword.value {
Expr::Name(ast::ExprName { id, .. }) => {
if is_insecure_protocol(id) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
SslInsecureVersion {
protocol: id.to_string(),
},
keyword.range(),
));
);
}
}
Expr::Attribute(ast::ExprAttribute { attr, .. }) => {
if is_insecure_protocol(attr) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
SslInsecureVersion {
protocol: attr.to_string(),
},
keyword.range(),
));
);
}
}
_ => {}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr, StmtFunctionDef};
@ -57,22 +57,22 @@ pub(crate) fn ssl_with_bad_defaults(checker: &Checker, function_def: &StmtFuncti
match default {
Expr::Name(ast::ExprName { id, range, .. }) => {
if is_insecure_protocol(id.as_str()) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
SslWithBadDefaults {
protocol: id.to_string(),
},
*range,
));
);
}
}
Expr::Attribute(ast::ExprAttribute { attr, range, .. }) => {
if is_insecure_protocol(attr.as_str()) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
SslWithBadDefaults {
protocol: attr.to_string(),
},
*range,
));
);
}
}
_ => {}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::ExprCall;
use ruff_text_size::Ranged;
@ -43,7 +43,7 @@ pub(crate) fn ssl_with_no_version(checker: &Checker, call: &ExprCall) {
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["ssl", "wrap_socket"]))
{
if call.arguments.find_keyword("ssl_version").is_none() {
checker.report_diagnostic(Diagnostic::new(SslWithNoVersion, call.range()));
checker.report_diagnostic(SslWithNoVersion, call.range());
}
}
}

View file

@ -2,14 +2,13 @@
//!
//! See: <https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html>
use itertools::Either;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Arguments, Decorator, Expr, ExprCall, Operator};
use ruff_text_size::{Ranged, TextRange};
use crate::checkers::ast::Checker;
use crate::preview::is_suspicious_function_reference_enabled;
use crate::registry::AsRule;
/// ## What it does
/// Checks for calls to `pickle` functions or modules that wrap them.
@ -1035,16 +1034,20 @@ fn suspicious_function(
return;
};
let diagnostic = match qualified_name.segments() {
match qualified_name.segments() {
// Pickle
["pickle" | "dill", "load" | "loads" | "Unpickler"]
| ["shelve", "open" | "DbfilenameShelf"]
| ["jsonpickle", "decode"]
| ["jsonpickle", "unpickler", "decode"]
| ["pandas", "read_pickle"] => Diagnostic::new(SuspiciousPickleUsage, range),
| ["pandas", "read_pickle"] => {
checker.report_diagnostic_if_enabled(SuspiciousPickleUsage, range)
}
// Marshal
["marshal", "load" | "loads"] => Diagnostic::new(SuspiciousMarshalUsage, range),
["marshal", "load" | "loads"] => {
checker.report_diagnostic_if_enabled(SuspiciousMarshalUsage, range)
}
// InsecureHash
[
@ -1059,7 +1062,7 @@ fn suspicious_function(
"primitives",
"hashes",
"SHA1" | "MD5",
] => Diagnostic::new(SuspiciousInsecureHashUsage, range),
] => checker.report_diagnostic_if_enabled(SuspiciousInsecureHashUsage, range),
// InsecureCipher
[
@ -1075,7 +1078,7 @@ fn suspicious_function(
"ciphers",
"algorithms",
"ARC4" | "Blowfish" | "IDEA",
] => Diagnostic::new(SuspiciousInsecureCipherUsage, range),
] => checker.report_diagnostic_if_enabled(SuspiciousInsecureCipherUsage, range),
// InsecureCipherMode
[
@ -1085,13 +1088,17 @@ fn suspicious_function(
"ciphers",
"modes",
"ECB",
] => Diagnostic::new(SuspiciousInsecureCipherModeUsage, range),
] => checker.report_diagnostic_if_enabled(SuspiciousInsecureCipherModeUsage, range),
// Mktemp
["tempfile", "mktemp"] => Diagnostic::new(SuspiciousMktempUsage, range),
["tempfile", "mktemp"] => {
checker.report_diagnostic_if_enabled(SuspiciousMktempUsage, range)
}
// Eval
["" | "builtins", "eval"] => Diagnostic::new(SuspiciousEvalUsage, range),
["" | "builtins", "eval"] => {
checker.report_diagnostic_if_enabled(SuspiciousEvalUsage, range)
}
// MarkSafe
["django", "utils", "safestring" | "html", "mark_safe"] => {
@ -1102,7 +1109,7 @@ fn suspicious_function(
}
}
}
Diagnostic::new(SuspiciousMarkSafeUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousMarkSafeUsage, range)
}
// URLOpen (`Request`)
@ -1124,7 +1131,7 @@ fn suspicious_function(
}
}
}
Diagnostic::new(SuspiciousURLOpenUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousURLOpenUsage, range)
}
// URLOpen (`urlopen`, `urlretrieve`)
@ -1176,7 +1183,7 @@ fn suspicious_function(
}
}
}
Diagnostic::new(SuspiciousURLOpenUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousURLOpenUsage, range)
}
// URLOpen (`URLopener`, `FancyURLopener`)
@ -1187,18 +1194,18 @@ fn suspicious_function(
"urllib",
"request",
"URLopener" | "FancyURLopener",
] => Diagnostic::new(SuspiciousURLOpenUsage, range),
] => checker.report_diagnostic_if_enabled(SuspiciousURLOpenUsage, range),
// NonCryptographicRandom
[
"random",
"Random" | "random" | "randrange" | "randint" | "choice" | "choices" | "uniform"
| "triangular" | "randbytes",
] => Diagnostic::new(SuspiciousNonCryptographicRandomUsage, range),
] => checker.report_diagnostic_if_enabled(SuspiciousNonCryptographicRandomUsage, range),
// UnverifiedContext
["ssl", "_create_unverified_context"] => {
Diagnostic::new(SuspiciousUnverifiedContextUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousUnverifiedContextUsage, range)
}
// XMLCElementTree
@ -1207,7 +1214,7 @@ fn suspicious_function(
"etree",
"cElementTree",
"parse" | "iterparse" | "fromstring" | "XMLParser",
] => Diagnostic::new(SuspiciousXMLCElementTreeUsage, range),
] => checker.report_diagnostic_if_enabled(SuspiciousXMLCElementTreeUsage, range),
// XMLElementTree
[
@ -1215,31 +1222,31 @@ fn suspicious_function(
"etree",
"ElementTree",
"parse" | "iterparse" | "fromstring" | "XMLParser",
] => Diagnostic::new(SuspiciousXMLElementTreeUsage, range),
] => checker.report_diagnostic_if_enabled(SuspiciousXMLElementTreeUsage, range),
// XMLExpatReader
["xml", "sax", "expatreader", "create_parser"] => {
Diagnostic::new(SuspiciousXMLExpatReaderUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousXMLExpatReaderUsage, range)
}
// XMLExpatBuilder
["xml", "dom", "expatbuilder", "parse" | "parseString"] => {
Diagnostic::new(SuspiciousXMLExpatBuilderUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousXMLExpatBuilderUsage, range)
}
// XMLSax
["xml", "sax", "parse" | "parseString" | "make_parser"] => {
Diagnostic::new(SuspiciousXMLSaxUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousXMLSaxUsage, range)
}
// XMLMiniDOM
["xml", "dom", "minidom", "parse" | "parseString"] => {
Diagnostic::new(SuspiciousXMLMiniDOMUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousXMLMiniDOMUsage, range)
}
// XMLPullDOM
["xml", "dom", "pulldom", "parse" | "parseString"] => {
Diagnostic::new(SuspiciousXMLPullDOMUsage, range)
checker.report_diagnostic_if_enabled(SuspiciousXMLPullDOMUsage, range)
}
// XMLETree
@ -1248,20 +1255,16 @@ fn suspicious_function(
"etree",
"parse" | "fromstring" | "RestrictedElement" | "GlobalParserTLS" | "getDefaultParser"
| "check_docinfo",
] => Diagnostic::new(SuspiciousXMLETreeUsage, range),
] => checker.report_diagnostic_if_enabled(SuspiciousXMLETreeUsage, range),
// Telnet
["telnetlib", ..] => Diagnostic::new(SuspiciousTelnetUsage, range),
["telnetlib", ..] => checker.report_diagnostic_if_enabled(SuspiciousTelnetUsage, range),
// FTPLib
["ftplib", ..] => Diagnostic::new(SuspiciousFTPLibUsage, range),
["ftplib", ..] => checker.report_diagnostic_if_enabled(SuspiciousFTPLibUsage, range),
_ => return,
};
if checker.enabled(diagnostic.rule()) {
checker.report_diagnostic(diagnostic);
}
}
/// S308

View file

@ -1,13 +1,12 @@
//! Check for imports of or from suspicious modules.
//!
//! See: <https://bandit.readthedocs.io/en/latest/blacklists/blacklist_imports.html>
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Stmt};
use ruff_text_size::{Ranged, TextRange};
use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
/// ## What it does
/// Checks for imports of the `telnetlib` module.
@ -362,42 +361,47 @@ pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
for name in names {
match name.name.as_str() {
"telnetlib" => {
check_and_push_diagnostic(checker, SuspiciousTelnetlibImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousTelnetlibImport, name.range);
}
"ftplib" => {
check_and_push_diagnostic(checker, SuspiciousFtplibImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousFtplibImport, name.range);
}
"pickle" | "cPickle" | "dill" | "shelve" => {
check_and_push_diagnostic(checker, SuspiciousPickleImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousPickleImport, name.range);
}
"subprocess" => {
check_and_push_diagnostic(checker, SuspiciousSubprocessImport, name.range);
checker
.report_diagnostic_if_enabled(SuspiciousSubprocessImport, name.range);
}
"xml.etree.cElementTree" | "xml.etree.ElementTree" => {
check_and_push_diagnostic(checker, SuspiciousXmlEtreeImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousXmlEtreeImport, name.range);
}
"xml.sax" => {
check_and_push_diagnostic(checker, SuspiciousXmlSaxImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousXmlSaxImport, name.range);
}
"xml.dom.expatbuilder" => {
check_and_push_diagnostic(checker, SuspiciousXmlExpatImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousXmlExpatImport, name.range);
}
"xml.dom.minidom" => {
check_and_push_diagnostic(checker, SuspiciousXmlMinidomImport, name.range);
checker
.report_diagnostic_if_enabled(SuspiciousXmlMinidomImport, name.range);
}
"xml.dom.pulldom" => {
check_and_push_diagnostic(checker, SuspiciousXmlPulldomImport, name.range);
checker
.report_diagnostic_if_enabled(SuspiciousXmlPulldomImport, name.range);
}
"lxml" => {
checker.report_diagnostic_if_enabled(SuspiciousLxmlImport, name.range);
}
"lxml" => check_and_push_diagnostic(checker, SuspiciousLxmlImport, name.range),
"xmlrpc" => {
check_and_push_diagnostic(checker, SuspiciousXmlrpcImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousXmlrpcImport, name.range);
}
"Crypto.Cipher" | "Crypto.Hash" | "Crypto.IO" | "Crypto.Protocol"
| "Crypto.PublicKey" | "Crypto.Random" | "Crypto.Signature" | "Crypto.Util" => {
check_and_push_diagnostic(checker, SuspiciousPycryptoImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousPycryptoImport, name.range);
}
"pyghmi" => {
check_and_push_diagnostic(checker, SuspiciousPyghmiImport, name.range);
checker.report_diagnostic_if_enabled(SuspiciousPyghmiImport, name.range);
}
_ => {}
}
@ -406,27 +410,30 @@ pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
Stmt::ImportFrom(ast::StmtImportFrom { module, names, .. }) => {
let Some(identifier) = module else { return };
match identifier.as_str() {
"telnetlib" => check_and_push_diagnostic(
checker,
SuspiciousTelnetlibImport,
identifier.range(),
),
"telnetlib" => {
checker.report_diagnostic_if_enabled(
SuspiciousTelnetlibImport,
identifier.range(),
);
}
"ftplib" => {
check_and_push_diagnostic(checker, SuspiciousFtplibImport, identifier.range());
checker
.report_diagnostic_if_enabled(SuspiciousFtplibImport, identifier.range());
}
"pickle" | "cPickle" | "dill" | "shelve" => {
check_and_push_diagnostic(checker, SuspiciousPickleImport, identifier.range());
checker
.report_diagnostic_if_enabled(SuspiciousPickleImport, identifier.range());
}
"subprocess" => {
checker.report_diagnostic_if_enabled(
SuspiciousSubprocessImport,
identifier.range(),
);
}
"subprocess" => check_and_push_diagnostic(
checker,
SuspiciousSubprocessImport,
identifier.range(),
),
"xml.etree" => {
for name in names {
if matches!(name.name.as_str(), "cElementTree" | "ElementTree") {
check_and_push_diagnostic(
checker,
checker.report_diagnostic_if_enabled(
SuspiciousXmlEtreeImport,
identifier.range(),
);
@ -434,17 +441,13 @@ pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
}
}
"xml.etree.cElementTree" | "xml.etree.ElementTree" => {
check_and_push_diagnostic(
checker,
SuspiciousXmlEtreeImport,
identifier.range(),
);
checker
.report_diagnostic_if_enabled(SuspiciousXmlEtreeImport, identifier.range());
}
"xml" => {
for name in names {
if name.name.as_str() == "sax" {
check_and_push_diagnostic(
checker,
checker.report_diagnostic_if_enabled(
SuspiciousXmlSaxImport,
identifier.range(),
);
@ -452,58 +455,61 @@ pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
}
}
"xml.sax" => {
check_and_push_diagnostic(checker, SuspiciousXmlSaxImport, identifier.range());
checker
.report_diagnostic_if_enabled(SuspiciousXmlSaxImport, identifier.range());
}
"xml.dom" => {
for name in names {
match name.name.as_str() {
"expatbuilder" => check_and_push_diagnostic(
checker,
SuspiciousXmlExpatImport,
identifier.range(),
),
"minidom" => check_and_push_diagnostic(
checker,
SuspiciousXmlMinidomImport,
identifier.range(),
),
"pulldom" => check_and_push_diagnostic(
checker,
SuspiciousXmlPulldomImport,
identifier.range(),
),
_ => (),
"expatbuilder" => {
checker.report_diagnostic_if_enabled(
SuspiciousXmlExpatImport,
identifier.range(),
);
}
"minidom" => {
checker.report_diagnostic_if_enabled(
SuspiciousXmlMinidomImport,
identifier.range(),
);
}
"pulldom" => {
checker.report_diagnostic_if_enabled(
SuspiciousXmlPulldomImport,
identifier.range(),
);
}
_ => {}
}
}
}
"xml.dom.expatbuilder" => {
check_and_push_diagnostic(
checker,
SuspiciousXmlExpatImport,
checker
.report_diagnostic_if_enabled(SuspiciousXmlExpatImport, identifier.range());
}
"xml.dom.minidom" => {
checker.report_diagnostic_if_enabled(
SuspiciousXmlMinidomImport,
identifier.range(),
);
}
"xml.dom.pulldom" => {
checker.report_diagnostic_if_enabled(
SuspiciousXmlPulldomImport,
identifier.range(),
);
}
"xml.dom.minidom" => check_and_push_diagnostic(
checker,
SuspiciousXmlMinidomImport,
identifier.range(),
),
"xml.dom.pulldom" => check_and_push_diagnostic(
checker,
SuspiciousXmlPulldomImport,
identifier.range(),
),
"lxml" => {
check_and_push_diagnostic(checker, SuspiciousLxmlImport, identifier.range());
checker.report_diagnostic_if_enabled(SuspiciousLxmlImport, identifier.range());
}
"xmlrpc" => {
check_and_push_diagnostic(checker, SuspiciousXmlrpcImport, identifier.range());
checker
.report_diagnostic_if_enabled(SuspiciousXmlrpcImport, identifier.range());
}
"wsgiref.handlers" => {
for name in names {
if name.name.as_str() == "CGIHandler" {
check_and_push_diagnostic(
checker,
checker.report_diagnostic_if_enabled(
SuspiciousHttpoxyImport,
identifier.range(),
);
@ -513,8 +519,7 @@ pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
"twisted.web.twcgi" => {
for name in names {
if name.name.as_str() == "CGIScript" {
check_and_push_diagnostic(
checker,
checker.report_diagnostic_if_enabled(
SuspiciousHttpoxyImport,
identifier.range(),
);
@ -534,8 +539,7 @@ pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
| "Signature"
| "Util"
) {
check_and_push_diagnostic(
checker,
checker.report_diagnostic_if_enabled(
SuspiciousPycryptoImport,
identifier.range(),
);
@ -544,14 +548,12 @@ pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
}
"Crypto.Cipher" | "Crypto.Hash" | "Crypto.IO" | "Crypto.Protocol"
| "Crypto.PublicKey" | "Crypto.Random" | "Crypto.Signature" | "Crypto.Util" => {
check_and_push_diagnostic(
checker,
SuspiciousPycryptoImport,
identifier.range(),
);
checker
.report_diagnostic_if_enabled(SuspiciousPycryptoImport, identifier.range());
}
"pyghmi" => {
check_and_push_diagnostic(checker, SuspiciousPyghmiImport, identifier.range());
checker
.report_diagnostic_if_enabled(SuspiciousPyghmiImport, identifier.range());
}
_ => {}
}
@ -559,10 +561,3 @@ pub(crate) fn suspicious_imports(checker: &Checker, stmt: &Stmt) {
_ => panic!("Expected Stmt::Import | Stmt::ImportFrom"),
}
}
fn check_and_push_diagnostic<T: Violation>(checker: &Checker, diagnostic: T, range: TextRange) {
let diagnostic = Diagnostic::new(diagnostic, range);
if checker.enabled(diagnostic.rule()) {
checker.report_diagnostic(diagnostic);
}
}

View file

@ -1,5 +1,4 @@
use crate::checkers::ast::Checker;
use ruff_diagnostics::Diagnostic;
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast};
@ -70,5 +69,5 @@ pub(crate) fn tarfile_unsafe_members(checker: &Checker, call: &ast::ExprCall) {
return;
}
checker.report_diagnostic(Diagnostic::new(TarfileUnsafeMembers, call.func.range()));
checker.report_diagnostic(TarfileUnsafeMembers, call.func.range());
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{ExceptHandler, Expr, Stmt};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -64,7 +64,7 @@ pub(crate) fn try_except_continue(
) {
if matches!(body, [Stmt::Continue(_)]) {
if check_typed_exception || is_untyped_exception(type_, checker.semantic()) {
checker.report_diagnostic(Diagnostic::new(TryExceptContinue, except_handler.range()));
checker.report_diagnostic(TryExceptContinue, except_handler.range());
}
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{ExceptHandler, Expr, Stmt};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -60,7 +60,7 @@ pub(crate) fn try_except_pass(
) {
if matches!(body, [Stmt::Pass(_)]) {
if check_typed_exception || is_untyped_exception(type_, checker.semantic()) {
checker.report_diagnostic(Diagnostic::new(TryExceptPass, except_handler.range()));
checker.report_diagnostic(TryExceptPass, except_handler.range());
}
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{Expr, ExprCall};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::QualifiedName;
use ruff_python_semantic::{Modules, SemanticModel};
@ -112,12 +112,12 @@ pub(crate) fn unsafe_markup_call(checker: &Checker, call: &ExprCall) {
return;
}
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
UnsafeMarkupUse {
name: qualified_name.to_string(),
},
call.range(),
));
);
}
fn is_markup_call(qualified_name: &QualifiedName, settings: &LinterSettings) -> bool {

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;
@ -82,16 +82,10 @@ pub(crate) fn unsafe_yaml_load(checker: &Checker, call: &ast::ExprCall) {
Expr::Name(ast::ExprName { id, .. }) => Some(id.to_string()),
_ => None,
};
checker.report_diagnostic(Diagnostic::new(
UnsafeYAMLLoad { loader },
loader_arg.range(),
));
checker.report_diagnostic(UnsafeYAMLLoad { loader }, loader_arg.range());
}
} else {
checker.report_diagnostic(Diagnostic::new(
UnsafeYAMLLoad { loader: None },
call.func.range(),
));
checker.report_diagnostic(UnsafeYAMLLoad { loader: None }, call.func.range());
}
}
}

View file

@ -1,6 +1,6 @@
use std::fmt::{Display, Formatter};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr, ExprAttribute, ExprCall};
use ruff_text_size::{Ranged, TextRange};
@ -55,10 +55,7 @@ pub(crate) fn weak_cryptographic_key(checker: &Checker, call: &ExprCall) {
};
if cryptographic_key.is_vulnerable() {
checker.report_diagnostic(Diagnostic::new(
WeakCryptographicKey { cryptographic_key },
range,
));
checker.report_diagnostic(WeakCryptographicKey { cryptographic_key }, range);
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_const_true;
use ruff_python_ast::statement_visitor::{StatementVisitor, walk_stmt};
@ -107,12 +107,12 @@ pub(crate) fn blind_except(
return;
}
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
BlindExcept {
name: builtin_exception_type.to_string(),
},
type_.range(),
));
);
}
/// A visitor to detect whether the exception with the given name was re-raised.

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::identifier::Identifier;
use ruff_python_ast::name::UnqualifiedName;
@ -131,10 +131,7 @@ pub(crate) fn boolean_default_value_positional_argument(
return;
}
checker.report_diagnostic(Diagnostic::new(
BooleanDefaultValuePositionalArgument,
param.identifier(),
));
checker.report_diagnostic(BooleanDefaultValuePositionalArgument, param.identifier());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_text_size::Ranged;
@ -61,6 +61,6 @@ pub(crate) fn boolean_positional_value_in_call(checker: &Checker, call: &ast::Ex
.iter()
.filter(|arg| arg.is_boolean_literal_expr())
{
checker.report_diagnostic(Diagnostic::new(BooleanPositionalValueInCall, arg.range()));
checker.report_diagnostic(BooleanPositionalValueInCall, arg.range());
}
}

View file

@ -1,4 +1,3 @@
use ruff_diagnostics::Diagnostic;
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::identifier::Identifier;
@ -158,10 +157,7 @@ pub(crate) fn boolean_type_hint_positional_argument(
return;
}
checker.report_diagnostic(Diagnostic::new(
BooleanTypeHintPositionalArgument,
parameter.identifier(),
));
checker.report_diagnostic(BooleanTypeHintPositionalArgument, parameter.identifier());
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{self as ast, Arguments, Expr, Keyword, Stmt};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::identifier::Identifier;
use ruff_python_semantic::SemanticModel;
@ -196,22 +196,22 @@ pub(crate) fn abstract_base_class(
&& is_empty_body(body)
&& !is_overload(decorator_list, checker.semantic())
{
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
EmptyMethodWithoutAbstractDecorator {
name: format!("{name}.{method_name}"),
},
stmt.range(),
));
);
}
}
if checker.enabled(Rule::AbstractBaseClassWithoutAbstractMethod) {
if !has_abstract_method {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
AbstractBaseClassWithoutAbstractMethod {
name: name.to_string(),
},
stmt.identifier(),
));
);
}
}
}

View file

@ -1,7 +1,7 @@
use ruff_python_ast::{self as ast, Arguments, Expr, ExprContext, Stmt};
use ruff_text_size::{Ranged, TextRange};
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_diagnostics::{AlwaysFixableViolation, Edit, Fix};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_const_false;
@ -79,10 +79,9 @@ pub(crate) fn assert_false(checker: &Checker, stmt: &Stmt, test: &Expr, msg: Opt
return;
}
let mut diagnostic = Diagnostic::new(AssertFalse, test.range());
let mut diagnostic = checker.report_diagnostic(AssertFalse, test.range());
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
checker.generator().stmt(&assertion_error(msg)),
stmt.range(),
)));
checker.report_diagnostic(diagnostic);
}

View file

@ -1,6 +1,6 @@
use std::fmt;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr, WithItem};
use ruff_text_size::Ranged;
@ -99,9 +99,6 @@ pub(crate) fn assert_raises_exception(checker: &Checker, items: &[WithItem]) {
continue;
}
checker.report_diagnostic(Diagnostic::new(
AssertRaisesException { exception },
item.range(),
));
checker.report_diagnostic(AssertRaisesException { exception }, item.range());
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{self as ast, Expr};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -66,5 +66,5 @@ pub(crate) fn assignment_to_os_environ(checker: &Checker, targets: &[Expr]) {
if id != "os" {
return;
}
checker.report_diagnostic(Diagnostic::new(AssignmentToOsEnviron, target.range()));
checker.report_diagnostic(AssignmentToOsEnviron, target.range());
}

View file

@ -1,6 +1,6 @@
use crate::checkers::ast::Checker;
use crate::rules::flake8_bugbear::rules::is_infinite_iterable;
use ruff_diagnostics::{Diagnostic, FixAvailability, Violation};
use ruff_diagnostics::{FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::ExprCall;
use ruff_python_ast::PythonVersion;
@ -86,6 +86,5 @@ pub(crate) fn batched_without_explicit_strict(checker: &Checker, call: &ExprCall
return;
}
let diagnostic = Diagnostic::new(BatchedWithoutExplicitStrict, call.range);
checker.report_diagnostic(diagnostic);
checker.report_diagnostic(BatchedWithoutExplicitStrict, call.range);
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::map_callable;
use ruff_python_ast::{self as ast, Expr};
@ -102,7 +102,7 @@ pub(crate) fn cached_instance_method(checker: &Checker, function_def: &ast::Stmt
return;
}
checker.report_diagnostic(Diagnostic::new(CachedInstanceMethod, decorator.range()));
checker.report_diagnostic(CachedInstanceMethod, decorator.range());
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast};
use ruff_python_semantic::analyze::visibility::{self, Visibility::Public};
@ -105,7 +105,7 @@ pub(crate) fn class_as_data_structure(checker: &Checker, class_def: &ast::StmtCl
}
if has_dunder_init && public_methods == 1 {
checker.report_diagnostic(Diagnostic::new(ClassAsDataStructure, class_def.range()));
checker.report_diagnostic(ClassAsDataStructure, class_def.range());
}
}

View file

@ -2,7 +2,7 @@ use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
use ruff_diagnostics::{AlwaysFixableViolation, Violation};
use ruff_diagnostics::{Diagnostic, Edit, Fix};
use ruff_diagnostics::{Edit, Fix};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::UnqualifiedName;
use ruff_python_ast::{self as ast, ExceptHandler, Expr, ExprContext};
@ -141,7 +141,7 @@ fn duplicate_handler_exceptions<'a>(
if checker.enabled(Rule::DuplicateHandlerException) {
// TODO(charlie): Handle "BaseException" and redundant exception aliases.
if !duplicates.is_empty() {
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
DuplicateHandlerException {
names: duplicates
.into_iter()
@ -167,7 +167,6 @@ fn duplicate_handler_exceptions<'a>(
},
expr.range(),
)));
checker.report_diagnostic(diagnostic);
}
}
@ -217,13 +216,13 @@ pub(crate) fn duplicate_exceptions(checker: &Checker, handlers: &[ExceptHandler]
.current_statement()
.as_try_stmt()
.is_some_and(|try_stmt| try_stmt.is_star);
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
DuplicateTryBlockException {
name: name.segments().join("."),
is_star,
},
expr.range(),
));
);
}
}
}

View file

@ -1,7 +1,7 @@
use anyhow::{Context, Result};
use rustc_hash::FxHashMap;
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_python_ast::Expr;
@ -60,7 +60,7 @@ pub(crate) fn duplicate_value(checker: &Checker, set: &ast::ExprSet) {
for (index, value) in set.iter().enumerate() {
if value.is_literal_expr() {
if let Some(existing) = seen_values.insert(HashableExpr::from(value), value) {
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
DuplicateValue {
value: checker.generator().expr(value),
existing: checker.generator().expr(existing),
@ -71,8 +71,6 @@ pub(crate) fn duplicate_value(checker: &Checker, set: &ast::ExprSet) {
diagnostic.try_set_fix(|| {
remove_member(set, index, checker.locator().contents()).map(Fix::safe_edit)
});
checker.report_diagnostic(diagnostic);
}
}
}

View file

@ -1,7 +1,7 @@
use ruff_python_ast::{self as ast};
use ruff_python_ast::{ExceptHandler, Expr};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -66,9 +66,6 @@ pub(crate) fn except_with_empty_tuple(checker: &Checker, except_handler: &Except
.current_statement()
.as_try_stmt()
.is_some_and(|try_stmt| try_stmt.is_star);
checker.report_diagnostic(Diagnostic::new(
ExceptWithEmptyTuple { is_star },
except_handler.range(),
));
checker.report_diagnostic(ExceptWithEmptyTuple { is_star }, except_handler.range());
}
}

View file

@ -2,7 +2,7 @@ use std::collections::VecDeque;
use ruff_python_ast::{self as ast, ExceptHandler, Expr, Operator};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -69,10 +69,7 @@ pub(crate) fn except_with_non_exception_classes(checker: &Checker, except_handle
.current_statement()
.as_try_stmt()
.is_some_and(|try_stmt| try_stmt.is_star);
checker.report_diagnostic(Diagnostic::new(
ExceptWithNonExceptionClasses { is_star },
expr.range(),
));
checker.report_diagnostic(ExceptWithNonExceptionClasses { is_star }, expr.range());
}
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{self as ast, Stmt};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::identifier::Identifier;
@ -51,5 +51,5 @@ pub(crate) fn f_string_docstring(checker: &Checker, body: &[Stmt]) {
if !value.is_f_string_expr() {
return;
}
checker.report_diagnostic(Diagnostic::new(FStringDocstring, stmt.identifier()));
checker.report_diagnostic(FStringDocstring, stmt.identifier());
}

View file

@ -1,7 +1,6 @@
use ruff_python_ast::{self as ast, Expr, Parameters};
use ruff_text_size::Ranged;
use ruff_diagnostics::Diagnostic;
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::name::{QualifiedName, UnqualifiedName};
@ -113,12 +112,12 @@ impl Visitor<'_> for ArgumentDefaultVisitor<'_, '_> {
)
})
{
self.checker.report_diagnostic(Diagnostic::new(
self.checker.report_diagnostic(
FunctionCallInDefaultArgument {
name: UnqualifiedName::from_expr(func).map(|name| name.to_string()),
},
expr.range(),
));
);
}
visitor::walk_expr(self, expr);
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::types::Node;
use ruff_python_ast::visitor;
@ -305,12 +305,12 @@ pub(crate) fn function_uses_loop_variable(checker: &Checker, node: &Node) {
for name in suspicious_variables {
if reassigned_in_loop.contains(&name.id.as_str()) {
if checker.insert_flake8_bugbear_range(name.range()) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
FunctionUsesLoopVariable {
name: name.id.to_string(),
},
name.range(),
));
);
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_diagnostics::{AlwaysFixableViolation, Edit, Fix};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_python_stdlib::identifiers::{is_identifier, is_mangled_private};
@ -68,7 +68,7 @@ pub(crate) fn getattr_with_constant(checker: &Checker, expr: &Expr, func: &Expr,
return;
}
let mut diagnostic = Diagnostic::new(GetAttrWithConstant, expr.range());
let mut diagnostic = checker.report_diagnostic(GetAttrWithConstant, expr.range());
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
pad(
if matches!(
@ -88,5 +88,4 @@ pub(crate) fn getattr_with_constant(checker: &Checker, expr: &Expr, func: &Expr,
),
expr.range(),
)));
checker.report_diagnostic(diagnostic);
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{self as ast, Stmt};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -56,7 +56,7 @@ impl Violation for JumpStatementInFinally {
fn walk_stmt(checker: &Checker, body: &[Stmt], f: fn(&Stmt) -> bool) {
for stmt in body {
if f(stmt) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
JumpStatementInFinally {
name: match stmt {
Stmt::Break(_) => "break",
@ -67,7 +67,7 @@ fn walk_stmt(checker: &Checker, body: &[Stmt], f: fn(&Stmt) -> bool) {
.to_owned(),
},
stmt.range(),
));
);
}
match stmt {
Stmt::While(ast::StmtWhile { body, .. }) | Stmt::For(ast::StmtFor { body, .. }) => {

View file

@ -1,7 +1,6 @@
use std::collections::HashMap;
use std::fmt::Debug;
use ruff_diagnostics::Diagnostic;
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::comparable::ComparableExpr;
@ -110,7 +109,7 @@ pub(crate) fn loop_iterator_mutation(checker: &Checker, stmt_for: &StmtFor) {
let name = UnqualifiedName::from_expr(iter)
.map(|name| name.to_string())
.map(SourceCodeSnippet::new);
checker.report_diagnostic(Diagnostic::new(LoopIteratorMutation { name }, *mutation));
checker.report_diagnostic(LoopIteratorMutation { name }, *mutation);
}
}

View file

@ -1,7 +1,7 @@
use ruff_python_ast::{self as ast, Expr};
use rustc_hash::FxHashMap;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::visitor;
use ruff_python_ast::visitor::Visitor;
@ -64,12 +64,12 @@ pub(crate) fn loop_variable_overrides_iterator(checker: &Checker, target: &Expr,
for (name, expr) in target_names {
if iter_names.contains_key(name) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
LoopVariableOverridesIterator {
name: name.to_string(),
},
expr.range(),
));
);
}
}
}

View file

@ -1,6 +1,6 @@
use std::fmt::Write;
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
use ruff_diagnostics::{Edit, Fix, FixAvailability, Violation};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::is_docstring_stmt;
use ruff_python_ast::name::QualifiedName;
@ -111,7 +111,7 @@ pub(crate) fn mutable_argument_default(checker: &Checker, function_def: &ast::St
is_immutable_annotation(expr, checker.semantic(), extend_immutable_calls.as_slice())
})
{
let mut diagnostic = Diagnostic::new(MutableArgumentDefault, default.range());
let mut diagnostic = checker.report_diagnostic(MutableArgumentDefault, default.range());
// If the function body is on the same line as the function def, do not fix
if let Some(fix) = move_initialization(
@ -126,7 +126,6 @@ pub(crate) fn mutable_argument_default(checker: &Checker, function_def: &ast::St
) {
diagnostic.set_fix(fix);
}
checker.report_diagnostic(diagnostic);
}
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::map_subscript;
use ruff_python_ast::name::QualifiedName;
@ -102,6 +102,6 @@ pub(crate) fn mutable_contextvar_default(checker: &Checker, call: &ast::ExprCall
matches!(qualified_name.segments(), ["contextvars", "ContextVar"])
})
{
checker.report_diagnostic(Diagnostic::new(MutableContextvarDefault, default.range()));
checker.report_diagnostic(MutableContextvarDefault, default.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Fix};
use ruff_diagnostics::{AlwaysFixableViolation, Fix};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::Ranged;
@ -85,7 +85,7 @@ pub(crate) fn no_explicit_stacklevel(checker: &Checker, call: &ast::ExprCall) {
{
return;
}
let mut diagnostic = Diagnostic::new(NoExplicitStacklevel, call.func.range());
let mut diagnostic = checker.report_diagnostic(NoExplicitStacklevel, call.func.range());
let edit = add_argument(
"stacklevel=2",
@ -95,8 +95,6 @@ pub(crate) fn no_explicit_stacklevel(checker: &Checker, call: &ast::ExprCall) {
);
diagnostic.set_fix(Fix::unsafe_edit(edit));
checker.report_diagnostic(diagnostic);
}
/// Returns `true` if `skip_file_prefixes` is set to its non-default value.

View file

@ -1,6 +1,6 @@
use ruff_python_ast::Expr;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -39,6 +39,6 @@ impl Violation for RaiseLiteral {
/// B016
pub(crate) fn raise_literal(checker: &Checker, expr: &Expr) {
if expr.is_literal_expr() {
checker.report_diagnostic(Diagnostic::new(RaiseLiteral, expr.range()));
checker.report_diagnostic(RaiseLiteral, expr.range());
}
}

View file

@ -1,7 +1,7 @@
use ruff_python_ast as ast;
use ruff_python_ast::Stmt;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::RaiseStatementVisitor;
use ruff_python_ast::statement_visitor::StatementVisitor;
@ -106,10 +106,7 @@ pub(crate) fn raise_without_from_inside_except(
.as_try_stmt()
.is_some_and(|try_stmt| try_stmt.is_star);
checker.report_diagnostic(Diagnostic::new(
RaiseWithoutFromInsideExcept { is_star },
range,
));
checker.report_diagnostic(RaiseWithoutFromInsideExcept { is_star }, range);
}
}
}

View file

@ -2,7 +2,7 @@ use std::fmt;
use ruff_python_ast::{self as ast};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_semantic::Modules;
use ruff_text_size::Ranged;
@ -75,10 +75,7 @@ pub(crate) fn re_sub_positional_args(checker: &Checker, call: &ast::ExprCall) {
};
if call.arguments.args.len() > method.num_args() {
checker.report_diagnostic(Diagnostic::new(
ReSubPositionalArgs { method },
call.range(),
));
checker.report_diagnostic(ReSubPositionalArgs { method }, call.range());
}
}

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_diagnostics::{AlwaysFixableViolation, Edit, Fix};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::{self as ast, ExceptHandler, Expr};
use ruff_text_size::Ranged;
@ -79,7 +79,7 @@ pub(crate) fn redundant_tuple_in_exception_handler(checker: &Checker, handlers:
if elt.is_starred_expr() {
continue;
}
let mut diagnostic = Diagnostic::new(
let mut diagnostic = checker.report_diagnostic(
RedundantTupleInExceptionHandler {
name: checker.generator().expr(elt),
},
@ -100,6 +100,5 @@ pub(crate) fn redundant_tuple_in_exception_handler(checker: &Checker, handlers:
),
type_.range(),
)));
checker.report_diagnostic(diagnostic);
}
}

View file

@ -1,4 +1,3 @@
use ruff_diagnostics::Diagnostic;
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::statement_visitor;
@ -101,7 +100,7 @@ pub(crate) fn return_in_generator(checker: &Checker, function_def: &StmtFunction
if visitor.has_yield {
if let Some(return_) = visitor.return_ {
checker.report_diagnostic(Diagnostic::new(ReturnInGenerator, return_));
checker.report_diagnostic(ReturnInGenerator, return_);
}
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{self as ast, Comprehension, Expr, Stmt};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::visitor::{self, Visitor};
use ruff_text_size::Ranged;
@ -339,6 +339,6 @@ pub(crate) fn reuse_of_groupby_generator(
finder.visit_stmt(stmt);
}
for expr in finder.exprs {
checker.report_diagnostic(Diagnostic::new(ReuseOfGroupbyGenerator, expr.range()));
checker.report_diagnostic(ReuseOfGroupbyGenerator, expr.range());
}
}

View file

@ -1,7 +1,7 @@
use ruff_python_ast::{self as ast, Expr, ExprContext, Identifier, Stmt};
use ruff_text_size::{Ranged, TextRange};
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_diagnostics::{AlwaysFixableViolation, Edit, Fix};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_codegen::Generator;
use ruff_python_stdlib::identifiers::{is_identifier, is_mangled_private};
@ -90,12 +90,11 @@ pub(crate) fn setattr_with_constant(checker: &Checker, expr: &Expr, func: &Expr,
}) = checker.semantic().current_statement()
{
if expr == child.as_ref() {
let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range());
let mut diagnostic = checker.report_diagnostic(SetAttrWithConstant, expr.range());
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
assignment(obj, name.to_str(), value, checker.generator()),
expr.range(),
)));
checker.report_diagnostic(diagnostic);
}
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{Expr, Keyword};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -71,9 +71,6 @@ pub(crate) fn star_arg_unpacking_after_keyword_arg(
if arg.start() <= keyword.start() {
continue;
}
checker.report_diagnostic(Diagnostic::new(
StarArgUnpackingAfterKeywordArg,
arg.range(),
));
checker.report_diagnostic(StarArgUnpackingAfterKeywordArg, arg.range());
}
}

View file

@ -1,6 +1,6 @@
use rustc_hash::FxHashMap;
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::helpers::StoredNameFinder;
use ruff_python_ast::visitor::Visitor;
@ -58,12 +58,12 @@ pub(crate) fn static_key_dict_comprehension(checker: &Checker, dict_comp: &ast::
};
if is_constant(&dict_comp.key, &names) {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
StaticKeyDictComprehension {
key: SourceCodeSnippet::from_str(checker.locator().slice(dict_comp.key.as_ref())),
},
dict_comp.key.range(),
));
);
}
}

View file

@ -1,7 +1,7 @@
use itertools::Itertools;
use ruff_python_ast::{self as ast, Expr};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -73,6 +73,6 @@ pub(crate) fn strip_with_multi_characters(
};
if value.chars().count() > 1 && !value.chars().all_unique() {
checker.report_diagnostic(Diagnostic::new(StripWithMultiCharacters, expr.range()));
checker.report_diagnostic(StripWithMultiCharacters, expr.range());
}
}

View file

@ -1,6 +1,6 @@
use ruff_python_ast::{self as ast, Expr, UnaryOp};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::Violation;
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_text_size::Ranged;
@ -61,20 +61,20 @@ pub(crate) fn unary_prefix_increment_decrement(
};
match (op, nested_op) {
(UnaryOp::UAdd, UnaryOp::UAdd) => {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
UnaryPrefixIncrementDecrement {
operator: UnaryPrefixOperatorType::Increment,
},
expr.range(),
));
);
}
(UnaryOp::USub, UnaryOp::USub) => {
checker.report_diagnostic(Diagnostic::new(
checker.report_diagnostic(
UnaryPrefixIncrementDecrement {
operator: UnaryPrefixOperatorType::Decrement,
},
expr.range(),
));
);
}
_ => {}
}

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