Remove some diagnostics.extend calls (#5483)

## Summary

It's more efficient (and more idiomatic for us) to pass in the `Checker`
directly.
This commit is contained in:
Charlie Marsh 2023-07-03 12:47:23 -04:00 committed by GitHub
parent 00fbbe4223
commit ca497fabbd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 75 additions and 90 deletions

View file

@ -359,11 +359,7 @@ where
.. ..
}) => { }) => {
if self.enabled(Rule::DjangoNonLeadingReceiverDecorator) { if self.enabled(Rule::DjangoNonLeadingReceiverDecorator) {
self.diagnostics flake8_django::rules::non_leading_receiver_decorator(self, decorator_list);
.extend(flake8_django::rules::non_leading_receiver_decorator(
decorator_list,
|expr| self.semantic.resolve_call_path(expr),
));
} }
if self.enabled(Rule::AmbiguousFunctionName) { if self.enabled(Rule::AmbiguousFunctionName) {
if let Some(diagnostic) = if let Some(diagnostic) =
@ -505,8 +501,7 @@ where
} }
} }
if self.enabled(Rule::HardcodedPasswordDefault) { if self.enabled(Rule::HardcodedPasswordDefault) {
self.diagnostics flake8_bandit::rules::hardcoded_password_default(self, args);
.extend(flake8_bandit::rules::hardcoded_password_default(args));
} }
if self.enabled(Rule::PropertyWithParameters) { if self.enabled(Rule::PropertyWithParameters) {
pylint::rules::property_with_parameters(self, stmt, decorator_list, args); pylint::rules::property_with_parameters(self, stmt, decorator_list, args);
@ -1573,9 +1568,7 @@ where
pyupgrade::rules::os_error_alias_handlers(self, handlers); pyupgrade::rules::os_error_alias_handlers(self, handlers);
} }
if self.enabled(Rule::PytestAssertInExcept) { if self.enabled(Rule::PytestAssertInExcept) {
self.diagnostics.extend( flake8_pytest_style::rules::assert_in_exception_handler(self, handlers);
flake8_pytest_style::rules::assert_in_exception_handler(handlers),
);
} }
if self.enabled(Rule::SuppressibleException) { if self.enabled(Rule::SuppressibleException) {
flake8_simplify::rules::suppressible_exception( flake8_simplify::rules::suppressible_exception(
@ -1616,11 +1609,7 @@ where
flake8_bugbear::rules::assignment_to_os_environ(self, targets); flake8_bugbear::rules::assignment_to_os_environ(self, targets);
} }
if self.enabled(Rule::HardcodedPasswordString) { if self.enabled(Rule::HardcodedPasswordString) {
if let Some(diagnostic) = flake8_bandit::rules::assign_hardcoded_password_string(self, value, targets);
flake8_bandit::rules::assign_hardcoded_password_string(value, targets)
{
self.diagnostics.push(diagnostic);
}
} }
if self.enabled(Rule::GlobalStatement) { if self.enabled(Rule::GlobalStatement) {
for target in targets.iter() { for target in targets.iter() {
@ -2615,8 +2604,7 @@ where
flake8_bandit::rules::jinja2_autoescape_false(self, func, args, keywords); flake8_bandit::rules::jinja2_autoescape_false(self, func, args, keywords);
} }
if self.enabled(Rule::HardcodedPasswordFuncArg) { if self.enabled(Rule::HardcodedPasswordFuncArg) {
self.diagnostics flake8_bandit::rules::hardcoded_password_func_arg(self, keywords);
.extend(flake8_bandit::rules::hardcoded_password_func_arg(keywords));
} }
if self.enabled(Rule::HardcodedSQLExpression) { if self.enabled(Rule::HardcodedSQLExpression) {
flake8_bandit::rules::hardcoded_sql_expression(self, expr); flake8_bandit::rules::hardcoded_sql_expression(self, expr);
@ -2871,16 +2859,13 @@ where
&self.settings.flake8_gettext.functions_names, &self.settings.flake8_gettext.functions_names,
) { ) {
if self.enabled(Rule::FStringInGetTextFuncCall) { if self.enabled(Rule::FStringInGetTextFuncCall) {
self.diagnostics flake8_gettext::rules::f_string_in_gettext_func_call(self, args);
.extend(flake8_gettext::rules::f_string_in_gettext_func_call(args));
} }
if self.enabled(Rule::FormatInGetTextFuncCall) { if self.enabled(Rule::FormatInGetTextFuncCall) {
self.diagnostics flake8_gettext::rules::format_in_gettext_func_call(self, args);
.extend(flake8_gettext::rules::format_in_gettext_func_call(args));
} }
if self.enabled(Rule::PrintfInGetTextFuncCall) { if self.enabled(Rule::PrintfInGetTextFuncCall) {
self.diagnostics flake8_gettext::rules::printf_in_gettext_func_call(self, args);
.extend(flake8_gettext::rules::printf_in_gettext_func_call(args));
} }
} }
if self.enabled(Rule::UncapitalizedEnvironmentVariables) { if self.enabled(Rule::UncapitalizedEnvironmentVariables) {
@ -3221,11 +3206,10 @@ where
flake8_2020::rules::compare(self, left, ops, comparators); flake8_2020::rules::compare(self, left, ops, comparators);
} }
if self.enabled(Rule::HardcodedPasswordString) { if self.enabled(Rule::HardcodedPasswordString) {
self.diagnostics.extend(
flake8_bandit::rules::compare_to_hardcoded_password_string( flake8_bandit::rules::compare_to_hardcoded_password_string(
self,
left, left,
comparators, comparators,
),
); );
} }
if self.enabled(Rule::ComparisonWithItself) { if self.enabled(Rule::ComparisonWithItself) {

View file

@ -1,5 +1,6 @@
use rustpython_parser::ast::{Arg, ArgWithDefault, Arguments, Expr, Ranged}; use rustpython_parser::ast::{Arg, ArgWithDefault, Arguments, Expr, Ranged};
use crate::checkers::ast::Checker;
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -36,9 +37,7 @@ fn check_password_kwarg(arg: &Arg, default: &Expr) -> Option<Diagnostic> {
} }
/// S107 /// S107
pub(crate) fn hardcoded_password_default(arguments: &Arguments) -> Vec<Diagnostic> { pub(crate) fn hardcoded_password_default(checker: &mut Checker, arguments: &Arguments) {
let mut diagnostics: Vec<Diagnostic> = Vec::new();
for ArgWithDefault { for ArgWithDefault {
def, def,
default, default,
@ -53,9 +52,7 @@ pub(crate) fn hardcoded_password_default(arguments: &Arguments) -> Vec<Diagnosti
continue; continue;
}; };
if let Some(diagnostic) = check_password_kwarg(def, default) { if let Some(diagnostic) = check_password_kwarg(def, default) {
diagnostics.push(diagnostic); checker.diagnostics.push(diagnostic);
} }
} }
diagnostics
} }

View file

@ -1,5 +1,6 @@
use rustpython_parser::ast::{Keyword, Ranged}; use rustpython_parser::ast::{Keyword, Ranged};
use crate::checkers::ast::Checker;
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -22,10 +23,10 @@ impl Violation for HardcodedPasswordFuncArg {
} }
/// S106 /// S106
pub(crate) fn hardcoded_password_func_arg(keywords: &[Keyword]) -> Vec<Diagnostic> { pub(crate) fn hardcoded_password_func_arg(checker: &mut Checker, keywords: &[Keyword]) {
keywords checker
.iter() .diagnostics
.filter_map(|keyword| { .extend(keywords.iter().filter_map(|keyword| {
string_literal(&keyword.value).filter(|string| !string.is_empty())?; string_literal(&keyword.value).filter(|string| !string.is_empty())?;
let arg = keyword.arg.as_ref()?; let arg = keyword.arg.as_ref()?;
if !matches_password_name(arg) { if !matches_password_name(arg) {
@ -37,6 +38,5 @@ pub(crate) fn hardcoded_password_func_arg(keywords: &[Keyword]) -> Vec<Diagnosti
}, },
keyword.range(), keyword.range(),
)) ))
}) }));
.collect()
} }

