mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 22:31:23 +00:00
Correct quick fix message for W605
(#8255)
## Summary This PR fixes the `W605` rule implementation to provide the quickfix message as per the fix provided. ## Test Plan Update snapshots. fixes: #8155
This commit is contained in:
parent
a4dd1e5fad
commit
4ffd4ed61f
4 changed files with 88 additions and 38 deletions
|
@ -5,7 +5,7 @@ use ruff_macros::{derive_message_formats, violation};
|
|||
use ruff_python_index::Indexer;
|
||||
use ruff_python_parser::Tok;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::fix::edits::pad_start;
|
||||
|
||||
|
@ -25,23 +25,51 @@ use crate::fix::edits::pad_start;
|
|||
/// regex = r"\.png$"
|
||||
/// ```
|
||||
///
|
||||
/// Or, if the string already contains a valid escape sequence:
|
||||
/// ```python
|
||||
/// value = "new line\nand invalid escape \_ here"
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// value = "new line\nand invalid escape \\_ here"
|
||||
/// ```
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: String and Bytes literals](https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals)
|
||||
#[violation]
|
||||
pub struct InvalidEscapeSequence(char);
|
||||
pub struct InvalidEscapeSequence {
|
||||
ch: char,
|
||||
fix_title: FixTitle,
|
||||
}
|
||||
|
||||
impl AlwaysFixableViolation for InvalidEscapeSequence {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
let InvalidEscapeSequence(char) = self;
|
||||
format!("Invalid escape sequence: `\\{char}`")
|
||||
let InvalidEscapeSequence { ch, .. } = self;
|
||||
format!("Invalid escape sequence: `\\{ch}`")
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> String {
|
||||
"Add backslash to escape sequence".to_string()
|
||||
match self.fix_title {
|
||||
FixTitle::AddBackslash => format!("Add backslash to escape sequence"),
|
||||
FixTitle::UseRawStringLiteral => format!("Use a raw string literal"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum FixTitle {
|
||||
AddBackslash,
|
||||
UseRawStringLiteral,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct InvalidEscapeChar {
|
||||
ch: char,
|
||||
range: TextRange,
|
||||
}
|
||||
|
||||
/// W605
|
||||
pub(crate) fn invalid_escape_sequence(
|
||||
diagnostics: &mut Vec<Diagnostic>,
|
||||
|
@ -67,7 +95,7 @@ pub(crate) fn invalid_escape_sequence(
|
|||
};
|
||||
|
||||
let mut contains_valid_escape_sequence = false;
|
||||
let mut invalid_escape_sequence = Vec::new();
|
||||
let mut invalid_escape_chars = Vec::new();
|
||||
|
||||
let mut prev = None;
|
||||
let bytes = token_source_code.as_bytes();
|
||||
|
@ -154,16 +182,28 @@ pub(crate) fn invalid_escape_sequence(
|
|||
|
||||
let location = token_range.start() + TextSize::try_from(i).unwrap();
|
||||
let range = TextRange::at(location, next_char.text_len() + TextSize::from(1));
|
||||
invalid_escape_sequence.push(Diagnostic::new(InvalidEscapeSequence(next_char), range));
|
||||
invalid_escape_chars.push(InvalidEscapeChar {
|
||||
ch: next_char,
|
||||
range,
|
||||
});
|
||||
}
|
||||
|
||||
let mut invalid_escape_sequence = Vec::new();
|
||||
if contains_valid_escape_sequence {
|
||||
// Escape with backslash.
|
||||
for diagnostic in &mut invalid_escape_sequence {
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::insertion(
|
||||
for invalid_escape_char in &invalid_escape_chars {
|
||||
let diagnostic = Diagnostic::new(
|
||||
InvalidEscapeSequence {
|
||||
ch: invalid_escape_char.ch,
|
||||
fix_title: FixTitle::AddBackslash,
|
||||
},
|
||||
invalid_escape_char.range,
|
||||
)
|
||||
.with_fix(Fix::safe_edit(Edit::insertion(
|
||||
r"\".to_string(),
|
||||
diagnostic.start() + TextSize::from(1),
|
||||
invalid_escape_char.range.start() + TextSize::from(1),
|
||||
)));
|
||||
invalid_escape_sequence.push(diagnostic);
|
||||
}
|
||||
} else {
|
||||
let tok_start = if token.is_f_string_middle() {
|
||||
|
@ -178,14 +218,24 @@ pub(crate) fn invalid_escape_sequence(
|
|||
token_range.start()
|
||||
};
|
||||
// Turn into raw string.
|
||||
for diagnostic in &mut invalid_escape_sequence {
|
||||
// If necessary, add a space between any leading keyword (`return`, `yield`,
|
||||
// `assert`, etc.) and the string. For example, `return"foo"` is valid, but
|
||||
// `returnr"foo"` is not.
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::insertion(
|
||||
pad_start("r".to_string(), tok_start, locator),
|
||||
tok_start,
|
||||
)));
|
||||
for invalid_escape_char in &invalid_escape_chars {
|
||||
let diagnostic = Diagnostic::new(
|
||||
InvalidEscapeSequence {
|
||||
ch: invalid_escape_char.ch,
|
||||
fix_title: FixTitle::UseRawStringLiteral,
|
||||
},
|
||||
invalid_escape_char.range,
|
||||
)
|
||||
.with_fix(
|
||||
// If necessary, add a space between any leading keyword (`return`, `yield`,
|
||||
// `assert`, etc.) and the string. For example, `return"foo"` is valid, but
|
||||
// `returnr"foo"` is not.
|
||||
Fix::safe_edit(Edit::insertion(
|
||||
pad_start("r".to_string(), tok_start, locator),
|
||||
tok_start,
|
||||
)),
|
||||
);
|
||||
invalid_escape_sequence.push(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ W605_0.py:2:10: W605 [*] Invalid escape sequence: `\.`
|
|||
3 |
|
||||
4 | #: W605:2:1
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
1 1 | #: W605:1:10
|
||||
|
@ -27,7 +27,7 @@ W605_0.py:6:1: W605 [*] Invalid escape sequence: `\.`
|
|||
| ^^ W605
|
||||
7 | '''
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
2 2 | regex = '\.png$'
|
||||
|
@ -47,7 +47,7 @@ W605_0.py:11:6: W605 [*] Invalid escape sequence: `\_`
|
|||
| ^^ W605
|
||||
12 | )
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
8 8 |
|
||||
|
@ -68,7 +68,7 @@ W605_0.py:18:6: W605 [*] Invalid escape sequence: `\_`
|
|||
19 | in the middle
|
||||
20 | """
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
12 12 | )
|
||||
|
@ -107,7 +107,7 @@ W605_0.py:28:12: W605 [*] Invalid escape sequence: `\.`
|
|||
29 |
|
||||
30 | #: Okay
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
25 25 |
|
||||
|
|
|
@ -9,7 +9,7 @@ W605_1.py:2:10: W605 [*] Invalid escape sequence: `\.`
|
|||
3 |
|
||||
4 | #: W605:2:1
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
1 1 | #: W605:1:10
|
||||
|
@ -27,7 +27,7 @@ W605_1.py:6:1: W605 [*] Invalid escape sequence: `\.`
|
|||
| ^^ W605
|
||||
7 | '''
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
2 2 | regex = '\.png$'
|
||||
|
@ -47,7 +47,7 @@ W605_1.py:11:6: W605 [*] Invalid escape sequence: `\_`
|
|||
| ^^ W605
|
||||
12 | )
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
8 8 |
|
||||
|
@ -68,7 +68,7 @@ W605_1.py:18:6: W605 [*] Invalid escape sequence: `\_`
|
|||
19 | in the middle
|
||||
20 | """
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
12 12 | )
|
||||
|
@ -89,7 +89,7 @@ W605_1.py:25:12: W605 [*] Invalid escape sequence: `\.`
|
|||
26 |
|
||||
27 | #: Okay
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
22 22 |
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
source: crates/ruff/src/rules/pycodestyle/mod.rs
|
||||
source: crates/ruff_linter/src/rules/pycodestyle/mod.rs
|
||||
---
|
||||
W605_2.py:4:11: W605 [*] Invalid escape sequence: `\.`
|
||||
|
|
||||
|
@ -9,7 +9,7 @@ W605_2.py:4:11: W605 [*] Invalid escape sequence: `\.`
|
|||
5 |
|
||||
6 | #: W605:2:1
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
1 1 | # Same as `W605_0.py` but using f-strings instead.
|
||||
|
@ -29,7 +29,7 @@ W605_2.py:8:1: W605 [*] Invalid escape sequence: `\.`
|
|||
| ^^ W605
|
||||
9 | '''
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
4 4 | regex = f'\.png$'
|
||||
|
@ -49,7 +49,7 @@ W605_2.py:13:7: W605 [*] Invalid escape sequence: `\_`
|
|||
| ^^ W605
|
||||
14 | )
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
10 10 |
|
||||
|
@ -70,7 +70,7 @@ W605_2.py:20:6: W605 [*] Invalid escape sequence: `\_`
|
|||
21 | in the middle
|
||||
22 | """
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
14 14 | )
|
||||
|
@ -129,7 +129,7 @@ W605_2.py:44:11: W605 [*] Invalid escape sequence: `\{`
|
|||
45 | value = f'\{1}'
|
||||
46 | value = f'{1:\}'
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
41 41 | ''' # noqa
|
||||
|
@ -150,7 +150,7 @@ W605_2.py:45:11: W605 [*] Invalid escape sequence: `\{`
|
|||
46 | value = f'{1:\}'
|
||||
47 | value = f"{f"\{1}"}"
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
42 42 |
|
||||
|
@ -171,7 +171,7 @@ W605_2.py:46:14: W605 [*] Invalid escape sequence: `\}`
|
|||
47 | value = f"{f"\{1}"}"
|
||||
48 | value = rf"{f"\{1}"}"
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
43 43 | regex = f'\\\_'
|
||||
|
@ -191,7 +191,7 @@ W605_2.py:47:14: W605 [*] Invalid escape sequence: `\{`
|
|||
| ^^ W605
|
||||
48 | value = rf"{f"\{1}"}"
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
44 44 | value = f'\{{1}}'
|
||||
|
@ -212,7 +212,7 @@ W605_2.py:48:15: W605 [*] Invalid escape sequence: `\{`
|
|||
49 |
|
||||
50 | # Okay
|
||||
|
|
||||
= help: Add backslash to escape sequence
|
||||
= help: Use a raw string literal
|
||||
|
||||
ℹ Fix
|
||||
45 45 | value = f'\{1}'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue