Fix panic in D208 with multibyte indent (#9147)

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
```
This commit is contained in:
konsti 2023-12-15 18:02:15 +01:00 committed by GitHub
parent cd3c2f773f
commit 82731b8194
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 5 deletions

View file

@ -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:
"""

View file

@ -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));

View file

@ -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 | """

View file

@ -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
|
@ -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 | """