mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-25 05:53:51 +00:00
Add syntax error when conversion flag does not immediately follow exclamation mark (#18706)
Closes #18671 Note that while this has, I believe, always been invalid syntax, it was reported as a different syntax error until Python 3.12: Python 3.11: ```pycon >>> x = 1 >>> f"{x! s}" File "<stdin>", line 1 f"{x! s}" ^ SyntaxError: f-string: invalid conversion character: expected 's', 'r', or 'a' ``` Python 3.12: ```pycon >>> x = 1 >>> f"{x! s}" File "<stdin>", line 1 f"{x! s}" ^^^ SyntaxError: f-string: conversion type must come right after the exclamanation mark ```
This commit is contained in:
parent
a842899862
commit
c5b58187da
8 changed files with 219 additions and 38 deletions
|
@ -63,13 +63,16 @@ pub enum InterpolatedStringErrorType {
|
|||
UnterminatedTripleQuotedString,
|
||||
/// A lambda expression without parentheses was encountered.
|
||||
LambdaWithoutParentheses,
|
||||
/// Conversion flag does not immediately follow exclamation.
|
||||
ConversionFlagNotImmediatelyAfterExclamation,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for InterpolatedStringErrorType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
use InterpolatedStringErrorType::{
|
||||
InvalidConversionFlag, LambdaWithoutParentheses, SingleRbrace, UnclosedLbrace,
|
||||
UnterminatedString, UnterminatedTripleQuotedString,
|
||||
ConversionFlagNotImmediatelyAfterExclamation, InvalidConversionFlag,
|
||||
LambdaWithoutParentheses, SingleRbrace, UnclosedLbrace, UnterminatedString,
|
||||
UnterminatedTripleQuotedString,
|
||||
};
|
||||
match self {
|
||||
UnclosedLbrace => write!(f, "expecting '}}'"),
|
||||
|
@ -80,6 +83,10 @@ impl std::fmt::Display for InterpolatedStringErrorType {
|
|||
LambdaWithoutParentheses => {
|
||||
write!(f, "lambda expressions are not allowed without parentheses")
|
||||
}
|
||||
ConversionFlagNotImmediatelyAfterExclamation => write!(
|
||||
f,
|
||||
"conversion type must come right after the exclamation mark"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1771,6 +1771,19 @@ impl<'src> Parser<'src> {
|
|||
let conversion = if self.eat(TokenKind::Exclamation) {
|
||||
let conversion_flag_range = self.current_token_range();
|
||||
if self.at(TokenKind::Name) {
|
||||
// test_err f_string_conversion_follows_exclamation
|
||||
// f"{x! s}"
|
||||
// t"{x! s}"
|
||||
// f"{x! z}"
|
||||
if self.prev_token_end != conversion_flag_range.start() {
|
||||
self.add_error(
|
||||
ParseErrorType::from_interpolated_string_error(
|
||||
InterpolatedStringErrorType::ConversionFlagNotImmediatelyAfterExclamation,
|
||||
string_kind,
|
||||
),
|
||||
TextRange::new(self.prev_token_end, conversion_flag_range.start()),
|
||||
);
|
||||
}
|
||||
let TokenValue::Name(name) = self.bump_value(TokenKind::Name) else {
|
||||
unreachable!();
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue