diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs index 393ce0deacf1b6..ac9bc89c341aaf 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs @@ -1632,9 +1632,13 @@ fn common_section( } let line_end = checker.stylist().line_ending().as_str(); - let last_line = context.following_lines().last(); - if last_line.map_or(true, |line| !line.trim().is_empty()) { - if let Some(next) = next { + + if let Some(next) = next { + if context + .following_lines() + .last() + .map_or(true, |line| !line.trim().is_empty()) + { if checker.enabled(Rule::NoBlankLineAfterSection) { let mut diagnostic = Diagnostic::new( NoBlankLineAfterSection { @@ -1649,7 +1653,18 @@ fn common_section( ))); checker.diagnostics.push(diagnostic); } - } else { + } + } else { + // The first blank line is the line containing the closing triple quotes, so we need at + // least two. + if matches!( + context + .following_lines() + .rev() + .take_while(|line| line.trim().is_empty()) + .count(), + 0 | 1 + ) { if checker.enabled(Rule::BlankLineAfterLastSection) { let mut diagnostic = Diagnostic::new( BlankLineAfterLastSection { diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap index 55af2104260924..0565c37439fda3 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap @@ -24,4 +24,141 @@ sections.py:65:5: D413 [*] Missing blank line after last section ("Returns") 69 70 | 70 71 | @expect(_D213) +sections.py:120:5: D413 [*] Missing blank line after last section ("Returns") + | +118 | @expect("D413: Missing blank line after last section ('Returns')") +119 | def no_blank_line_after_last_section(): # noqa: D416 +120 | """Toggle the gizmo. + | _____^ +121 | | +122 | | Returns +123 | | ------- +124 | | A value of some sort. +125 | | """ + | |_______^ D413 + | + = help: Add blank line after "Returns" + +ℹ Safe fix +122 122 | Returns +123 123 | ------- +124 124 | A value of some sort. + 125 |+ +125 126 | """ +126 127 | +127 128 | + +sections.py:170:5: D413 [*] Missing blank line after last section ("Returns") + | +168 | @expect("D414: Section has no content ('Returns')") +169 | def section_underline_overindented_and_contentless(): # noqa: D416 +170 | """Toggle the gizmo. + | _____^ +171 | | +172 | | Returns +173 | | ------- +174 | | """ + | |_______^ D413 + | + = help: Add blank line after "Returns" + +ℹ Safe fix +171 171 | +172 172 | Returns +173 173 | ------- + 174 |+ +174 175 | """ +175 176 | +176 177 | + +sections.py:519:5: D413 [*] Missing blank line after last section ("Parameters") + | +518 | def replace_equals_with_dash(): +519 | """Equal length equals should be replaced with dashes. + | _____^ +520 | | +521 | | Parameters +522 | | ========== +523 | | """ + | |_______^ D413 + | + = help: Add blank line after "Parameters" + +ℹ Safe fix +520 520 | +521 521 | Parameters +522 522 | ========== + 523 |+ +523 524 | """ +524 525 | +525 526 | + +sections.py:527:5: D413 [*] Missing blank line after last section ("Parameters") + | +526 | def replace_equals_with_dash2(): +527 | """Here, the length of equals is not the same. + | _____^ +528 | | +529 | | Parameters +530 | | =========== +531 | | """ + | |_______^ D413 + | + = help: Add blank line after "Parameters" + +ℹ Safe fix +528 528 | +529 529 | Parameters +530 530 | =========== + 531 |+ +531 532 | """ +532 533 | +533 534 | + +sections.py:548:5: D413 [*] Missing blank line after last section ("Args") + | +547 | def lowercase_sub_section_header(): +548 | """Below, `returns:` should _not_ be considered a section header. + | _____^ +549 | | +550 | | Args: +551 | | Here's a note. +552 | | +553 | | returns: +554 | | """ + | |_______^ D413 + | + = help: Add blank line after "Args" + +ℹ Safe fix +551 551 | Here's a note. +552 552 | +553 553 | returns: + 554 |+ +554 555 | """ +555 556 | +556 557 | + +sections.py:558:5: D413 [*] Missing blank line after last section ("Returns") + | +557 | def titlecase_sub_section_header(): +558 | """Below, `Returns:` should be considered a section header. + | _____^ +559 | | +560 | | Args: +561 | | Here's a note. +562 | | +563 | | Returns: +564 | | """ + | |_______^ D413 + | + = help: Add blank line after "Returns" + +ℹ Safe fix +561 561 | Here's a note. +562 562 | +563 563 | Returns: + 564 |+ +564 565 | """ +