Skip to content

Commit

Permalink
Escaped single-quote docsting within single-quote docstring
Browse files Browse the repository at this point in the history
  • Loading branch information
ukyen8 committed Jul 12, 2024
1 parent e09ffe4 commit 0d94f8e
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 24 deletions.
42 changes: 35 additions & 7 deletions crates/ruff_linter/resources/test/fixtures/pydocstyle/D301.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,59 @@ def shouldnt_add_raw_here2():
u"Sum\\mary."


def shouldnt_add_raw_for_docstring_contains_docstring():
def shouldnt_add_raw_for_double_quote_docstring_contains_docstring():
"""
This docstring contains another docstring.
This docstring contains another double-quote docstring.
def foo():
\"\"\"Foo.\"\"\"
"""


def shouldnt_add_raw_for_docstring_contains_docstring2():
def shouldnt_add_raw_for_double_quote_docstring_contains_docstring2():
"""
This docstring contains another docstring.
This docstring contains another double-quote docstring.
def bar():
\"""Bar.\"""
"""


def shouldnt_add_raw_for_docstring_contains_escaped_triple_quotes():
def shouldnt_add_raw_for_single_quote_docstring_contains_docstring():
'''
This docstring contains another single-quote docstring.
def foo():
\'\'\'Foo.\'\'\'
'''


def shouldnt_add_raw_for_single_quote_docstring_contains_docstring2():
'''
This docstring contains another single-quote docstring.
def bar():
\'''Bar.\'''
'''

def shouldnt_add_raw_for_docstring_contains_escaped_double_triple_quotes():
"""
Escaped triple quote \""" or \"\"\".
"""

def shouldnt_add_raw_for_docstring_contains_escaped_single_triple_quotes():
'''
Escaped triple quote \''' or \'\'\'.
'''


def should_add_raw_for_single_quote_escape():
def should_add_raw_for_single_double_quote_escape():
"""
This is single quote escape \".
"""
"""


def should_add_raw_for_single_single_quote_escape():
'''
This is single quote escape \'.
'''
14 changes: 9 additions & 5 deletions crates/ruff_linter/src/rules/pydocstyle/rules/backslashes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,28 @@ pub(crate) fn backslashes(checker: &mut Checker, docstring: &Docstring) {
let body = docstring.body();
let bytes = body.as_bytes();
let mut backslash_index = 0;
let escaped_docstring_backslashes_pattern = b"\"\\\"\\\"";
let double_quote_docstring_backslashes_pattern = b"\"\\\"\\\"";
let single_quote_docstring_backslashes_pattern = b"\'\\\'\\\'";
if memchr_iter(b'\\', bytes).any(|position| {
let escaped_char = bytes.get(position.saturating_add(1));
// Allow escaped docstring.
if matches!(escaped_char, Some(b'"')) {
// If the next chars is equal to `"""`, it is a escaped docstring pattern.
if matches!(escaped_char, Some(b'"' | b'\'')) {
// If the next three characters are equal to """, it indicates an escaped docstring pattern.
let escaped_triple_quotes =
&bytes[position.saturating_add(1)..position.saturating_add(4)];
if escaped_triple_quotes == b"\"\"\"" {
if escaped_triple_quotes == b"\"\"\"" || escaped_triple_quotes == b"\'\'\'" {
return false;
}

// For the `"\"\"` pattern, each iteration advances by 2 characters.
// For example, the sequence progresses from `"\"\"` to `"\"` and then to `"`.
// Therefore, we utilize an index to keep track of the remaining characters.
let escaped_quotes_backslashes = &bytes
[position.saturating_add(1)..position.saturating_add(6 - backslash_index * 2)];
if escaped_quotes_backslashes
== &escaped_docstring_backslashes_pattern[backslash_index * 2..]
== &double_quote_docstring_backslashes_pattern[backslash_index * 2..]
|| escaped_quotes_backslashes
== &single_quote_docstring_backslashes_pattern[backslash_index * 2..]
{
backslash_index += 1;
// Reset to avoid overflow.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,43 @@ D301.py:37:5: D301 Use `r"""` if any backslashes in a docstring
|
= help: Add `r` prefix

D301.py:65:5: D301 [*] Use `r"""` if any backslashes in a docstring
D301.py:87:5: D301 [*] Use `r"""` if any backslashes in a docstring
|
64 | def should_add_raw_for_single_quote_escape():
65 | """
86 | def should_add_raw_for_single_double_quote_escape():
87 | """
| _____^
66 | | This is single quote escape \".
67 | | """
88 | | This is single quote escape \".
89 | | """
| |_______^ D301
|
= help: Add `r` prefix

Unsafe fix
62 62 |
63 63 |
64 64 | def should_add_raw_for_single_quote_escape():
65 |- """
65 |+ r"""
66 66 | This is single quote escape \".
67 67 | """
84 84 |
85 85 |
86 86 | def should_add_raw_for_single_double_quote_escape():
87 |- """
87 |+ r"""
88 88 | This is single quote escape \".
89 89 | """
90 90 |

D301.py:93:5: D301 [*] Use `r"""` if any backslashes in a docstring
|
92 | def should_add_raw_for_single_single_quote_escape():
93 | '''
| _____^
94 | | This is single quote escape \'.
95 | | '''
| |_______^ D301
|
= help: Add `r` prefix

Unsafe fix
90 90 |
91 91 |
92 92 | def should_add_raw_for_single_single_quote_escape():
93 |- '''
93 |+ r'''
94 94 | This is single quote escape \'.
95 95 | '''

0 comments on commit 0d94f8e

Please sign in to comment.