View file

@ -3,6 +3,8 @@ use rustpython_parser::ast::{self, Constant, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker;
use super::super::helpers::{matches_password_name, string_literal}; use super::super::helpers::{matches_password_name, string_literal};
#[violation] #[violation]
@ -47,12 +49,13 @@ fn password_target(target: &Expr) -> Option<&str> {
/// S105 /// S105
pub(crate) fn compare_to_hardcoded_password_string( pub(crate) fn compare_to_hardcoded_password_string(
checker: &mut Checker,
left: &Expr, left: &Expr,
comparators: &[Expr], comparators: &[Expr],
) -> Vec<Diagnostic> { ) {
comparators checker
.iter() .diagnostics
.filter_map(|comp| { .extend(comparators.iter().filter_map(|comp| {
string_literal(comp).filter(|string| !string.is_empty())?; string_literal(comp).filter(|string| !string.is_empty())?;
let Some(name) = password_target(left) else { let Some(name) = password_target(left) else {
return None; return None;
@ -63,29 +66,29 @@ pub(crate) fn compare_to_hardcoded_password_string(
}, },
comp.range(), comp.range(),
)) ))
}) }));
.collect()
} }
/// S105 /// S105
pub(crate) fn assign_hardcoded_password_string( pub(crate) fn assign_hardcoded_password_string(
checker: &mut Checker,
value: &Expr, value: &Expr,
targets: &[Expr], targets: &[Expr],
) -> Option<Diagnostic> { ) {
if string_literal(value) if string_literal(value)
.filter(|string| !string.is_empty()) .filter(|string| !string.is_empty())
.is_some() .is_some()
{ {
for target in targets { for target in targets {
if let Some(name) = password_target(target) { if let Some(name) = password_target(target) {
return Some(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
HardcodedPasswordString { HardcodedPasswordString {
name: name.to_string(), name: name.to_string(),
}, },
value.range(), value.range(),
)); ));
return;
} }
} }
} }
None
} }

