Skip to content

Commit

Permalink
Ignore trailing quotes for unclosed l-brace errors
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Jan 4, 2024
1 parent 9a14f40 commit 6a81eb3
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 21 deletions.
45 changes: 35 additions & 10 deletions crates/ruff_python_parser/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,15 +700,15 @@ impl<'source> Lexer<'source> {
}
Some('\r' | '\n') if !triple_quoted => {
if let Some(fstring) = self.fstrings.current() {
// When we are in an f-string, check whether does the initial quote
// When we are in an f-string, check whether the initial quote
// matches with f-strings quotes and if it is, then this must be a
// missing '}' token so raise the proper error.
if fstring.quote_char() == quote && !fstring.is_triple_quoted() {
return Err(LexicalError {
error: LexicalErrorType::FStringError(
FStringErrorType::UnclosedLbrace,
),
location: self.offset() - fstring.quote_size(),
location: self.offset() - TextSize::new(1),
});
}
}
Expand All @@ -732,7 +732,7 @@ impl<'source> Lexer<'source> {
Some(_) => {}
None => {
if let Some(fstring) = self.fstrings.current() {
// When we are in an f-string, check whether does the initial quote
// When we are in an f-string, check whether the initial quote
// matches with f-strings quotes and if it is, then this must be a
// missing '}' token so raise the proper error.
if fstring.quote_char() == quote
Expand All @@ -742,7 +742,7 @@ impl<'source> Lexer<'source> {
error: LexicalErrorType::FStringError(
FStringErrorType::UnclosedLbrace,
),
location: self.offset() - fstring.quote_size(),
location: self.offset(),
});
}
}
Expand Down Expand Up @@ -2195,13 +2195,17 @@ f"{(lambda x:{x})}"
assert_debug_snapshot!(lex_jupyter_source(source));
}

fn lex_error(source: &str) -> LexicalError {
match lex(source, Mode::Module).find_map(Result::err) {
Some(err) => err,
_ => panic!("Expected at least one error"),
}
}

fn lex_fstring_error(source: &str) -> FStringErrorType {
match lex(source, Mode::Module).find_map(std::result::Result::err) {
Some(err) => match err.error {
LexicalErrorType::FStringError(error) => error,
_ => panic!("Expected FStringError: {err:?}"),
},
_ => panic!("Expected atleast one FStringError"),
match lex_error(source).error {
LexicalErrorType::FStringError(error) => error,
err => panic!("Expected FStringError: {err:?}"),
}
}

Expand Down Expand Up @@ -2246,4 +2250,25 @@ f"{(lambda x:{x})}"
UnterminatedTripleQuotedString
);
}

#[test]
fn test_fstring_error_location() {
assert_debug_snapshot!(lex_error("f'{'"), @r###"
LexicalError {
error: FStringError(
UnclosedLbrace,
),
location: 4,
}
"###);

assert_debug_snapshot!(lex_error("f'{'α"), @r###"
LexicalError {
error: FStringError(
UnclosedLbrace,
),
location: 6,
}
"###);
}
}
11 changes: 0 additions & 11 deletions crates/ruff_python_parser/src/lexer/fstring.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use bitflags::bitflags;

use ruff_text_size::TextSize;

bitflags! {
#[derive(Debug)]
pub(crate) struct FStringContextFlags: u8 {
Expand Down Expand Up @@ -58,15 +56,6 @@ impl FStringContext {
}
}

/// Returns the number of quotes for the current f-string.
pub(crate) const fn quote_size(&self) -> TextSize {
if self.is_triple_quoted() {
TextSize::new(3)
} else {
TextSize::new(1)
}
}

/// Returns the triple quotes for the current f-string if it is a triple-quoted
/// f-string, `None` otherwise.
pub(crate) const fn triple_quotes(&self) -> Option<&'static str> {
Expand Down

0 comments on commit 6a81eb3

Please sign in to comment.