Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ def __init__():
pass


class NonEmptyChildWithInlineComment:
value: int
... # preserve me


class EmptyClass:
...

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class NonEmptyWithInit:
def __init__():
pass

class NonEmptyChildWithInlineComment:
value: int
... # preserve me

# Not violations

class EmptyClass: ...
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast::whitespace::trailing_comment_start_offset;
use ruff_python_ast::{Stmt, StmtExpr};
use ruff_text_size::Ranged;

use crate::checkers::ast::Checker;
use crate::fix;
use crate::{Fix, FixAvailability, Violation};
use crate::{Edit, Fix, FixAvailability, Violation};

/// ## What it does
/// Removes ellipses (`...`) in otherwise non-empty class bodies.
Expand Down Expand Up @@ -50,15 +51,21 @@ pub(crate) fn ellipsis_in_non_empty_class_body(checker: &Checker, body: &[Stmt])
}

for stmt in body {
let Stmt::Expr(StmtExpr { value, .. }) = &stmt else {
let Stmt::Expr(StmtExpr { value, .. }) = stmt else {
continue;
};

if value.is_ellipsis_literal_expr() {
let mut diagnostic =
checker.report_diagnostic(EllipsisInNonEmptyClassBody, stmt.range());
let edit =
fix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer());

// Try to preserve trailing comment if it exists
let edit = if let Some(index) = trailing_comment_start_offset(stmt, checker.source()) {
Edit::range_deletion(stmt.range().add_end(index))
} else {
fix::edits::delete_stmt(stmt, Some(stmt), checker.locator(), checker.indexer())
};

diagnostic.set_fix(Fix::safe_edit(edit).isolate(Checker::isolation(
checker.semantic().current_statement_id(),
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,22 @@ PYI013.py:36:5: PYI013 [*] Non-empty class body must not contain `...`
37 36 |
38 37 | def __init__():
39 38 | pass

PYI013.py:44:5: PYI013 [*] Non-empty class body must not contain `...`
|
42 | class NonEmptyChildWithInlineComment:
43 | value: int
44 | ... # preserve me
| ^^^ PYI013
|
= help: Remove unnecessary `...`

ℹ Safe fix
41 41 |
42 42 | class NonEmptyChildWithInlineComment:
43 43 | value: int
44 |- ... # preserve me
44 |+ # preserve me
45 45 |
46 46 |
47 47 | class EmptyClass:
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ PYI013.pyi:5:5: PYI013 [*] Non-empty class body must not contain `...`
3 3 | class OneAttributeClass:
4 4 | value: int
5 |- ... # Error
6 5 |
7 6 | class OneAttributeClass2:
8 7 | ... # Error
5 |+ # Error
6 6 |
7 7 | class OneAttributeClass2:
8 8 | ... # Error

PYI013.pyi:8:5: PYI013 [*] Non-empty class body must not contain `...`
|
Expand All @@ -35,9 +36,10 @@ PYI013.pyi:8:5: PYI013 [*] Non-empty class body must not contain `...`
6 6 |
7 7 | class OneAttributeClass2:
8 |- ... # Error
9 8 | value: int
10 9 |
11 10 | class MyClass:
8 |+ # Error
9 9 | value: int
10 10 |
11 11 | class MyClass:

PYI013.pyi:12:5: PYI013 [*] Non-empty class body must not contain `...`
|
Expand Down Expand Up @@ -91,9 +93,10 @@ PYI013.pyi:17:5: PYI013 [*] Non-empty class body must not contain `...`
15 15 | class TwoEllipsesClass:
16 16 | ...
17 |- ... # Error
18 17 |
19 18 | class DocstringClass:
20 19 | """
17 |+ # Error
18 18 |
19 19 | class DocstringClass:
20 20 | """

PYI013.pyi:24:5: PYI013 [*] Non-empty class body must not contain `...`
|
Expand All @@ -111,9 +114,10 @@ PYI013.pyi:24:5: PYI013 [*] Non-empty class body must not contain `...`
22 22 | """
23 23 |
24 |- ... # Error
25 24 |
26 25 | class NonEmptyChild(Exception):
27 26 | value: int
24 |+ # Error
25 25 |
26 26 | class NonEmptyChild(Exception):
27 27 | value: int

PYI013.pyi:28:5: PYI013 [*] Non-empty class body must not contain `...`
|
Expand All @@ -131,9 +135,10 @@ PYI013.pyi:28:5: PYI013 [*] Non-empty class body must not contain `...`
26 26 | class NonEmptyChild(Exception):
27 27 | value: int
28 |- ... # Error
29 28 |
30 29 | class NonEmptyChild2(Exception):
31 30 | ... # Error
28 |+ # Error
29 29 |
30 30 | class NonEmptyChild2(Exception):
31 31 | ... # Error

PYI013.pyi:31:5: PYI013 [*] Non-empty class body must not contain `...`
|
Expand All @@ -149,9 +154,10 @@ PYI013.pyi:31:5: PYI013 [*] Non-empty class body must not contain `...`
29 29 |
30 30 | class NonEmptyChild2(Exception):
31 |- ... # Error
32 31 | value: int
33 32 |
34 33 | class NonEmptyWithInit:
31 |+ # Error
32 32 | value: int
33 33 |
34 34 | class NonEmptyWithInit:

PYI013.pyi:36:5: PYI013 [*] Non-empty class body must not contain `...`
|
Expand All @@ -169,6 +175,28 @@ PYI013.pyi:36:5: PYI013 [*] Non-empty class body must not contain `...`
34 34 | class NonEmptyWithInit:
35 35 | value: int
36 |- ... # Error
37 36 |
38 37 | def __init__():
39 38 | pass
36 |+ # Error
37 37 |
38 38 | def __init__():
39 39 | pass

PYI013.pyi:43:5: PYI013 [*] Non-empty class body must not contain `...`
|
41 | class NonEmptyChildWithInlineComment:
42 | value: int
43 | ... # preserve me
| ^^^ PYI013
44 |
45 | # Not violations
|
= help: Remove unnecessary `...`

ℹ Safe fix
40 40 |
41 41 | class NonEmptyChildWithInlineComment:
42 42 | value: int
43 |- ... # preserve me
43 |+ # preserve me
44 44 |
45 45 | # Not violations
46 46 |
Loading