View file

@ -1,8 +1,9 @@
use rustpython_parser::ast::{self, Decorator, Expr, Ranged}; use rustpython_parser::ast::{Decorator, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::call_path::CallPath;
use crate::checkers::ast::Checker;
/// ## What it does /// ## What it does
/// Checks that Django's `@receiver` decorator is listed first, prior to /// Checks that Django's `@receiver` decorator is listed first, prior to
@ -48,25 +49,19 @@ impl Violation for DjangoNonLeadingReceiverDecorator {
} }
/// DJ013 /// DJ013
pub(crate) fn non_leading_receiver_decorator<'a, F>( pub(crate) fn non_leading_receiver_decorator(checker: &mut Checker, decorator_list: &[Decorator]) {
decorator_list: &'a [Decorator],
resolve_call_path: F,
) -> Vec<Diagnostic>
where
F: Fn(&'a Expr) -> Option<CallPath<'a>>,
{
let mut diagnostics = vec![];
let mut seen_receiver = false; let mut seen_receiver = false;
for (i, decorator) in decorator_list.iter().enumerate() { for (i, decorator) in decorator_list.iter().enumerate() {
let is_receiver = match &decorator.expression { let is_receiver = decorator.expression.as_call_expr().map_or(false, |call| {
Expr::Call(ast::ExprCall { func, .. }) => resolve_call_path(func) checker
.semantic()
.resolve_call_path(&call.func)
.map_or(false, |call_path| { .map_or(false, |call_path| {
matches!(call_path.as_slice(), ["django", "dispatch", "receiver"]) matches!(call_path.as_slice(), ["django", "dispatch", "receiver"])
}), })
_ => false, });
};
if i > 0 && is_receiver && !seen_receiver { if i > 0 && is_receiver && !seen_receiver {
diagnostics.push(Diagnostic::new( checker.diagnostics.push(Diagnostic::new(
DjangoNonLeadingReceiverDecorator, DjangoNonLeadingReceiverDecorator,
decorator.range(), decorator.range(),
)); ));
@ -77,5 +72,4 @@ where
seen_receiver = true; seen_receiver = true;
} }
} }
diagnostics
} }

View file

@ -3,6 +3,8 @@ use rustpython_parser::ast::{Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker;
#[violation] #[violation]
pub struct FStringInGetTextFuncCall; pub struct FStringInGetTextFuncCall;
@ -14,11 +16,12 @@ impl Violation for FStringInGetTextFuncCall {
} }
/// INT001 /// INT001
pub(crate) fn f_string_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> { pub(crate) fn f_string_in_gettext_func_call(checker: &mut Checker, args: &[Expr]) {
if let Some(first) = args.first() { if let Some(first) = args.first() {
if first.is_joined_str_expr() { if first.is_joined_str_expr() {
return Some(Diagnostic::new(FStringInGetTextFuncCall {}, first.range())); checker
.diagnostics
.push(Diagnostic::new(FStringInGetTextFuncCall {}, first.range()));
} }
} }
None
} }

View file

@ -3,6 +3,8 @@ use rustpython_parser::ast::{self, Expr, Ranged};
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use crate::checkers::ast::Checker;
#[violation] #[violation]
pub struct FormatInGetTextFuncCall; pub struct FormatInGetTextFuncCall;
@ -14,15 +16,16 @@ impl Violation for FormatInGetTextFuncCall {
} }
/// INT002 /// INT002
pub(crate) fn format_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> { pub(crate) fn format_in_gettext_func_call(checker: &mut Checker, args: &[Expr]) {
if let Some(first) = args.first() { if let Some(first) = args.first() {
if let Expr::Call(ast::ExprCall { func, .. }) = &first { if let Expr::Call(ast::ExprCall { func, .. }) = &first {
if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() { if let Expr::Attribute(ast::ExprAttribute { attr, .. }) = func.as_ref() {
if attr == "format" { if attr == "format" {
return Some(Diagnostic::new(FormatInGetTextFuncCall {}, first.range())); checker
.diagnostics
.push(Diagnostic::new(FormatInGetTextFuncCall {}, first.range()));
} }
} }
} }
} }
None
} }

