Skip to content

Commit

Permalink
Fix panic in D208 with multibyte indent (#9147)
Browse files Browse the repository at this point in the history
Fix #9080

Example, where `[]` is a 2 byte non-breaking space:
```
def f():
    """ Docstring header
^^^^ Real indentation is 4 chars
      docstring body, over-indented
^^^^^^ Over-indentation is 6 - 4 = 2 chars due to this line
   [] []  docstring body 2, further indented
^^^^^ We take these 4 chars/5 bytes to match the docstring ...
     ^^^ ... and these 2 chars/3 bytes to remove the `over_indented_size` ...
        ^^ ... but preserve this real indent
```
  • Loading branch information
konstin authored Dec 15, 2023
1 parent cd3c2f7 commit 82731b8
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 5 deletions.
9 changes: 8 additions & 1 deletion crates/ruff_linter/resources/test/fixtures/pydocstyle/D.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,5 +713,12 @@ def retain_extra_whitespace_not_overindented():
This is not overindented
This is overindented, but since one line is not overindented this should not raise
And so is this, but it we should preserve the extra space on this line relative
And so is this, but it we should preserve the extra space on this line relative
"""


def inconsistent_indent_byte_size():
"""There's a non-breaking space (2-bytes) after 3 spaces (https://github.com/astral-sh/ruff/issues/9080).
    Returns:
"""
18 changes: 15 additions & 3 deletions crates/ruff_linter/src/rules/pydocstyle/rules/indent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,26 @@ pub(crate) fn indent(checker: &mut Checker, docstring: &Docstring) {
Edit::range_deletion(TextRange::at(line.start(), line_indent.text_len()))
} else {
// Convert the character count to an offset within the source.
// Example, where `[]` is a 2 byte non-breaking space:
// ```
// def f():
// """ Docstring header
// ^^^^ Real indentation is 4 chars
// docstring body, over-indented
// ^^^^^^ Over-indentation is 6 - 4 = 2 chars due to this line
// [] [] docstring body 2, further indented
// ^^^^^ We take these 4 chars/5 bytes to match the docstring ...
// ^^^ ... and these 2 chars/3 bytes to remove the `over_indented_size` ...
// ^^ ... but preserve this real indent
// ```
let offset = checker
.locator()
.after(line.start() + indent.text_len())
.after(line.start())
.chars()
.take(over_indented_size)
.take(docstring.indentation.chars().count() + over_indented_size)
.map(TextLen::text_len)
.sum::<TextSize>();
let range = TextRange::at(line.start(), indent.text_len() + offset);
let range = TextRange::at(line.start(), offset);
Edit::range_replacement(indent, range)
};
diagnostic.set_fix(Fix::safe_edit(edit));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,4 +411,22 @@ D.py:707:1: D208 [*] Docstring is over-indented
709 709 |
710 710 |

D.py:723:1: D208 [*] Docstring is over-indented
|
721 | """There's a non-breaking space (2-bytes) after 3 spaces (https://github.com/astral-sh/ruff/issues/9080).
722 |
723 |     Returns:
| D208
724 | """
|
= help: Remove over-indentation

Safe fix
720 720 | def inconsistent_indent_byte_size():
721 721 | """There's a non-breaking space (2-bytes) after 3 spaces (https://github.com/astral-sh/ruff/issues/9080).
722 722 |
723 |-     Returns:
723 |+ Returns:
724 724 | """
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ D.py:712:5: D213 [*] Multi-line docstring summary should start at the second lin
713 | |
714 | | This is not overindented
715 | | This is overindented, but since one line is not overindented this should not raise
716 | | And so is this, but it we should preserve the extra space on this line relative
716 | | And so is this, but it we should preserve the extra space on this line relative
717 | | """
| |_______^ D213
|
Expand All @@ -679,4 +679,27 @@ D.py:712:5: D213 [*] Multi-line docstring summary should start at the second lin
714 715 | This is not overindented
715 716 | This is overindented, but since one line is not overindented this should not raise

D.py:721:5: D213 [*] Multi-line docstring summary should start at the second line
|
720 | def inconsistent_indent_byte_size():
721 | """There's a non-breaking space (2-bytes) after 3 spaces (https://github.com/astral-sh/ruff/issues/9080).
| _____^
722 | |
723 | |     Returns:
724 | | """
| |_______^ D213
|
= help: Insert line break and indentation after opening quotes

Safe fix
718 718 |
719 719 |
720 720 | def inconsistent_indent_byte_size():
721 |- """There's a non-breaking space (2-bytes) after 3 spaces (https://github.com/astral-sh/ruff/issues/9080).
721 |+ """
722 |+ There's a non-breaking space (2-bytes) after 3 spaces (https://github.com/astral-sh/ruff/issues/9080).
722 723 |
723 724 |     Returns:
724 725 | """


0 comments on commit 82731b8

Please sign in to comment.