1
1
use ruff_diagnostics:: { AlwaysFixableViolation , Diagnostic , Edit , Fix } ;
2
2
use ruff_macros:: { derive_message_formats, violation} ;
3
- use ruff_python_ast:: str:: { is_triple_quote, leading_quote} ;
4
3
use ruff_python_parser:: lexer:: LexResult ;
5
4
use ruff_python_parser:: Tok ;
6
5
use ruff_source_file:: Locator ;
@@ -158,7 +157,7 @@ pub(crate) fn avoidable_escaped_quote(
158
157
// ```python
159
158
// f'"foo" {'nested'}"
160
159
// ```
161
- if matches ! ( tok, Tok :: String { .. } | Tok :: FStringStart ) {
160
+ if matches ! ( tok, Tok :: String { .. } | Tok :: FStringStart ( _ ) ) {
162
161
if let Some ( fstring_context) = fstrings. last_mut ( ) {
163
162
fstring_context. ignore_escaped_quotes ( ) ;
164
163
continue ;
@@ -170,16 +169,13 @@ pub(crate) fn avoidable_escaped_quote(
170
169
Tok :: String {
171
170
value : string_contents,
172
171
kind,
173
- triple_quoted,
174
172
} => {
175
- if kind. is_raw ( ) || * triple_quoted {
173
+ if kind. is_raw_string ( ) || kind . is_triple_quoted ( ) {
176
174
continue ;
177
175
}
178
176
179
177
// Check if we're using the preferred quotation style.
180
- if !leading_quote ( locator. slice ( tok_range) ) . is_some_and ( |text| {
181
- contains_quote ( text, quotes_settings. inline_quotes . as_char ( ) )
182
- } ) {
178
+ if Quote :: from ( kind. quote_style ( ) ) != quotes_settings. inline_quotes {
183
179
continue ;
184
180
}
185
181
@@ -192,7 +188,7 @@ pub(crate) fn avoidable_escaped_quote(
192
188
let mut diagnostic = Diagnostic :: new ( AvoidableEscapedQuote , tok_range) ;
193
189
let fixed_contents = format ! (
194
190
"{prefix}{quote}{value}{quote}" ,
195
- prefix = kind. as_str ( ) ,
191
+ prefix = kind. prefix_str ( ) ,
196
192
quote = quotes_settings. inline_quotes. opposite( ) . as_char( ) ,
197
193
value = unescape_string(
198
194
string_contents,
@@ -206,12 +202,11 @@ pub(crate) fn avoidable_escaped_quote(
206
202
diagnostics. push ( diagnostic) ;
207
203
}
208
204
}
209
- Tok :: FStringStart => {
210
- let text = locator. slice ( tok_range) ;
205
+ Tok :: FStringStart ( kind) => {
211
206
// Check for escaped quote only if we're using the preferred quotation
212
207
// style and it isn't a triple-quoted f-string.
213
- let check_for_escaped_quote = !is_triple_quote ( text )
214
- && contains_quote ( text , quotes_settings . inline_quotes . as_char ( ) ) ;
208
+ let check_for_escaped_quote = !kind . is_triple_quoted ( )
209
+ && Quote :: from ( kind . quote_style ( ) ) == quotes_settings . inline_quotes ;
215
210
fstrings. push ( FStringContext :: new (
216
211
check_for_escaped_quote,
217
212
tok_range,
@@ -220,9 +215,8 @@ pub(crate) fn avoidable_escaped_quote(
220
215
}
221
216
Tok :: FStringMiddle {
222
217
value : string_contents,
223
- is_raw,
224
- triple_quoted : _,
225
- } if !is_raw => {
218
+ kind,
219
+ } if !kind. is_raw_string ( ) => {
226
220
let Some ( context) = fstrings. last_mut ( ) else {
227
221
continue ;
228
222
} ;
@@ -315,25 +309,20 @@ pub(crate) fn unnecessary_escaped_quote(
315
309
Tok :: String {
316
310
value : string_contents,
317
311
kind,
318
- triple_quoted,
319
312
} => {
320
- if kind. is_raw ( ) || * triple_quoted {
313
+ if kind. is_raw_string ( ) || kind . is_triple_quoted ( ) {
321
314
continue ;
322
315
}
323
316
324
- let leading = match leading_quote ( locator. slice ( tok_range) ) {
325
- Some ( "\" " ) => Quote :: Double ,
326
- Some ( "'" ) => Quote :: Single ,
327
- _ => continue ,
328
- } ;
317
+ let leading = kind. quote_style ( ) ;
329
318
if !contains_escaped_quote ( string_contents, leading. opposite ( ) . as_char ( ) ) {
330
319
continue ;
331
320
}
332
321
333
322
let mut diagnostic = Diagnostic :: new ( UnnecessaryEscapedQuote , tok_range) ;
334
323
let fixed_contents = format ! (
335
324
"{prefix}{quote}{value}{quote}" ,
336
- prefix = kind. as_str ( ) ,
325
+ prefix = kind. prefix_str ( ) ,
337
326
quote = leading. as_char( ) ,
338
327
value = unescape_string( string_contents, leading. opposite( ) . as_char( ) )
339
328
) ;
@@ -343,16 +332,11 @@ pub(crate) fn unnecessary_escaped_quote(
343
332
) ) ) ;
344
333
diagnostics. push ( diagnostic) ;
345
334
}
346
- Tok :: FStringStart => {
347
- let text = locator. slice ( tok_range) ;
335
+ Tok :: FStringStart ( kind) => {
348
336
// Check for escaped quote only if we're using the preferred quotation
349
337
// style and it isn't a triple-quoted f-string.
350
- let check_for_escaped_quote = !is_triple_quote ( text) ;
351
- let quote_style = if contains_quote ( text, Quote :: Single . as_char ( ) ) {
352
- Quote :: Single
353
- } else {
354
- Quote :: Double
355
- } ;
338
+ let check_for_escaped_quote = !kind. is_triple_quoted ( ) ;
339
+ let quote_style = Quote :: from ( kind. quote_style ( ) ) ;
356
340
fstrings. push ( FStringContext :: new (
357
341
check_for_escaped_quote,
358
342
tok_range,
@@ -361,9 +345,8 @@ pub(crate) fn unnecessary_escaped_quote(
361
345
}
362
346
Tok :: FStringMiddle {
363
347
value : string_contents,
364
- is_raw,
365
- triple_quoted : _,
366
- } if !is_raw => {
348
+ kind,
349
+ } if !kind. is_raw_string ( ) => {
367
350
let Some ( context) = fstrings. last_mut ( ) else {
368
351
continue ;
369
352
} ;
0 commit comments