View file

@ -1,5 +1,6 @@
use rustpython_parser::ast::{self, Constant, Expr, Operator, Ranged}; use rustpython_parser::ast::{self, Constant, Expr, Operator, Ranged};
use crate::checkers::ast::Checker;
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
@ -14,7 +15,7 @@ impl Violation for PrintfInGetTextFuncCall {
} }
/// INT003 /// INT003
pub(crate) fn printf_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> { pub(crate) fn printf_in_gettext_func_call(checker: &mut Checker, args: &[Expr]) {
if let Some(first) = args.first() { if let Some(first) = args.first() {
if let Expr::BinOp(ast::ExprBinOp { if let Expr::BinOp(ast::ExprBinOp {
op: Operator::Mod { .. }, op: Operator::Mod { .. },
@ -27,9 +28,10 @@ pub(crate) fn printf_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
.. ..
}) = left.as_ref() }) = left.as_ref()
{ {
return Some(Diagnostic::new(PrintfInGetTextFuncCall {}, first.range())); checker
.diagnostics
.push(Diagnostic::new(PrintfInGetTextFuncCall {}, first.range()));
} }
} }
} }
None
} }

View file

@ -226,10 +226,10 @@ pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) {
} }
/// PT017 /// PT017
pub(crate) fn assert_in_exception_handler(handlers: &[ExceptHandler]) -> Vec<Diagnostic> { pub(crate) fn assert_in_exception_handler(checker: &mut Checker, handlers: &[ExceptHandler]) {
handlers checker
.iter() .diagnostics
.flat_map(|handler| match handler { .extend(handlers.iter().flat_map(|handler| match handler {
ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler { ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
name, body, .. name, body, ..
}) => { }) => {
@ -239,8 +239,7 @@ pub(crate) fn assert_in_exception_handler(handlers: &[ExceptHandler]) -> Vec<Dia
Vec::new() Vec::new()
} }
} }
}) }));
.collect()
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -5,27 +5,27 @@ use ruff_python_ast::visitor;
use ruff_python_ast::visitor::Visitor; use ruff_python_ast::visitor::Visitor;
#[derive(Default)] #[derive(Default)]
pub(crate) struct Stack<'a> { pub(super) struct Stack<'a> {
/// The `return` statements in the current function. /// The `return` statements in the current function.
pub(crate) returns: Vec<&'a ast::StmtReturn>, pub(super) returns: Vec<&'a ast::StmtReturn>,
/// The `else` statements in the current function. /// The `else` statements in the current function.
pub(crate) elses: Vec<&'a ast::StmtIf>, pub(super) elses: Vec<&'a ast::StmtIf>,
/// The `elif` statements in the current function. /// The `elif` statements in the current function.
pub(crate) elifs: Vec<&'a ast::StmtIf>, pub(super) elifs: Vec<&'a ast::StmtIf>,
/// The non-local variables in the current function. /// The non-local variables in the current function.
pub(crate) non_locals: FxHashSet<&'a str>, pub(super) non_locals: FxHashSet<&'a str>,
/// Whether the current function is a generator. /// Whether the current function is a generator.
pub(crate) is_generator: bool, pub(super) is_generator: bool,
/// The `assignment`-to-`return` statement pairs in the current function. /// The `assignment`-to-`return` statement pairs in the current function.
/// TODO(charlie): Remove the extra [`Stmt`] here, which is necessary to support statement /// TODO(charlie): Remove the extra [`Stmt`] here, which is necessary to support statement
/// removal for the `return` statement. /// removal for the `return` statement.
pub(crate) assignment_return: Vec<(&'a ast::StmtAssign, &'a ast::StmtReturn, &'a Stmt)>, pub(super) assignment_return: Vec<(&'a ast::StmtAssign, &'a ast::StmtReturn, &'a Stmt)>,
} }
#[derive(Default)] #[derive(Default)]
pub(crate) struct ReturnVisitor<'a> { pub(super) struct ReturnVisitor<'a> {
/// The current stack of nodes. /// The current stack of nodes.
pub(crate) stack: Stack<'a>, pub(super) stack: Stack<'a>,
/// The preceding sibling of the current node. /// The preceding sibling of the current node.
sibling: Option<&'a Stmt>, sibling: Option<&'a Stmt>,
/// The parent nodes of the current node. /// The parent nodes of the current node.