mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 10:22:24 +00:00
Fix invalid printer IR error (#5422)
This commit is contained in:
parent
ca5e10b5ea
commit
38189ed913
4 changed files with 70 additions and 18 deletions
|
@ -108,3 +108,13 @@ test_particular = [
|
||||||
'1.0000000000000000000000000000000000000000000010000' #...
|
'1.0000000000000000000000000000000000000000000010000' #...
|
||||||
'0000000000000000000000000000000000000000025',
|
'0000000000000000000000000000000000000000025',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Parenthesized string continuation with messed up indentation
|
||||||
|
{
|
||||||
|
"key": (
|
||||||
|
[],
|
||||||
|
'a'
|
||||||
|
'b'
|
||||||
|
'c'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -242,6 +242,7 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn finish(&mut self) -> FormatResult<()> {
|
pub(crate) fn finish(&mut self) -> FormatResult<()> {
|
||||||
|
self.result.and_then(|_| {
|
||||||
if let Some(last_end) = self.last_end.take() {
|
if let Some(last_end) = self.last_end.take() {
|
||||||
if_group_breaks(&text(",")).fmt(self.fmt)?;
|
if_group_breaks(&text(",")).fmt(self.fmt)?;
|
||||||
|
|
||||||
|
@ -259,6 +260,7 @@ impl<'fmt, 'ast, 'buf> JoinCommaSeparatedBuilder<'fmt, 'ast, 'buf> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ruff_formatter::{format_args, write, FormatError};
|
||||||
use ruff_python_ast::str::is_implicit_concatenation;
|
use ruff_python_ast::str::is_implicit_concatenation;
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
use rustpython_parser::ast::{ExprConstant, Ranged};
|
use rustpython_parser::ast::{ExprConstant, Ranged};
|
||||||
use rustpython_parser::lexer::lex_starts_at;
|
use rustpython_parser::lexer::{lex_starts_at, LexicalError, LexicalErrorType};
|
||||||
use rustpython_parser::{Mode, Tok};
|
use rustpython_parser::{Mode, Tok};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ impl Format<PyFormatContext<'_>> for FormatStringContinuation<'_> {
|
||||||
// Call into the lexer to extract the individual chunks and format each string on its own.
|
// Call into the lexer to extract the individual chunks and format each string on its own.
|
||||||
// This code does not yet implement the automatic joining of strings that fit on the same line
|
// This code does not yet implement the automatic joining of strings that fit on the same line
|
||||||
// because this is a black preview style.
|
// because this is a black preview style.
|
||||||
let lexer = lex_starts_at(string_content, Mode::Module, string_range.start());
|
let lexer = lex_starts_at(string_content, Mode::Expression, string_range.start());
|
||||||
|
|
||||||
let separator = format_with(|f| match self.layout {
|
let separator = format_with(|f| match self.layout {
|
||||||
StringLayout::Default(_) => soft_line_break_or_space().fmt(f),
|
StringLayout::Default(_) => soft_line_break_or_space().fmt(f),
|
||||||
|
@ -93,7 +93,31 @@ impl Format<PyFormatContext<'_>> for FormatStringContinuation<'_> {
|
||||||
let mut joiner = f.join_with(separator);
|
let mut joiner = f.join_with(separator);
|
||||||
|
|
||||||
for token in lexer {
|
for token in lexer {
|
||||||
let (token, token_range) = token.map_err(|_| FormatError::SyntaxError)?;
|
let (token, token_range) = match token {
|
||||||
|
Ok(spanned) => spanned,
|
||||||
|
Err(LexicalError {
|
||||||
|
error: LexicalErrorType::IndentationError,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
// This can happen if the string continuation appears anywhere inside of a parenthesized expression
|
||||||
|
// because the lexer doesn't know about the parentheses. For example, the following snipped triggers an Indentation error
|
||||||
|
// ```python
|
||||||
|
// {
|
||||||
|
// "key": (
|
||||||
|
// [],
|
||||||
|
// 'a'
|
||||||
|
// 'b'
|
||||||
|
// 'c'
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
// Ignoring the error here is *safe* because we know that the program once parsed to a valid AST.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Err(FormatError::SyntaxError);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match token {
|
match token {
|
||||||
Tok::String { .. } => {
|
Tok::String { .. } => {
|
||||||
|
|
|
@ -114,6 +114,16 @@ test_particular = [
|
||||||
'1.0000000000000000000000000000000000000000000010000' #...
|
'1.0000000000000000000000000000000000000000000010000' #...
|
||||||
'0000000000000000000000000000000000000000025',
|
'0000000000000000000000000000000000000000025',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Parenthesized string continuation with messed up indentation
|
||||||
|
{
|
||||||
|
"key": (
|
||||||
|
[],
|
||||||
|
'a'
|
||||||
|
'b'
|
||||||
|
'c'
|
||||||
|
)
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
@ -259,6 +269,9 @@ test_particular = [
|
||||||
"1.0000000000000000000000000000000000000000000010000" # ...
|
"1.0000000000000000000000000000000000000000000010000" # ...
|
||||||
"0000000000000000000000000000000000000000025",
|
"0000000000000000000000000000000000000000025",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Parenthesized string continuation with messed up indentation
|
||||||
|
{"key": ([], "a" "b" "c")}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -404,6 +417,9 @@ test_particular = [
|
||||||
'1.0000000000000000000000000000000000000000000010000' # ...
|
'1.0000000000000000000000000000000000000000000010000' # ...
|
||||||
'0000000000000000000000000000000000000000025',
|
'0000000000000000000000000000000000000000025',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Parenthesized string continuation with messed up indentation
|
||||||
|
{'key': ([], 'a' 'b' 'c')}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue