Handle multiple receiver decorators in receiver-decorator (#2858)

This commit is contained in:
Charlie Marsh 2023-02-13 09:57:11 -05:00 committed by GitHub
parent 15f65fa8d6
commit 1705574e75
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 18 deletions

View file

@ -15,3 +15,23 @@ def correct_pre_save_handler():
@receiver(pre_save, sender=MyModel)
def incorrect_pre_save_handler():
pass
@receiver(pre_save, sender=MyModel)
@receiver(pre_save, sender=MyModel)
@test_decorator
def correct_multiple():
pass
@receiver(pre_save, sender=MyModel)
@receiver(pre_save, sender=MyModel)
def correct_multiple():
pass
@receiver(pre_save, sender=MyModel)
@test_decorator
@receiver(pre_save, sender=MyModel)
def incorrect_multiple():
pass

View file

@ -465,13 +465,11 @@ where
..
} => {
if self.settings.rules.enabled(&Rule::ReceiverDecoratorChecker) {
if let Some(diagnostic) =
flake8_django::rules::receiver_decorator_checker(decorator_list, |expr| {
self.resolve_call_path(expr)
})
{
self.diagnostics.push(diagnostic);
}
self.diagnostics
.extend(flake8_django::rules::receiver_decorator_checker(
decorator_list,
|expr| self.resolve_call_path(expr),
));
}
if self.settings.rules.enabled(&Rule::AmbiguousFunctionName) {
if let Some(diagnostic) =

View file

@ -51,25 +51,30 @@ impl Violation for ReceiverDecoratorChecker {
pub fn receiver_decorator_checker<'a, F>(
decorator_list: &'a [Expr],
resolve_call_path: F,
) -> Option<Diagnostic>
) -> Vec<Diagnostic>
where
F: Fn(&'a Expr) -> Option<CallPath<'a>>,
{
let mut diagnostics = vec![];
let mut seen_receiver = false;
for (i, decorator) in decorator_list.iter().enumerate() {
if i == 0 {
continue;
}
let ExprKind::Call{ func, ..} = &decorator.node else {
continue;
let is_receiver = match &decorator.node {
ExprKind::Call { func, .. } => resolve_call_path(func).map_or(false, |call_path| {
call_path.as_slice() == ["django", "dispatch", "receiver"]
}),
_ => false,
};
if resolve_call_path(func).map_or(false, |call_path| {
call_path.as_slice() == ["django", "dispatch", "receiver"]
}) {
return Some(Diagnostic::new(
if i > 0 && is_receiver && !seen_receiver {
diagnostics.push(Diagnostic::new(
ReceiverDecoratorChecker,
Range::from_located(decorator),
));
}
if !is_receiver && seen_receiver {
seen_receiver = false;
} else if is_receiver {
seen_receiver = true;
}
}
None
diagnostics
}

View file

@ -12,4 +12,14 @@ expression: diagnostics
column: 35
fix: ~
parent: ~
- kind:
ReceiverDecoratorChecker: ~
location:
row: 35
column: 1
end_location:
row: 35
column: 35
fix: ~
parent: ~