-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Summary Implement [`super-without-brackets`/`W0245`](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/super-without-brackets.html) See: #970 ## Test Plan `cargo test`
- Loading branch information
1 parent
08c60f5
commit 3fcc140
Showing
8 changed files
with
183 additions
and
0 deletions.
There are no files selected for viewing
33 changes: 33 additions & 0 deletions
33
crates/ruff_linter/resources/test/fixtures/pylint/super_without_brackets.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
class Animal: | ||
@staticmethod | ||
def speak(): | ||
return f"This animal says something." | ||
|
||
|
||
class BadDog(Animal): | ||
@staticmethod | ||
def speak(): | ||
original_speak = super.speak() # PLW0245 | ||
return f"{original_speak} But as a dog, it barks!" | ||
|
||
|
||
class GoodDog(Animal): | ||
@staticmethod | ||
def speak(): | ||
original_speak = super().speak() # OK | ||
return f"{original_speak} But as a dog, it barks!" | ||
|
||
|
||
class FineDog(Animal): | ||
@staticmethod | ||
def speak(): | ||
super = "super" | ||
original_speak = super.speak() # OK | ||
return f"{original_speak} But as a dog, it barks!" | ||
|
||
|
||
def super_without_class() -> None: | ||
super.blah() # OK | ||
|
||
|
||
super.blah() # OK |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
crates/ruff_linter/src/rules/pylint/rules/super_without_brackets.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
use ruff_python_ast::{self as ast, Expr}; | ||
use ruff_python_semantic::{analyze::function_type, ScopeKind}; | ||
|
||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; | ||
use ruff_macros::{derive_message_formats, violation}; | ||
use ruff_text_size::Ranged; | ||
|
||
use crate::checkers::ast::Checker; | ||
|
||
/// ## What it does | ||
/// Checks for `super` calls without parentheses. | ||
/// | ||
/// ## Why is this bad? | ||
/// When `super` is used without parentheses, it is not an actual call, and | ||
/// thus has no effect. | ||
/// | ||
/// ## Example | ||
/// ```python | ||
/// class Animal: | ||
/// @staticmethod | ||
/// def speak(): | ||
/// return "This animal says something." | ||
/// | ||
/// | ||
/// class Dog(Animal): | ||
/// @staticmethod | ||
/// def speak(): | ||
/// original_speak = super.speak() | ||
/// return f"{original_speak} But as a dog, it barks!" | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
/// ```python | ||
/// class Animal: | ||
/// @staticmethod | ||
/// def speak(): | ||
/// return "This animal says something." | ||
/// | ||
/// | ||
/// class Dog(Animal): | ||
/// @staticmethod | ||
/// def speak(): | ||
/// original_speak = super().speak() | ||
/// return f"{original_speak} But as a dog, it barks!" | ||
/// ``` | ||
#[violation] | ||
pub struct SuperWithoutBrackets; | ||
|
||
impl AlwaysFixableViolation for SuperWithoutBrackets { | ||
#[derive_message_formats] | ||
fn message(&self) -> String { | ||
format!("`super` call is missing parentheses") | ||
} | ||
|
||
fn fix_title(&self) -> String { | ||
"Add parentheses to `super` call".to_string() | ||
} | ||
} | ||
|
||
/// PLW0245 | ||
pub(crate) fn super_without_brackets(checker: &mut Checker, func: &Expr) { | ||
// The call must be to `super` (without parentheses). | ||
let Expr::Attribute(ast::ExprAttribute { value, .. }) = func else { | ||
return; | ||
}; | ||
|
||
let Expr::Name(ast::ExprName { id, .. }) = value.as_ref() else { | ||
return; | ||
}; | ||
|
||
if id.as_str() != "super" { | ||
return; | ||
} | ||
|
||
if !checker.semantic().is_builtin(id.as_str()) { | ||
return; | ||
} | ||
|
||
let scope = checker.semantic().current_scope(); | ||
|
||
// The current scope _must_ be a function. | ||
let ScopeKind::Function(function_def) = scope.kind else { | ||
return; | ||
}; | ||
|
||
let Some(parent) = &checker.semantic().first_non_type_parent_scope(scope) else { | ||
return; | ||
}; | ||
|
||
// The function must be a method, class method, or static method. | ||
let classification = function_type::classify( | ||
&function_def.name, | ||
&function_def.decorator_list, | ||
parent, | ||
checker.semantic(), | ||
&checker.settings.pep8_naming.classmethod_decorators, | ||
&checker.settings.pep8_naming.staticmethod_decorators, | ||
); | ||
if !matches!( | ||
classification, | ||
function_type::FunctionType::Method { .. } | ||
| function_type::FunctionType::ClassMethod { .. } | ||
| function_type::FunctionType::StaticMethod { .. } | ||
) { | ||
return; | ||
} | ||
|
||
let mut diagnostic = Diagnostic::new(SuperWithoutBrackets, value.range()); | ||
|
||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( | ||
"super()".to_string(), | ||
value.range(), | ||
))); | ||
|
||
checker.diagnostics.push(diagnostic); | ||
} |
24 changes: 24 additions & 0 deletions
24
...ylint/snapshots/ruff_linter__rules__pylint__tests__PLW0245_super_without_brackets.py.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
--- | ||
source: crates/ruff_linter/src/rules/pylint/mod.rs | ||
--- | ||
super_without_brackets.py:10:26: PLW0245 [*] `super` call is missing parentheses | ||
| | ||
8 | @staticmethod | ||
9 | def speak(): | ||
10 | original_speak = super.speak() # PLW0245 | ||
| ^^^^^ PLW0245 | ||
11 | return f"{original_speak} But as a dog, it barks!" | ||
| | ||
= help: Add parentheses to `super` call | ||
|
||
ℹ Safe fix | ||
7 7 | class BadDog(Animal): | ||
8 8 | @staticmethod | ||
9 9 | def speak(): | ||
10 |- original_speak = super.speak() # PLW0245 | ||
10 |+ original_speak = super().speak() # PLW0245 | ||
11 11 | return f"{original_speak} But as a dog, it barks!" | ||
12 12 | | ||
13 13 | | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.