diff --git a/crates/ruff_linter/resources/test/fixtures/pydocstyle/D413.py b/crates/ruff_linter/resources/test/fixtures/pydocstyle/D413.py index 1d04024f8c..3d912aae4f 100644 --- a/crates/ruff_linter/resources/test/fixtures/pydocstyle/D413.py +++ b/crates/ruff_linter/resources/test/fixtures/pydocstyle/D413.py @@ -57,3 +57,15 @@ def func(): Returns: the value""" + + +def func(): + """Do something. + + Args: + x: the value + with a hanging indent + + Returns: + the value + """ diff --git a/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs b/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs index 7275cff37f..c9074b377e 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs +++ b/crates/ruff_linter/src/rules/pydocstyle/rules/sections.rs @@ -1665,21 +1665,30 @@ fn common_section( .take_while(|line| line.trim().is_empty()) .count(); if num_blank_lines < 2 { + let del_len = if num_blank_lines == 1 { + // SAFETY: Guaranteed to not be None, because `num_blank_lines`is 1. + context.following_lines().next_back().unwrap().text_len() + } else { + TextSize::new(0) + }; + + let edit = Edit::replacement( + format!( + "{}{}", + line_end.repeat(2 - num_blank_lines), + docstring.indentation + ), + context.end() - del_len, + context.end(), + ); + let mut diagnostic = Diagnostic::new( BlankLineAfterLastSection { name: context.section_name().to_string(), }, docstring.range(), ); - // Add a newline after the section. - diagnostic.set_fix(Fix::safe_edit(Edit::insertion( - format!( - "{}{}", - line_end.repeat(2 - num_blank_lines), - docstring.indentation - ), - context.end(), - ))); + diagnostic.set_fix(Fix::safe_edit(edit)); checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap index ae996b1e45..c04db39b79 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap @@ -46,7 +46,7 @@ D413.py:13:5: D413 [*] Missing blank line after last section ("Returns") 18 18 | 19 19 | Returns: 20 20 | the value - 21 |+ + 21 |+ 21 22 | """ 22 23 | 23 24 | @@ -75,5 +75,31 @@ D413.py:52:5: D413 [*] Missing blank line after last section ("Returns") 59 |+ the value 60 |+ 61 |+ """ +60 62 | +61 63 | +62 64 | def func(): +D413.py:63:5: D413 [*] Missing blank line after last section ("Returns") + | +62 | def func(): +63 | """Do something. + | _____^ +64 | | +65 | | Args: +66 | | x: the value +67 | | with a hanging indent +68 | | +69 | | Returns: +70 | | the value +71 | | """ + | |___________^ D413 + | + = help: Add blank line after "Returns" +ℹ Safe fix +68 68 | +69 69 | Returns: +70 70 | the value +71 |- """ + 71 |+ + 72 |+ """ 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 0d1bcec87a..3618cdd6ca 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 @@ -44,7 +44,7 @@ sections.py:120:5: D413 [*] Missing blank line after last section ("Returns") 122 122 | Returns 123 123 | ------- 124 124 | A value of some sort. - 125 |+ + 125 |+ 125 126 | """ 126 127 | 127 128 | @@ -67,7 +67,7 @@ sections.py:170:5: D413 [*] Missing blank line after last section ("Returns") 171 171 | 172 172 | Returns 173 173 | ------- - 174 |+ + 174 |+ 174 175 | """ 175 176 | 176 177 | @@ -89,7 +89,7 @@ sections.py:519:5: D413 [*] Missing blank line after last section ("Parameters") 520 520 | 521 521 | Parameters 522 522 | ========== - 523 |+ + 523 |+ 523 524 | """ 524 525 | 525 526 | @@ -111,7 +111,7 @@ sections.py:527:5: D413 [*] Missing blank line after last section ("Parameters") 528 528 | 529 529 | Parameters 530 530 | =========== - 531 |+ + 531 |+ 531 532 | """ 532 533 | 533 534 | @@ -135,7 +135,7 @@ sections.py:548:5: D413 [*] Missing blank line after last section ("Args") 551 551 | Here's a note. 552 552 | 553 553 | returns: - 554 |+ + 554 |+ 554 555 | """ 555 556 | 556 557 | @@ -159,7 +159,7 @@ sections.py:558:5: D413 [*] Missing blank line after last section ("Returns") 561 561 | Here's a note. 562 562 | 563 563 | Returns: - 564 |+ + 564 |+ 564 565 | """ 565 566 | 566 567 | @@ -185,9 +185,7 @@ sections.py:588:5: D413 [*] Missing blank line after last section ("Parameters") 593 593 | A list of string parameters 594 594 | value: 595 595 | Some value - 596 |+ + 596 |+ 596 597 | """ 597 598 | -598 599 | - - +598 599 |