mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-17 05:47:37 +00:00
Improved error recovery for unclosed strings (including f- and t-strings) (#20848)
This commit is contained in:
parent
a93618ed23
commit
4fc7dd300c
151 changed files with 1370 additions and 566 deletions
|
@ -1,10 +1,10 @@
|
||||||
# The lexer doesn't emit a string token if it's unterminated
|
# The lexer emits a string token if it's unterminated
|
||||||
"a" "b
|
"a" "b
|
||||||
"a" "b" "c
|
"a" "b" "c
|
||||||
"a" """b
|
"a" """b
|
||||||
c""" "d
|
c""" "d
|
||||||
|
|
||||||
# For f-strings, the `FStringRanges` won't contain the range for
|
# This is also true for
|
||||||
# unterminated f-strings.
|
# unterminated f-strings.
|
||||||
f"a" f"b
|
f"a" f"b
|
||||||
f"a" f"b" f"c
|
f"a" f"b" f"c
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff_linter/src/rules/flake8_implicit_str_concat/mod.rs
|
source: crates/ruff_linter/src/rules/flake8_implicit_str_concat/mod.rs
|
||||||
---
|
---
|
||||||
invalid-syntax: missing closing quote in string literal
|
ISC001 Implicitly concatenated string literals on one line
|
||||||
--> ISC_syntax_error.py:2:5
|
--> ISC_syntax_error.py:2:1
|
||||||
|
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
1 | # The lexer emits a string token if it's unterminated
|
||||||
2 | "a" "b
|
2 | "a" "b
|
||||||
| ^^
|
| ^^^^^^
|
||||||
3 | "a" "b" "c
|
3 | "a" "b" "c
|
||||||
4 | "a" """b
|
4 | "a" """b
|
||||||
|
|
|
|
||||||
|
help: Combine string literals
|
||||||
|
|
||||||
invalid-syntax: Expected a statement
|
invalid-syntax: missing closing quote in string literal
|
||||||
--> ISC_syntax_error.py:2:7
|
--> ISC_syntax_error.py:2:5
|
||||||
|
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
1 | # The lexer emits a string token if it's unterminated
|
||||||
2 | "a" "b
|
2 | "a" "b
|
||||||
| ^
|
| ^^
|
||||||
3 | "a" "b" "c
|
3 | "a" "b" "c
|
||||||
4 | "a" """b
|
4 | "a" """b
|
||||||
|
|
|
|
||||||
|
@ -24,7 +25,7 @@ invalid-syntax: Expected a statement
|
||||||
ISC001 Implicitly concatenated string literals on one line
|
ISC001 Implicitly concatenated string literals on one line
|
||||||
--> ISC_syntax_error.py:3:1
|
--> ISC_syntax_error.py:3:1
|
||||||
|
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
1 | # The lexer emits a string token if it's unterminated
|
||||||
2 | "a" "b
|
2 | "a" "b
|
||||||
3 | "a" "b" "c
|
3 | "a" "b" "c
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
|
@ -33,24 +34,25 @@ ISC001 Implicitly concatenated string literals on one line
|
||||||
|
|
|
|
||||||
help: Combine string literals
|
help: Combine string literals
|
||||||
|
|
||||||
invalid-syntax: missing closing quote in string literal
|
ISC001 Implicitly concatenated string literals on one line
|
||||||
--> ISC_syntax_error.py:3:9
|
--> ISC_syntax_error.py:3:5
|
||||||
|
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
1 | # The lexer emits a string token if it's unterminated
|
||||||
2 | "a" "b
|
2 | "a" "b
|
||||||
3 | "a" "b" "c
|
3 | "a" "b" "c
|
||||||
| ^^
|
| ^^^^^^
|
||||||
4 | "a" """b
|
4 | "a" """b
|
||||||
5 | c""" "d
|
5 | c""" "d
|
||||||
|
|
|
|
||||||
|
help: Combine string literals
|
||||||
|
|
||||||
invalid-syntax: Expected a statement
|
invalid-syntax: missing closing quote in string literal
|
||||||
--> ISC_syntax_error.py:3:11
|
--> ISC_syntax_error.py:3:9
|
||||||
|
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
1 | # The lexer emits a string token if it's unterminated
|
||||||
2 | "a" "b
|
2 | "a" "b
|
||||||
3 | "a" "b" "c
|
3 | "a" "b" "c
|
||||||
| ^
|
| ^^
|
||||||
4 | "a" """b
|
4 | "a" """b
|
||||||
5 | c""" "d
|
5 | c""" "d
|
||||||
|
|
|
|
||||||
|
@ -64,7 +66,21 @@ ISC001 Implicitly concatenated string literals on one line
|
||||||
5 | | c""" "d
|
5 | | c""" "d
|
||||||
| |____^
|
| |____^
|
||||||
6 |
|
6 |
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
7 | # This is also true for
|
||||||
|
|
|
||||||
|
help: Combine string literals
|
||||||
|
|
||||||
|
ISC001 Implicitly concatenated string literals on one line
|
||||||
|
--> ISC_syntax_error.py:4:5
|
||||||
|
|
|
||||||
|
2 | "a" "b
|
||||||
|
3 | "a" "b" "c
|
||||||
|
4 | "a" """b
|
||||||
|
| _____^
|
||||||
|
5 | | c""" "d
|
||||||
|
| |_______^
|
||||||
|
6 |
|
||||||
|
7 | # This is also true for
|
||||||
|
|
|
|
||||||
help: Combine string literals
|
help: Combine string literals
|
||||||
|
|
||||||
|
@ -76,24 +92,13 @@ invalid-syntax: missing closing quote in string literal
|
||||||
5 | c""" "d
|
5 | c""" "d
|
||||||
| ^^
|
| ^^
|
||||||
6 |
|
6 |
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
7 | # This is also true for
|
||||||
|
|
|
||||||
|
|
||||||
invalid-syntax: Expected a statement
|
|
||||||
--> ISC_syntax_error.py:5:8
|
|
||||||
|
|
|
||||||
3 | "a" "b" "c
|
|
||||||
4 | "a" """b
|
|
||||||
5 | c""" "d
|
|
||||||
| ^
|
|
||||||
6 |
|
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
|
||||||
|
|
|
|
||||||
|
|
||||||
invalid-syntax: f-string: unterminated string
|
invalid-syntax: f-string: unterminated string
|
||||||
--> ISC_syntax_error.py:9:8
|
--> ISC_syntax_error.py:9:8
|
||||||
|
|
|
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
7 | # This is also true for
|
||||||
8 | # unterminated f-strings.
|
8 | # unterminated f-strings.
|
||||||
9 | f"a" f"b
|
9 | f"a" f"b
|
||||||
| ^
|
| ^
|
||||||
|
@ -104,7 +109,7 @@ invalid-syntax: f-string: unterminated string
|
||||||
invalid-syntax: Expected FStringEnd, found newline
|
invalid-syntax: Expected FStringEnd, found newline
|
||||||
--> ISC_syntax_error.py:9:9
|
--> ISC_syntax_error.py:9:9
|
||||||
|
|
|
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
7 | # This is also true for
|
||||||
8 | # unterminated f-strings.
|
8 | # unterminated f-strings.
|
||||||
9 | f"a" f"b
|
9 | f"a" f"b
|
||||||
| ^
|
| ^
|
||||||
|
@ -183,14 +188,6 @@ invalid-syntax: f-string: unterminated triple-quoted string
|
||||||
| |__^
|
| |__^
|
||||||
|
|
|
|
||||||
|
|
||||||
invalid-syntax: unexpected EOF while parsing
|
|
||||||
--> ISC_syntax_error.py:30:1
|
|
||||||
|
|
|
||||||
28 | "i" "j"
|
|
||||||
29 | )
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
|
|
||||||
invalid-syntax: f-string: unterminated string
|
invalid-syntax: f-string: unterminated string
|
||||||
--> ISC_syntax_error.py:30:1
|
--> ISC_syntax_error.py:30:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,27 +4,17 @@ source: crates/ruff_linter/src/rules/flake8_implicit_str_concat/mod.rs
|
||||||
invalid-syntax: missing closing quote in string literal
|
invalid-syntax: missing closing quote in string literal
|
||||||
--> ISC_syntax_error.py:2:5
|
--> ISC_syntax_error.py:2:5
|
||||||
|
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
1 | # The lexer emits a string token if it's unterminated
|
||||||
2 | "a" "b
|
2 | "a" "b
|
||||||
| ^^
|
| ^^
|
||||||
3 | "a" "b" "c
|
3 | "a" "b" "c
|
||||||
4 | "a" """b
|
4 | "a" """b
|
||||||
|
|
|
|
||||||
|
|
||||||
invalid-syntax: Expected a statement
|
|
||||||
--> ISC_syntax_error.py:2:7
|
|
||||||
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
|
||||||
2 | "a" "b
|
|
||||||
| ^
|
|
||||||
3 | "a" "b" "c
|
|
||||||
4 | "a" """b
|
|
||||||
|
|
|
||||||
|
|
||||||
invalid-syntax: missing closing quote in string literal
|
invalid-syntax: missing closing quote in string literal
|
||||||
--> ISC_syntax_error.py:3:9
|
--> ISC_syntax_error.py:3:9
|
||||||
|
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
1 | # The lexer emits a string token if it's unterminated
|
||||||
2 | "a" "b
|
2 | "a" "b
|
||||||
3 | "a" "b" "c
|
3 | "a" "b" "c
|
||||||
| ^^
|
| ^^
|
||||||
|
@ -32,17 +22,6 @@ invalid-syntax: missing closing quote in string literal
|
||||||
5 | c""" "d
|
5 | c""" "d
|
||||||
|
|
|
|
||||||
|
|
||||||
invalid-syntax: Expected a statement
|
|
||||||
--> ISC_syntax_error.py:3:11
|
|
||||||
|
|
|
||||||
1 | # The lexer doesn't emit a string token if it's unterminated
|
|
||||||
2 | "a" "b
|
|
||||||
3 | "a" "b" "c
|
|
||||||
| ^
|
|
||||||
4 | "a" """b
|
|
||||||
5 | c""" "d
|
|
||||||
|
|
|
||||||
|
|
||||||
invalid-syntax: missing closing quote in string literal
|
invalid-syntax: missing closing quote in string literal
|
||||||
--> ISC_syntax_error.py:5:6
|
--> ISC_syntax_error.py:5:6
|
||||||
|
|
|
|
||||||
|
@ -51,24 +30,13 @@ invalid-syntax: missing closing quote in string literal
|
||||||
5 | c""" "d
|
5 | c""" "d
|
||||||
| ^^
|
| ^^
|
||||||
6 |
|
6 |
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
7 | # This is also true for
|
||||||
|
|
|
||||||
|
|
||||||
invalid-syntax: Expected a statement
|
|
||||||
--> ISC_syntax_error.py:5:8
|
|
||||||
|
|
|
||||||
3 | "a" "b" "c
|
|
||||||
4 | "a" """b
|
|
||||||
5 | c""" "d
|
|
||||||
| ^
|
|
||||||
6 |
|
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
|
||||||
|
|
|
|
||||||
|
|
||||||
invalid-syntax: f-string: unterminated string
|
invalid-syntax: f-string: unterminated string
|
||||||
--> ISC_syntax_error.py:9:8
|
--> ISC_syntax_error.py:9:8
|
||||||
|
|
|
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
7 | # This is also true for
|
||||||
8 | # unterminated f-strings.
|
8 | # unterminated f-strings.
|
||||||
9 | f"a" f"b
|
9 | f"a" f"b
|
||||||
| ^
|
| ^
|
||||||
|
@ -79,7 +47,7 @@ invalid-syntax: f-string: unterminated string
|
||||||
invalid-syntax: Expected FStringEnd, found newline
|
invalid-syntax: Expected FStringEnd, found newline
|
||||||
--> ISC_syntax_error.py:9:9
|
--> ISC_syntax_error.py:9:9
|
||||||
|
|
|
|
||||||
7 | # For f-strings, the `FStringRanges` won't contain the range for
|
7 | # This is also true for
|
||||||
8 | # unterminated f-strings.
|
8 | # unterminated f-strings.
|
||||||
9 | f"a" f"b
|
9 | f"a" f"b
|
||||||
| ^
|
| ^
|
||||||
|
@ -133,14 +101,6 @@ invalid-syntax: f-string: unterminated triple-quoted string
|
||||||
| |__^
|
| |__^
|
||||||
|
|
|
|
||||||
|
|
||||||
invalid-syntax: unexpected EOF while parsing
|
|
||||||
--> ISC_syntax_error.py:30:1
|
|
||||||
|
|
|
||||||
28 | "i" "j"
|
|
||||||
29 | )
|
|
||||||
| ^
|
|
||||||
|
|
|
||||||
|
|
||||||
invalid-syntax: f-string: unterminated string
|
invalid-syntax: f-string: unterminated string
|
||||||
--> ISC_syntax_error.py:30:1
|
--> ISC_syntax_error.py:30:1
|
||||||
|
|
|
|
||||||
|
|
|
@ -23,16 +23,17 @@ invalid-syntax: missing closing quote in string literal
|
||||||
9 | # Unterminated f-string
|
9 | # Unterminated f-string
|
||||||
|
|
|
|
||||||
|
|
||||||
invalid-syntax: Expected a statement
|
PLE2510 Invalid unescaped character backspace, use "\b" instead
|
||||||
--> invalid_characters_syntax_error.py:7:7
|
--> invalid_characters_syntax_error.py:7:6
|
||||||
|
|
|
|
||||||
5 | b = '␈'
|
5 | b = '␈'
|
||||||
6 | # Unterminated string
|
6 | # Unterminated string
|
||||||
7 | b = '␈
|
7 | b = '␈
|
||||||
| ^
|
| ^
|
||||||
8 | b = '␈'
|
8 | b = '␈'
|
||||||
9 | # Unterminated f-string
|
9 | # Unterminated f-string
|
||||||
|
|
|
|
||||||
|
help: Replace with escape sequence
|
||||||
|
|
||||||
PLE2510 Invalid unescaped character backspace, use "\b" instead
|
PLE2510 Invalid unescaped character backspace, use "\b" instead
|
||||||
--> invalid_characters_syntax_error.py:8:6
|
--> invalid_characters_syntax_error.py:8:6
|
||||||
|
@ -46,6 +47,18 @@ PLE2510 Invalid unescaped character backspace, use "\b" instead
|
||||||
|
|
|
|
||||||
help: Replace with escape sequence
|
help: Replace with escape sequence
|
||||||
|
|
||||||
|
PLE2510 Invalid unescaped character backspace, use "\b" instead
|
||||||
|
--> invalid_characters_syntax_error.py:10:7
|
||||||
|
|
|
||||||
|
8 | b = '␈'
|
||||||
|
9 | # Unterminated f-string
|
||||||
|
10 | b = f'␈
|
||||||
|
| ^
|
||||||
|
11 | b = f'␈'
|
||||||
|
12 | # Implicitly concatenated
|
||||||
|
|
|
||||||
|
help: Replace with escape sequence
|
||||||
|
|
||||||
invalid-syntax: f-string: unterminated string
|
invalid-syntax: f-string: unterminated string
|
||||||
--> invalid_characters_syntax_error.py:10:7
|
--> invalid_characters_syntax_error.py:10:7
|
||||||
|
|
|
|
||||||
|
@ -109,11 +122,12 @@ invalid-syntax: missing closing quote in string literal
|
||||||
| ^^
|
| ^^
|
||||||
|
|
|
|
||||||
|
|
||||||
invalid-syntax: Expected a statement
|
PLE2510 Invalid unescaped character backspace, use "\b" instead
|
||||||
--> invalid_characters_syntax_error.py:13:16
|
--> invalid_characters_syntax_error.py:13:15
|
||||||
|
|
|
|
||||||
11 | b = f'␈'
|
11 | b = f'␈'
|
||||||
12 | # Implicitly concatenated
|
12 | # Implicitly concatenated
|
||||||
13 | b = '␈' f'␈' '␈
|
13 | b = '␈' f'␈' '␈
|
||||||
| ^
|
| ^
|
||||||
|
|
|
|
||||||
|
help: Replace with escape sequence
|
||||||
|
|
|
@ -6,7 +6,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||||
use ruff_python_ast::helpers::any_over_expr;
|
use ruff_python_ast::helpers::any_over_expr;
|
||||||
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
use ruff_python_ast::str::{leading_quote, trailing_quote};
|
||||||
use ruff_python_ast::{self as ast, Expr, Keyword};
|
use ruff_python_ast::{self as ast, Expr, Keyword, StringFlags};
|
||||||
use ruff_python_literal::format::{
|
use ruff_python_literal::format::{
|
||||||
FieldName, FieldNamePart, FieldType, FormatPart, FormatString, FromTemplate,
|
FieldName, FieldNamePart, FieldType, FormatPart, FormatString, FromTemplate,
|
||||||
};
|
};
|
||||||
|
@ -430,7 +430,7 @@ pub(crate) fn f_strings(checker: &Checker, call: &ast::ExprCall, summary: &Forma
|
||||||
// dot is the start of an attribute access.
|
// dot is the start of an attribute access.
|
||||||
break token.start();
|
break token.start();
|
||||||
}
|
}
|
||||||
TokenKind::String => {
|
TokenKind::String if !token.unwrap_string_flags().is_unclosed() => {
|
||||||
match FStringConversion::try_convert(token.range(), &mut summary, checker.locator())
|
match FStringConversion::try_convert(token.range(), &mut summary, checker.locator())
|
||||||
{
|
{
|
||||||
// If the format string contains side effects that would need to be repeated,
|
// If the format string contains side effects that would need to be repeated,
|
||||||
|
|
|
@ -735,6 +735,8 @@ pub trait StringFlags: Copy {
|
||||||
|
|
||||||
fn prefix(self) -> AnyStringPrefix;
|
fn prefix(self) -> AnyStringPrefix;
|
||||||
|
|
||||||
|
fn is_unclosed(self) -> bool;
|
||||||
|
|
||||||
/// Is the string triple-quoted, i.e.,
|
/// Is the string triple-quoted, i.e.,
|
||||||
/// does it begin and end with three consecutive quote characters?
|
/// does it begin and end with three consecutive quote characters?
|
||||||
fn is_triple_quoted(self) -> bool {
|
fn is_triple_quoted(self) -> bool {
|
||||||
|
@ -779,6 +781,7 @@ pub trait StringFlags: Copy {
|
||||||
|
|
||||||
fn as_any_string_flags(self) -> AnyStringFlags {
|
fn as_any_string_flags(self) -> AnyStringFlags {
|
||||||
AnyStringFlags::new(self.prefix(), self.quote_style(), self.triple_quotes())
|
AnyStringFlags::new(self.prefix(), self.quote_style(), self.triple_quotes())
|
||||||
|
.with_unclosed(self.is_unclosed())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_contents(self, contents: &str) -> DisplayFlags<'_> {
|
fn display_contents(self, contents: &str) -> DisplayFlags<'_> {
|
||||||
|
@ -829,6 +832,10 @@ bitflags! {
|
||||||
/// for why we track the casing of the `r` prefix,
|
/// for why we track the casing of the `r` prefix,
|
||||||
/// but not for any other prefix
|
/// but not for any other prefix
|
||||||
const R_PREFIX_UPPER = 1 << 3;
|
const R_PREFIX_UPPER = 1 << 3;
|
||||||
|
|
||||||
|
/// The f-string is unclosed, meaning it is missing a closing quote.
|
||||||
|
/// For example: `f"{bar`
|
||||||
|
const UNCLOSED = 1 << 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,6 +894,12 @@ impl FStringFlags {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_unclosed(mut self, unclosed: bool) -> Self {
|
||||||
|
self.0.set(InterpolatedStringFlagsInner::UNCLOSED, unclosed);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_prefix(mut self, prefix: FStringPrefix) -> Self {
|
pub fn with_prefix(mut self, prefix: FStringPrefix) -> Self {
|
||||||
match prefix {
|
match prefix {
|
||||||
|
@ -984,6 +997,12 @@ impl TStringFlags {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_unclosed(mut self, unclosed: bool) -> Self {
|
||||||
|
self.0.set(InterpolatedStringFlagsInner::UNCLOSED, unclosed);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_prefix(mut self, prefix: TStringPrefix) -> Self {
|
pub fn with_prefix(mut self, prefix: TStringPrefix) -> Self {
|
||||||
match prefix {
|
match prefix {
|
||||||
|
@ -1051,6 +1070,10 @@ impl StringFlags for FStringFlags {
|
||||||
fn prefix(self) -> AnyStringPrefix {
|
fn prefix(self) -> AnyStringPrefix {
|
||||||
AnyStringPrefix::Format(self.prefix())
|
AnyStringPrefix::Format(self.prefix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_unclosed(self) -> bool {
|
||||||
|
self.0.intersects(InterpolatedStringFlagsInner::UNCLOSED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for FStringFlags {
|
impl fmt::Debug for FStringFlags {
|
||||||
|
@ -1059,6 +1082,7 @@ impl fmt::Debug for FStringFlags {
|
||||||
.field("quote_style", &self.quote_style())
|
.field("quote_style", &self.quote_style())
|
||||||
.field("prefix", &self.prefix())
|
.field("prefix", &self.prefix())
|
||||||
.field("triple_quoted", &self.is_triple_quoted())
|
.field("triple_quoted", &self.is_triple_quoted())
|
||||||
|
.field("unclosed", &self.is_unclosed())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1090,6 +1114,10 @@ impl StringFlags for TStringFlags {
|
||||||
fn prefix(self) -> AnyStringPrefix {
|
fn prefix(self) -> AnyStringPrefix {
|
||||||
AnyStringPrefix::Template(self.prefix())
|
AnyStringPrefix::Template(self.prefix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_unclosed(self) -> bool {
|
||||||
|
self.0.intersects(InterpolatedStringFlagsInner::UNCLOSED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for TStringFlags {
|
impl fmt::Debug for TStringFlags {
|
||||||
|
@ -1098,6 +1126,7 @@ impl fmt::Debug for TStringFlags {
|
||||||
.field("quote_style", &self.quote_style())
|
.field("quote_style", &self.quote_style())
|
||||||
.field("prefix", &self.prefix())
|
.field("prefix", &self.prefix())
|
||||||
.field("triple_quoted", &self.is_triple_quoted())
|
.field("triple_quoted", &self.is_triple_quoted())
|
||||||
|
.field("unclosed", &self.is_unclosed())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1427,6 +1456,9 @@ bitflags! {
|
||||||
|
|
||||||
/// The string was deemed invalid by the parser.
|
/// The string was deemed invalid by the parser.
|
||||||
const INVALID = 1 << 5;
|
const INVALID = 1 << 5;
|
||||||
|
|
||||||
|
/// The string literal misses the matching closing quote(s).
|
||||||
|
const UNCLOSED = 1 << 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1479,6 +1511,12 @@ impl StringLiteralFlags {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_unclosed(mut self, unclosed: bool) -> Self {
|
||||||
|
self.0.set(StringLiteralFlagsInner::UNCLOSED, unclosed);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_prefix(self, prefix: StringLiteralPrefix) -> Self {
|
pub fn with_prefix(self, prefix: StringLiteralPrefix) -> Self {
|
||||||
let StringLiteralFlags(flags) = self;
|
let StringLiteralFlags(flags) = self;
|
||||||
|
@ -1560,6 +1598,10 @@ impl StringFlags for StringLiteralFlags {
|
||||||
fn prefix(self) -> AnyStringPrefix {
|
fn prefix(self) -> AnyStringPrefix {
|
||||||
AnyStringPrefix::Regular(self.prefix())
|
AnyStringPrefix::Regular(self.prefix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_unclosed(self) -> bool {
|
||||||
|
self.0.intersects(StringLiteralFlagsInner::UNCLOSED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for StringLiteralFlags {
|
impl fmt::Debug for StringLiteralFlags {
|
||||||
|
@ -1568,6 +1610,7 @@ impl fmt::Debug for StringLiteralFlags {
|
||||||
.field("quote_style", &self.quote_style())
|
.field("quote_style", &self.quote_style())
|
||||||
.field("prefix", &self.prefix())
|
.field("prefix", &self.prefix())
|
||||||
.field("triple_quoted", &self.is_triple_quoted())
|
.field("triple_quoted", &self.is_triple_quoted())
|
||||||
|
.field("unclosed", &self.is_unclosed())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1846,6 +1889,9 @@ bitflags! {
|
||||||
|
|
||||||
/// The bytestring was deemed invalid by the parser.
|
/// The bytestring was deemed invalid by the parser.
|
||||||
const INVALID = 1 << 4;
|
const INVALID = 1 << 4;
|
||||||
|
|
||||||
|
/// The byte string misses the matching closing quote(s).
|
||||||
|
const UNCLOSED = 1 << 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1897,6 +1943,12 @@ impl BytesLiteralFlags {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_unclosed(mut self, unclosed: bool) -> Self {
|
||||||
|
self.0.set(BytesLiteralFlagsInner::UNCLOSED, unclosed);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_prefix(mut self, prefix: ByteStringPrefix) -> Self {
|
pub fn with_prefix(mut self, prefix: ByteStringPrefix) -> Self {
|
||||||
match prefix {
|
match prefix {
|
||||||
|
@ -1959,6 +2011,10 @@ impl StringFlags for BytesLiteralFlags {
|
||||||
fn prefix(self) -> AnyStringPrefix {
|
fn prefix(self) -> AnyStringPrefix {
|
||||||
AnyStringPrefix::Bytes(self.prefix())
|
AnyStringPrefix::Bytes(self.prefix())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_unclosed(self) -> bool {
|
||||||
|
self.0.intersects(BytesLiteralFlagsInner::UNCLOSED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for BytesLiteralFlags {
|
impl fmt::Debug for BytesLiteralFlags {
|
||||||
|
@ -1967,6 +2023,7 @@ impl fmt::Debug for BytesLiteralFlags {
|
||||||
.field("quote_style", &self.quote_style())
|
.field("quote_style", &self.quote_style())
|
||||||
.field("prefix", &self.prefix())
|
.field("prefix", &self.prefix())
|
||||||
.field("triple_quoted", &self.is_triple_quoted())
|
.field("triple_quoted", &self.is_triple_quoted())
|
||||||
|
.field("unclosed", &self.is_unclosed())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2028,7 +2085,7 @@ bitflags! {
|
||||||
/// prefix flags is by calling the `as_flags()` method on the
|
/// prefix flags is by calling the `as_flags()` method on the
|
||||||
/// `StringPrefix` enum.
|
/// `StringPrefix` enum.
|
||||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
struct AnyStringFlagsInner: u8 {
|
struct AnyStringFlagsInner: u16 {
|
||||||
/// The string uses double quotes (`"`).
|
/// The string uses double quotes (`"`).
|
||||||
/// If this flag is not set, the string uses single quotes (`'`).
|
/// If this flag is not set, the string uses single quotes (`'`).
|
||||||
const DOUBLE = 1 << 0;
|
const DOUBLE = 1 << 0;
|
||||||
|
@ -2071,6 +2128,9 @@ bitflags! {
|
||||||
/// for why we track the casing of the `r` prefix,
|
/// for why we track the casing of the `r` prefix,
|
||||||
/// but not for any other prefix
|
/// but not for any other prefix
|
||||||
const R_PREFIX_UPPER = 1 << 7;
|
const R_PREFIX_UPPER = 1 << 7;
|
||||||
|
|
||||||
|
/// String without matching closing quote(s).
|
||||||
|
const UNCLOSED = 1 << 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2166,6 +2226,12 @@ impl AnyStringFlags {
|
||||||
.set(AnyStringFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes());
|
.set(AnyStringFlagsInner::TRIPLE_QUOTED, triple_quotes.is_yes());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn with_unclosed(mut self, unclosed: bool) -> Self {
|
||||||
|
self.0.set(AnyStringFlagsInner::UNCLOSED, unclosed);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StringFlags for AnyStringFlags {
|
impl StringFlags for AnyStringFlags {
|
||||||
|
@ -2234,6 +2300,10 @@ impl StringFlags for AnyStringFlags {
|
||||||
}
|
}
|
||||||
AnyStringPrefix::Regular(StringLiteralPrefix::Empty)
|
AnyStringPrefix::Regular(StringLiteralPrefix::Empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_unclosed(self) -> bool {
|
||||||
|
self.0.intersects(AnyStringFlagsInner::UNCLOSED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for AnyStringFlags {
|
impl fmt::Debug for AnyStringFlags {
|
||||||
|
@ -2242,6 +2312,7 @@ impl fmt::Debug for AnyStringFlags {
|
||||||
.field("prefix", &self.prefix())
|
.field("prefix", &self.prefix())
|
||||||
.field("triple_quoted", &self.is_triple_quoted())
|
.field("triple_quoted", &self.is_triple_quoted())
|
||||||
.field("quote_style", &self.quote_style())
|
.field("quote_style", &self.quote_style())
|
||||||
|
.field("unclosed", &self.is_unclosed())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2258,6 +2329,7 @@ impl From<AnyStringFlags> for StringLiteralFlags {
|
||||||
.with_quote_style(value.quote_style())
|
.with_quote_style(value.quote_style())
|
||||||
.with_prefix(prefix)
|
.with_prefix(prefix)
|
||||||
.with_triple_quotes(value.triple_quotes())
|
.with_triple_quotes(value.triple_quotes())
|
||||||
|
.with_unclosed(value.is_unclosed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2279,6 +2351,7 @@ impl From<AnyStringFlags> for BytesLiteralFlags {
|
||||||
.with_quote_style(value.quote_style())
|
.with_quote_style(value.quote_style())
|
||||||
.with_prefix(bytestring_prefix)
|
.with_prefix(bytestring_prefix)
|
||||||
.with_triple_quotes(value.triple_quotes())
|
.with_triple_quotes(value.triple_quotes())
|
||||||
|
.with_unclosed(value.is_unclosed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2300,6 +2373,7 @@ impl From<AnyStringFlags> for FStringFlags {
|
||||||
.with_quote_style(value.quote_style())
|
.with_quote_style(value.quote_style())
|
||||||
.with_prefix(prefix)
|
.with_prefix(prefix)
|
||||||
.with_triple_quotes(value.triple_quotes())
|
.with_triple_quotes(value.triple_quotes())
|
||||||
|
.with_unclosed(value.is_unclosed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2321,6 +2395,7 @@ impl From<AnyStringFlags> for TStringFlags {
|
||||||
.with_quote_style(value.quote_style())
|
.with_quote_style(value.quote_style())
|
||||||
.with_prefix(prefix)
|
.with_prefix(prefix)
|
||||||
.with_triple_quotes(value.triple_quotes())
|
.with_triple_quotes(value.triple_quotes())
|
||||||
|
.with_unclosed(value.is_unclosed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ use unicode_ident::{is_xid_continue, is_xid_start};
|
||||||
use unicode_normalization::UnicodeNormalization;
|
use unicode_normalization::UnicodeNormalization;
|
||||||
|
|
||||||
use ruff_python_ast::name::Name;
|
use ruff_python_ast::name::Name;
|
||||||
|
use ruff_python_ast::str_prefix::{AnyStringPrefix, StringLiteralPrefix};
|
||||||
use ruff_python_ast::{Int, IpyEscapeKind, StringFlags};
|
use ruff_python_ast::{Int, IpyEscapeKind, StringFlags};
|
||||||
use ruff_python_trivia::is_python_whitespace;
|
use ruff_python_trivia::is_python_whitespace;
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
|
@ -24,6 +25,7 @@ use crate::lexer::indentation::{Indentation, Indentations, IndentationsCheckpoin
|
||||||
use crate::lexer::interpolated_string::{
|
use crate::lexer::interpolated_string::{
|
||||||
InterpolatedStringContext, InterpolatedStrings, InterpolatedStringsCheckpoint,
|
InterpolatedStringContext, InterpolatedStrings, InterpolatedStringsCheckpoint,
|
||||||
};
|
};
|
||||||
|
use crate::string::InterpolatedStringKind;
|
||||||
use crate::token::{TokenFlags, TokenKind, TokenValue};
|
use crate::token::{TokenFlags, TokenKind, TokenValue};
|
||||||
|
|
||||||
mod cursor;
|
mod cursor;
|
||||||
|
@ -782,6 +784,7 @@ impl<'src> Lexer<'src> {
|
||||||
// SAFETY: Safe because the function is only called when `self.fstrings` is not empty.
|
// SAFETY: Safe because the function is only called when `self.fstrings` is not empty.
|
||||||
let interpolated_string = self.interpolated_strings.current().unwrap();
|
let interpolated_string = self.interpolated_strings.current().unwrap();
|
||||||
let string_kind = interpolated_string.kind();
|
let string_kind = interpolated_string.kind();
|
||||||
|
let interpolated_flags = interpolated_string.flags();
|
||||||
|
|
||||||
// Check if we're at the end of the f-string.
|
// Check if we're at the end of the f-string.
|
||||||
if interpolated_string.is_triple_quoted() {
|
if interpolated_string.is_triple_quoted() {
|
||||||
|
@ -819,15 +822,19 @@ impl<'src> Lexer<'src> {
|
||||||
} else {
|
} else {
|
||||||
InterpolatedStringErrorType::UnterminatedString
|
InterpolatedStringErrorType::UnterminatedString
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.nesting = interpolated_string.nesting();
|
||||||
self.interpolated_strings.pop();
|
self.interpolated_strings.pop();
|
||||||
return Some(self.push_error(LexicalError::new(
|
self.current_flags |= TokenFlags::UNCLOSED_STRING;
|
||||||
|
self.push_error(LexicalError::new(
|
||||||
LexicalErrorType::from_interpolated_string_error(error, string_kind),
|
LexicalErrorType::from_interpolated_string_error(error, string_kind),
|
||||||
self.token_range(),
|
self.token_range(),
|
||||||
)));
|
));
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
'\n' | '\r' if !interpolated_string.is_triple_quoted() => {
|
'\n' | '\r' if !interpolated_string.is_triple_quoted() => {
|
||||||
// https://github.com/astral-sh/ruff/issues/18632
|
// https://github.com/astral-sh/ruff/issues/18632
|
||||||
self.interpolated_strings.pop();
|
|
||||||
|
|
||||||
let error_type = if in_format_spec {
|
let error_type = if in_format_spec {
|
||||||
InterpolatedStringErrorType::NewlineInFormatSpec
|
InterpolatedStringErrorType::NewlineInFormatSpec
|
||||||
|
@ -835,10 +842,16 @@ impl<'src> Lexer<'src> {
|
||||||
InterpolatedStringErrorType::UnterminatedString
|
InterpolatedStringErrorType::UnterminatedString
|
||||||
};
|
};
|
||||||
|
|
||||||
return Some(self.push_error(LexicalError::new(
|
self.nesting = interpolated_string.nesting();
|
||||||
|
self.interpolated_strings.pop();
|
||||||
|
self.current_flags |= TokenFlags::UNCLOSED_STRING;
|
||||||
|
|
||||||
|
self.push_error(LexicalError::new(
|
||||||
LexicalErrorType::from_interpolated_string_error(error_type, string_kind),
|
LexicalErrorType::from_interpolated_string_error(error_type, string_kind),
|
||||||
self.token_range(),
|
self.token_range(),
|
||||||
)));
|
));
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
'\\' => {
|
'\\' => {
|
||||||
self.cursor.bump(); // '\'
|
self.cursor.bump(); // '\'
|
||||||
|
@ -913,7 +926,7 @@ impl<'src> Lexer<'src> {
|
||||||
|
|
||||||
self.current_value = TokenValue::InterpolatedStringMiddle(value.into_boxed_str());
|
self.current_value = TokenValue::InterpolatedStringMiddle(value.into_boxed_str());
|
||||||
|
|
||||||
self.current_flags = interpolated_string.flags();
|
self.current_flags = interpolated_flags;
|
||||||
Some(string_kind.middle_token())
|
Some(string_kind.middle_token())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,10 +955,12 @@ impl<'src> Lexer<'src> {
|
||||||
let Some(index) = memchr::memchr(quote_byte, self.cursor.rest().as_bytes()) else {
|
let Some(index) = memchr::memchr(quote_byte, self.cursor.rest().as_bytes()) else {
|
||||||
self.cursor.skip_to_end();
|
self.cursor.skip_to_end();
|
||||||
|
|
||||||
return self.push_error(LexicalError::new(
|
self.current_flags |= TokenFlags::UNCLOSED_STRING;
|
||||||
|
self.push_error(LexicalError::new(
|
||||||
LexicalErrorType::UnclosedStringError,
|
LexicalErrorType::UnclosedStringError,
|
||||||
self.token_range(),
|
self.token_range(),
|
||||||
));
|
));
|
||||||
|
break self.offset();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rare case: if there are an odd number of backslashes before the quote, then
|
// Rare case: if there are an odd number of backslashes before the quote, then
|
||||||
|
@ -977,11 +992,14 @@ impl<'src> Lexer<'src> {
|
||||||
memchr::memchr3(quote_byte, b'\r', b'\n', self.cursor.rest().as_bytes())
|
memchr::memchr3(quote_byte, b'\r', b'\n', self.cursor.rest().as_bytes())
|
||||||
else {
|
else {
|
||||||
self.cursor.skip_to_end();
|
self.cursor.skip_to_end();
|
||||||
|
self.current_flags |= TokenFlags::UNCLOSED_STRING;
|
||||||
|
|
||||||
return self.push_error(LexicalError::new(
|
self.push_error(LexicalError::new(
|
||||||
LexicalErrorType::StringError,
|
LexicalErrorType::UnclosedStringError,
|
||||||
self.token_range(),
|
self.token_range(),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
break self.offset();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rare case: if there are an odd number of backslashes before the quote, then
|
// Rare case: if there are an odd number of backslashes before the quote, then
|
||||||
|
@ -1009,10 +1027,12 @@ impl<'src> Lexer<'src> {
|
||||||
|
|
||||||
match quote_or_newline {
|
match quote_or_newline {
|
||||||
'\r' | '\n' => {
|
'\r' | '\n' => {
|
||||||
return self.push_error(LexicalError::new(
|
self.current_flags |= TokenFlags::UNCLOSED_STRING;
|
||||||
|
self.push_error(LexicalError::new(
|
||||||
LexicalErrorType::UnclosedStringError,
|
LexicalErrorType::UnclosedStringError,
|
||||||
self.token_range(),
|
self.token_range(),
|
||||||
));
|
));
|
||||||
|
break self.offset();
|
||||||
}
|
}
|
||||||
ch if ch == quote => {
|
ch if ch == quote => {
|
||||||
let value_end = self.offset();
|
let value_end = self.offset();
|
||||||
|
@ -1331,7 +1351,20 @@ impl<'src> Lexer<'src> {
|
||||||
|
|
||||||
fn consume_end(&mut self) -> TokenKind {
|
fn consume_end(&mut self) -> TokenKind {
|
||||||
// We reached end of file.
|
// We reached end of file.
|
||||||
// First of all, we need all nestings to be finished.
|
|
||||||
|
// First, finish any unterminated interpolated-strings.
|
||||||
|
while let Some(interpolated_string) = self.interpolated_strings.pop() {
|
||||||
|
self.nesting = interpolated_string.nesting();
|
||||||
|
self.push_error(LexicalError::new(
|
||||||
|
LexicalErrorType::from_interpolated_string_error(
|
||||||
|
InterpolatedStringErrorType::UnterminatedString,
|
||||||
|
interpolated_string.kind(),
|
||||||
|
),
|
||||||
|
self.token_range(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second, finish all nestings.
|
||||||
// For Mode::ParenthesizedExpression we start with nesting level 1.
|
// For Mode::ParenthesizedExpression we start with nesting level 1.
|
||||||
// So we check if we end with that level.
|
// So we check if we end with that level.
|
||||||
let init_nesting = u32::from(self.mode == Mode::ParenthesizedExpression);
|
let init_nesting = u32::from(self.mode == Mode::ParenthesizedExpression);
|
||||||
|
@ -1459,6 +1492,107 @@ impl<'src> Lexer<'src> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-lexes an unclosed string token in the context of an interpolated string element.
|
||||||
|
///
|
||||||
|
/// ```py
|
||||||
|
/// f'{a'
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This method re-lexes the trailing `'` as the end of the f-string rather than the
|
||||||
|
/// start of a new string token for better error recovery.
|
||||||
|
pub(crate) fn re_lex_string_token_in_interpolation_element(
|
||||||
|
&mut self,
|
||||||
|
kind: InterpolatedStringKind,
|
||||||
|
) {
|
||||||
|
let Some(interpolated_string) = self.interpolated_strings.current() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let current_string_flags = self.current_flags().as_any_string_flags();
|
||||||
|
|
||||||
|
// Only unclosed strings, that have the same quote character
|
||||||
|
if !matches!(self.current_kind, TokenKind::String)
|
||||||
|
|| !self.current_flags.is_unclosed()
|
||||||
|
|| current_string_flags.prefix() != AnyStringPrefix::Regular(StringLiteralPrefix::Empty)
|
||||||
|
|| current_string_flags.quote_style().as_char() != interpolated_string.quote_char()
|
||||||
|
|| current_string_flags.is_triple_quoted() != interpolated_string.is_triple_quoted()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only if the string's first line only contains whitespace,
|
||||||
|
// or ends in a comment (not `f"{"abc`)
|
||||||
|
let first_line = &self.source
|
||||||
|
[(self.current_range.start() + current_string_flags.quote_len()).to_usize()..];
|
||||||
|
|
||||||
|
for c in first_line.chars() {
|
||||||
|
if matches!(c, '\n' | '\r' | '#') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `f'{'ab`, we want to parse `ab` as a normal string and not the closing element of the f-string
|
||||||
|
if !is_python_whitespace(c) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.errors.last().is_some_and(|error| {
|
||||||
|
error.location() == self.current_range
|
||||||
|
&& matches!(error.error(), LexicalErrorType::UnclosedStringError)
|
||||||
|
}) {
|
||||||
|
self.errors.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_range =
|
||||||
|
TextRange::at(self.current_range.start(), self.current_flags.quote_len());
|
||||||
|
self.current_kind = kind.end_token();
|
||||||
|
self.current_value = TokenValue::None;
|
||||||
|
self.current_flags = TokenFlags::empty();
|
||||||
|
|
||||||
|
self.nesting = interpolated_string.nesting();
|
||||||
|
self.interpolated_strings.pop();
|
||||||
|
|
||||||
|
self.cursor = Cursor::new(self.source);
|
||||||
|
self.cursor.skip_bytes(self.current_range.end().to_usize());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Re-lex `r"` in a format specifier position.
|
||||||
|
///
|
||||||
|
/// `r"` in a format specifier position is unlikely to be the start of a raw string.
|
||||||
|
/// Instead, it's the format specifier `!r` followed by the closing quote of the f-string,
|
||||||
|
/// when the `}` is missing.
|
||||||
|
///
|
||||||
|
/// ```py
|
||||||
|
/// f"{test!r"
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This function re-lexes the `r"` as `r` (a name token). The next `next_token` call will
|
||||||
|
/// return a unclosed string token for `"`, which [`Self::re_lex_string_token_in_interpolation_element`]
|
||||||
|
/// can then re-lex as the end of the f-string.
|
||||||
|
pub(crate) fn re_lex_raw_string_in_format_spec(&mut self) {
|
||||||
|
// Re-lex `r"` as `NAME r` followed by an unclosed string
|
||||||
|
// `f"{test!r"` -> `f"{test!`, `r`, `"`
|
||||||
|
if matches!(self.current_kind, TokenKind::String)
|
||||||
|
&& self.current_flags.is_unclosed()
|
||||||
|
&& self.current_flags.prefix()
|
||||||
|
== AnyStringPrefix::Regular(StringLiteralPrefix::Raw { uppercase: false })
|
||||||
|
{
|
||||||
|
if self.errors.last().is_some_and(|error| {
|
||||||
|
error.location() == self.current_range
|
||||||
|
&& matches!(error.error(), LexicalErrorType::UnclosedStringError)
|
||||||
|
}) {
|
||||||
|
self.errors.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.current_range = TextRange::at(self.current_range.start(), 'r'.text_len());
|
||||||
|
self.current_kind = TokenKind::Name;
|
||||||
|
self.current_value = TokenValue::Name(Name::new_static("r"));
|
||||||
|
self.current_flags = TokenFlags::empty();
|
||||||
|
self.cursor = Cursor::new(self.source);
|
||||||
|
self.cursor.skip_bytes(self.current_range.end().to_usize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn token_range(&self) -> TextRange {
|
fn token_range(&self) -> TextRange {
|
||||||
let end = self.offset();
|
let end = self.offset();
|
||||||
|
@ -2739,6 +2873,164 @@ t"{(lambda x:{x})}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lex_fstring_unclosed() {
|
||||||
|
let source = r#"f"hello"#;
|
||||||
|
|
||||||
|
assert_snapshot!(lex_invalid(source, Mode::Module), @r#"
|
||||||
|
## Tokens
|
||||||
|
```
|
||||||
|
[
|
||||||
|
(
|
||||||
|
FStringStart,
|
||||||
|
0..2,
|
||||||
|
TokenFlags(
|
||||||
|
DOUBLE_QUOTES | F_STRING,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
InterpolatedStringMiddle(
|
||||||
|
"hello",
|
||||||
|
),
|
||||||
|
2..7,
|
||||||
|
TokenFlags(
|
||||||
|
DOUBLE_QUOTES | F_STRING,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Newline,
|
||||||
|
7..7,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
## Errors
|
||||||
|
```
|
||||||
|
[
|
||||||
|
LexicalError {
|
||||||
|
error: FStringError(
|
||||||
|
UnterminatedString,
|
||||||
|
),
|
||||||
|
location: 2..7,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lex_fstring_missing_brace() {
|
||||||
|
let source = "f'{'";
|
||||||
|
|
||||||
|
assert_snapshot!(lex_invalid(source, Mode::Module), @r#"
|
||||||
|
## Tokens
|
||||||
|
```
|
||||||
|
[
|
||||||
|
(
|
||||||
|
FStringStart,
|
||||||
|
0..2,
|
||||||
|
TokenFlags(
|
||||||
|
F_STRING,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Lbrace,
|
||||||
|
2..3,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
String(
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
3..4,
|
||||||
|
TokenFlags(
|
||||||
|
UNCLOSED_STRING,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Newline,
|
||||||
|
4..4,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
## Errors
|
||||||
|
```
|
||||||
|
[
|
||||||
|
LexicalError {
|
||||||
|
error: UnclosedStringError,
|
||||||
|
location: 3..4,
|
||||||
|
},
|
||||||
|
LexicalError {
|
||||||
|
error: FStringError(
|
||||||
|
UnterminatedString,
|
||||||
|
),
|
||||||
|
location: 4..4,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lex_fstring_missing_brace_after_format_spec() {
|
||||||
|
let source = r#"f"{foo!r""#;
|
||||||
|
|
||||||
|
assert_snapshot!(lex_invalid(source, Mode::Module), @r#"
|
||||||
|
## Tokens
|
||||||
|
```
|
||||||
|
[
|
||||||
|
(
|
||||||
|
FStringStart,
|
||||||
|
0..2,
|
||||||
|
TokenFlags(
|
||||||
|
DOUBLE_QUOTES | F_STRING,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Lbrace,
|
||||||
|
2..3,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Name(
|
||||||
|
Name("foo"),
|
||||||
|
),
|
||||||
|
3..6,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Exclamation,
|
||||||
|
6..7,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
String(
|
||||||
|
"",
|
||||||
|
),
|
||||||
|
7..9,
|
||||||
|
TokenFlags(
|
||||||
|
DOUBLE_QUOTES | RAW_STRING_LOWERCASE | UNCLOSED_STRING,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Newline,
|
||||||
|
9..9,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
## Errors
|
||||||
|
```
|
||||||
|
[
|
||||||
|
LexicalError {
|
||||||
|
error: UnclosedStringError,
|
||||||
|
location: 7..9,
|
||||||
|
},
|
||||||
|
LexicalError {
|
||||||
|
error: FStringError(
|
||||||
|
UnterminatedString,
|
||||||
|
),
|
||||||
|
location: 9..9,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tstring_error() {
|
fn test_tstring_error() {
|
||||||
use InterpolatedStringErrorType::{
|
use InterpolatedStringErrorType::{
|
||||||
|
|
|
@ -1526,7 +1526,7 @@ impl<'src> Parser<'src> {
|
||||||
kind: InterpolatedStringKind,
|
kind: InterpolatedStringKind,
|
||||||
) -> InterpolatedStringData {
|
) -> InterpolatedStringData {
|
||||||
let start = self.node_start();
|
let start = self.node_start();
|
||||||
let flags = self.tokens.current_flags().as_any_string_flags();
|
let mut flags = self.tokens.current_flags().as_any_string_flags();
|
||||||
|
|
||||||
self.bump(kind.start_token());
|
self.bump(kind.start_token());
|
||||||
let elements = self.parse_interpolated_string_elements(
|
let elements = self.parse_interpolated_string_elements(
|
||||||
|
@ -1535,7 +1535,9 @@ impl<'src> Parser<'src> {
|
||||||
kind,
|
kind,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.expect(kind.end_token());
|
if !self.expect(kind.end_token()) {
|
||||||
|
flags = flags.with_unclosed(true);
|
||||||
|
}
|
||||||
|
|
||||||
// test_ok pep701_f_string_py312
|
// test_ok pep701_f_string_py312
|
||||||
// # parse_options: {"target-version": "3.12"}
|
// # parse_options: {"target-version": "3.12"}
|
||||||
|
@ -1719,6 +1721,9 @@ impl<'src> Parser<'src> {
|
||||||
let start = self.node_start();
|
let start = self.node_start();
|
||||||
self.bump(TokenKind::Lbrace);
|
self.bump(TokenKind::Lbrace);
|
||||||
|
|
||||||
|
self.tokens
|
||||||
|
.re_lex_string_token_in_interpolation_element(string_kind);
|
||||||
|
|
||||||
// test_err f_string_empty_expression
|
// test_err f_string_empty_expression
|
||||||
// f"{}"
|
// f"{}"
|
||||||
// f"{ }"
|
// f"{ }"
|
||||||
|
@ -1740,6 +1745,7 @@ impl<'src> Parser<'src> {
|
||||||
// t"{*}"
|
// t"{*}"
|
||||||
// t"{*x and y}"
|
// t"{*x and y}"
|
||||||
// t"{*yield x}"
|
// t"{*yield x}"
|
||||||
|
|
||||||
let value = self.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or());
|
let value = self.parse_expression_list(ExpressionContext::yield_or_starred_bitwise_or());
|
||||||
|
|
||||||
if !value.is_parenthesized && value.expr.is_lambda_expr() {
|
if !value.is_parenthesized && value.expr.is_lambda_expr() {
|
||||||
|
@ -1773,6 +1779,10 @@ impl<'src> Parser<'src> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let conversion = if self.eat(TokenKind::Exclamation) {
|
let conversion = if self.eat(TokenKind::Exclamation) {
|
||||||
|
// Ensure that the `r` is lexed as a `r` name token instead of a raw string
|
||||||
|
// in `f{abc!r"` (note the missing `}`).
|
||||||
|
self.tokens.re_lex_raw_string_in_format_spec();
|
||||||
|
|
||||||
let conversion_flag_range = self.current_token_range();
|
let conversion_flag_range = self.current_token_range();
|
||||||
if self.at(TokenKind::Name) {
|
if self.at(TokenKind::Name) {
|
||||||
// test_err f_string_conversion_follows_exclamation
|
// test_err f_string_conversion_follows_exclamation
|
||||||
|
@ -1852,6 +1862,9 @@ impl<'src> Parser<'src> {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.tokens
|
||||||
|
.re_lex_string_token_in_interpolation_element(string_kind);
|
||||||
|
|
||||||
// We're using `eat` here instead of `expect` to use the f-string specific error type.
|
// We're using `eat` here instead of `expect` to use the f-string specific error type.
|
||||||
if !self.eat(TokenKind::Rbrace) {
|
if !self.eat(TokenKind::Rbrace) {
|
||||||
// TODO(dhruvmanila): This requires some changes in the lexer. One of them
|
// TODO(dhruvmanila): This requires some changes in the lexer. One of them
|
||||||
|
|
|
@ -31,6 +31,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -44,11 +44,16 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
12..13,
|
12..13,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Unknown,
|
InterpolatedStringMiddle(
|
||||||
|
"d",
|
||||||
|
),
|
||||||
13..14,
|
13..14,
|
||||||
|
TokenFlags(
|
||||||
|
F_STRING,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
NonLogicalNewline,
|
Newline,
|
||||||
14..15,
|
14..15,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -62,8 +67,13 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
16..18,
|
16..18,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Unknown,
|
String(
|
||||||
|
"",
|
||||||
|
),
|
||||||
18..19,
|
18..19,
|
||||||
|
TokenFlags(
|
||||||
|
UNCLOSED_STRING,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Newline,
|
Newline,
|
||||||
|
@ -104,13 +114,22 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
31..32,
|
31..32,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Unknown,
|
InterpolatedStringMiddle(
|
||||||
|
"a",
|
||||||
|
),
|
||||||
32..33,
|
32..33,
|
||||||
|
TokenFlags(
|
||||||
|
F_STRING,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
NonLogicalNewline,
|
Newline,
|
||||||
33..34,
|
33..34,
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
Indent,
|
||||||
|
34..42,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
Name(
|
Name(
|
||||||
Name("b"),
|
Name("b"),
|
||||||
|
@ -118,9 +137,13 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
42..43,
|
42..43,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
NonLogicalNewline,
|
Newline,
|
||||||
43..44,
|
43..44,
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
Dedent,
|
||||||
|
44..44,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
Rbrace,
|
Rbrace,
|
||||||
44..45,
|
44..45,
|
||||||
|
@ -132,8 +155,13 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
45..47,
|
45..47,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Unknown,
|
String(
|
||||||
|
"",
|
||||||
|
),
|
||||||
47..48,
|
47..48,
|
||||||
|
TokenFlags(
|
||||||
|
UNCLOSED_STRING,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Newline,
|
Newline,
|
||||||
|
|
|
@ -44,11 +44,16 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
12..13,
|
12..13,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Unknown,
|
InterpolatedStringMiddle(
|
||||||
|
"d",
|
||||||
|
),
|
||||||
13..14,
|
13..14,
|
||||||
|
TokenFlags(
|
||||||
|
T_STRING,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
NonLogicalNewline,
|
Newline,
|
||||||
14..15,
|
14..15,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -62,8 +67,13 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
16..18,
|
16..18,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Unknown,
|
String(
|
||||||
|
"",
|
||||||
|
),
|
||||||
18..19,
|
18..19,
|
||||||
|
TokenFlags(
|
||||||
|
UNCLOSED_STRING,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Newline,
|
Newline,
|
||||||
|
@ -104,13 +114,22 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
31..32,
|
31..32,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Unknown,
|
InterpolatedStringMiddle(
|
||||||
|
"a",
|
||||||
|
),
|
||||||
32..33,
|
32..33,
|
||||||
|
TokenFlags(
|
||||||
|
T_STRING,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
NonLogicalNewline,
|
Newline,
|
||||||
33..34,
|
33..34,
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
Indent,
|
||||||
|
34..42,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
Name(
|
Name(
|
||||||
Name("b"),
|
Name("b"),
|
||||||
|
@ -118,9 +137,13 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
42..43,
|
42..43,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
NonLogicalNewline,
|
Newline,
|
||||||
43..44,
|
43..44,
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
Dedent,
|
||||||
|
44..44,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
Rbrace,
|
Rbrace,
|
||||||
44..45,
|
44..45,
|
||||||
|
@ -132,8 +155,13 @@ expression: "lex_invalid(source, Mode::Module)"
|
||||||
45..47,
|
45..47,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Unknown,
|
String(
|
||||||
|
"",
|
||||||
|
),
|
||||||
47..48,
|
47..48,
|
||||||
|
TokenFlags(
|
||||||
|
UNCLOSED_STRING,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Newline,
|
Newline,
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -31,6 +31,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -278,6 +278,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -32,6 +32,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -27,6 +27,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -78,6 +78,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -47,6 +47,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -47,6 +47,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -49,6 +49,7 @@ expression: suite
|
||||||
uppercase_r: false,
|
uppercase_r: false,
|
||||||
},
|
},
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -45,6 +45,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -81,6 +81,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -59,6 +59,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -47,6 +47,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: true,
|
triple_quoted: true,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -22,6 +22,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -43,6 +44,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -43,6 +44,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -56,6 +57,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -72,6 +74,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -56,6 +57,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -72,6 +74,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -84,6 +87,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -64,6 +64,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -61,6 +61,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -57,6 +57,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StringLiteral {
|
StringLiteral {
|
||||||
|
@ -67,6 +68,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -91,6 +93,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -64,6 +64,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -55,6 +55,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -76,6 +77,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -61,6 +61,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -54,6 +54,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -45,6 +45,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -45,6 +45,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -39,6 +39,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StringLiteral {
|
StringLiteral {
|
||||||
|
@ -33,6 +34,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Unicode,
|
prefix: Unicode,
|
||||||
triple_quoted: true,
|
triple_quoted: true,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -63,6 +63,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -60,6 +60,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -56,6 +56,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StringLiteral {
|
StringLiteral {
|
||||||
|
@ -66,6 +67,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -90,6 +92,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -63,6 +63,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -54,6 +54,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -75,6 +76,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -60,6 +60,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -53,6 +53,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -44,6 +44,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -44,6 +44,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -38,6 +38,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Unicode,
|
prefix: Unicode,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -43,6 +44,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Unicode,
|
prefix: Unicode,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -43,6 +44,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -55,6 +57,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StringLiteral {
|
StringLiteral {
|
||||||
|
@ -33,6 +34,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Unicode,
|
prefix: Unicode,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -23,6 +23,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Unicode,
|
prefix: Unicode,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StringLiteral {
|
StringLiteral {
|
||||||
|
@ -33,6 +34,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -28,6 +28,7 @@ expression: suite
|
||||||
uppercase_r: false,
|
uppercase_r: false,
|
||||||
},
|
},
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -26,6 +26,7 @@ expression: suite
|
||||||
uppercase_r: false,
|
uppercase_r: false,
|
||||||
},
|
},
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -42,6 +42,7 @@ expression: suite
|
||||||
uppercase_r: false,
|
uppercase_r: false,
|
||||||
},
|
},
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -41,6 +41,7 @@ expression: suite
|
||||||
uppercase_r: false,
|
uppercase_r: false,
|
||||||
},
|
},
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -278,6 +278,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -21,6 +21,7 @@ expression: suite
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -42,6 +42,7 @@ expression: suite
|
||||||
uppercase_r: false,
|
uppercase_r: false,
|
||||||
},
|
},
|
||||||
triple_quoted: true,
|
triple_quoted: true,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -41,6 +41,7 @@ expression: suite
|
||||||
uppercase_r: false,
|
uppercase_r: false,
|
||||||
},
|
},
|
||||||
triple_quoted: true,
|
triple_quoted: true,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -77,6 +77,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -46,6 +46,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -46,6 +46,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -48,6 +48,7 @@ expression: suite
|
||||||
uppercase_r: false,
|
uppercase_r: false,
|
||||||
},
|
},
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -44,6 +44,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -80,6 +80,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -58,6 +58,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -46,6 +46,7 @@ expression: suite
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: true,
|
triple_quoted: true,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -729,7 +729,7 @@ impl fmt::Display for TokenKind {
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub(crate) struct TokenFlags: u8 {
|
pub(crate) struct TokenFlags: u16 {
|
||||||
/// The token is a string with double quotes (`"`).
|
/// The token is a string with double quotes (`"`).
|
||||||
const DOUBLE_QUOTES = 1 << 0;
|
const DOUBLE_QUOTES = 1 << 0;
|
||||||
/// The token is a triple-quoted string i.e., it starts and ends with three consecutive
|
/// The token is a triple-quoted string i.e., it starts and ends with three consecutive
|
||||||
|
@ -748,9 +748,12 @@ bitflags! {
|
||||||
const RAW_STRING_LOWERCASE = 1 << 6;
|
const RAW_STRING_LOWERCASE = 1 << 6;
|
||||||
/// The token is a raw string and the prefix character is in uppercase.
|
/// The token is a raw string and the prefix character is in uppercase.
|
||||||
const RAW_STRING_UPPERCASE = 1 << 7;
|
const RAW_STRING_UPPERCASE = 1 << 7;
|
||||||
|
/// String without matching closing quote(s)
|
||||||
|
const UNCLOSED_STRING = 1 << 8;
|
||||||
|
|
||||||
/// The token is a raw string i.e., prefixed with `r` or `R`
|
/// The token is a raw string i.e., prefixed with `r` or `R`
|
||||||
const RAW_STRING = Self::RAW_STRING_LOWERCASE.bits() | Self::RAW_STRING_UPPERCASE.bits();
|
const RAW_STRING = Self::RAW_STRING_LOWERCASE.bits() | Self::RAW_STRING_UPPERCASE.bits();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,6 +811,10 @@ impl StringFlags for TokenFlags {
|
||||||
AnyStringPrefix::Regular(StringLiteralPrefix::Empty)
|
AnyStringPrefix::Regular(StringLiteralPrefix::Empty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_unclosed(self) -> bool {
|
||||||
|
self.intersects(TokenFlags::UNCLOSED_STRING)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenFlags {
|
impl TokenFlags {
|
||||||
|
|
|
@ -3,6 +3,7 @@ use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||||
use crate::Mode;
|
use crate::Mode;
|
||||||
use crate::error::LexicalError;
|
use crate::error::LexicalError;
|
||||||
use crate::lexer::{Lexer, LexerCheckpoint};
|
use crate::lexer::{Lexer, LexerCheckpoint};
|
||||||
|
use crate::string::InterpolatedStringKind;
|
||||||
use crate::token::{Token, TokenFlags, TokenKind, TokenValue};
|
use crate::token::{Token, TokenFlags, TokenKind, TokenValue};
|
||||||
|
|
||||||
/// Token source for the parser that skips over any trivia tokens.
|
/// Token source for the parser that skips over any trivia tokens.
|
||||||
|
@ -88,6 +89,18 @@ impl<'src> TokenSource<'src> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn re_lex_string_token_in_interpolation_element(
|
||||||
|
&mut self,
|
||||||
|
kind: InterpolatedStringKind,
|
||||||
|
) {
|
||||||
|
self.lexer
|
||||||
|
.re_lex_string_token_in_interpolation_element(kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn re_lex_raw_string_in_format_spec(&mut self) {
|
||||||
|
self.lexer.re_lex_raw_string_in_format_spec();
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the next non-trivia token without consuming it.
|
/// Returns the next non-trivia token without consuming it.
|
||||||
///
|
///
|
||||||
/// Use [`peek2`] to get the next two tokens.
|
/// Use [`peek2`] to get the next two tokens.
|
||||||
|
|
|
@ -28,6 +28,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -57,6 +58,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -114,6 +116,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -144,6 +144,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -164,6 +165,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -194,6 +196,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -214,6 +217,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -53,6 +53,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -74,6 +75,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -49,6 +49,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -229,6 +229,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -249,6 +250,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -396,6 +398,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -416,6 +419,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -601,6 +605,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -621,6 +626,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -45,6 +45,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -65,6 +66,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -147,6 +149,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -169,6 +172,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -663,6 +667,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: true,
|
triple_quoted: true,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -683,6 +688,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: true,
|
triple_quoted: true,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -763,6 +769,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -783,6 +790,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -803,6 +811,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -907,6 +916,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -936,6 +946,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1051,6 +1062,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1071,6 +1083,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1203,6 +1216,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1223,6 +1237,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1407,6 +1422,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1427,6 +1443,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -105,6 +105,7 @@ Module(
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -140,6 +140,7 @@ Module(
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -140,6 +140,7 @@ Module(
|
||||||
quote_style: Single,
|
quote_style: Single,
|
||||||
prefix: Empty,
|
prefix: Empty,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -47,6 +47,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -92,6 +93,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -137,6 +139,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -47,6 +47,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -93,6 +94,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -47,6 +47,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -47,6 +47,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -93,6 +94,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -54,6 +54,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -124,6 +125,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -185,6 +187,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -87,6 +87,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -47,6 +47,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -73,7 +74,7 @@ Module(
|
||||||
elements: [
|
elements: [
|
||||||
Interpolation(
|
Interpolation(
|
||||||
InterpolatedElement {
|
InterpolatedElement {
|
||||||
range: 7..14,
|
range: 7..13,
|
||||||
node_index: NodeIndex(None),
|
node_index: NodeIndex(None),
|
||||||
expression: Name(
|
expression: Name(
|
||||||
ExprName {
|
ExprName {
|
||||||
|
@ -84,7 +85,7 @@ Module(
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
debug_text: None,
|
debug_text: None,
|
||||||
conversion: None,
|
conversion: Repr,
|
||||||
format_spec: None,
|
format_spec: None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -93,6 +94,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -144,6 +146,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -156,75 +159,91 @@ Module(
|
||||||
Expr(
|
Expr(
|
||||||
StmtExpr {
|
StmtExpr {
|
||||||
node_index: NodeIndex(None),
|
node_index: NodeIndex(None),
|
||||||
range: 24..37,
|
range: 24..28,
|
||||||
value: FString(
|
value: FString(
|
||||||
ExprFString {
|
ExprFString {
|
||||||
node_index: NodeIndex(None),
|
node_index: NodeIndex(None),
|
||||||
range: 24..37,
|
range: 24..28,
|
||||||
value: FStringValue {
|
value: FStringValue {
|
||||||
inner: Concatenated(
|
inner: Single(
|
||||||
[
|
FString(
|
||||||
FString(
|
FString {
|
||||||
FString {
|
range: 24..28,
|
||||||
range: 24..28,
|
node_index: NodeIndex(None),
|
||||||
node_index: NodeIndex(None),
|
elements: [
|
||||||
elements: [
|
Interpolation(
|
||||||
Interpolation(
|
InterpolatedElement {
|
||||||
InterpolatedElement {
|
range: 26..27,
|
||||||
range: 26..27,
|
node_index: NodeIndex(None),
|
||||||
node_index: NodeIndex(None),
|
expression: Name(
|
||||||
expression: Name(
|
ExprName {
|
||||||
ExprName {
|
node_index: NodeIndex(None),
|
||||||
node_index: NodeIndex(None),
|
range: 27..27,
|
||||||
range: 27..27,
|
id: Name(""),
|
||||||
id: Name(""),
|
ctx: Invalid,
|
||||||
ctx: Invalid,
|
},
|
||||||
},
|
),
|
||||||
),
|
debug_text: None,
|
||||||
debug_text: None,
|
conversion: None,
|
||||||
conversion: None,
|
format_spec: None,
|
||||||
format_spec: None,
|
},
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
],
|
flags: FStringFlags {
|
||||||
flags: FStringFlags {
|
quote_style: Double,
|
||||||
quote_style: Double,
|
prefix: Regular,
|
||||||
prefix: Regular,
|
triple_quoted: false,
|
||||||
triple_quoted: false,
|
unclosed: false,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
),
|
},
|
||||||
FString(
|
),
|
||||||
FString {
|
),
|
||||||
range: 29..37,
|
},
|
||||||
node_index: NodeIndex(None),
|
},
|
||||||
elements: [
|
),
|
||||||
Interpolation(
|
},
|
||||||
InterpolatedElement {
|
),
|
||||||
range: 33..34,
|
Expr(
|
||||||
node_index: NodeIndex(None),
|
StmtExpr {
|
||||||
expression: Name(
|
node_index: NodeIndex(None),
|
||||||
ExprName {
|
range: 29..37,
|
||||||
node_index: NodeIndex(None),
|
value: FString(
|
||||||
range: 34..34,
|
ExprFString {
|
||||||
id: Name(""),
|
node_index: NodeIndex(None),
|
||||||
ctx: Invalid,
|
range: 29..37,
|
||||||
},
|
value: FStringValue {
|
||||||
),
|
inner: Single(
|
||||||
debug_text: None,
|
FString(
|
||||||
conversion: None,
|
FString {
|
||||||
format_spec: None,
|
range: 29..37,
|
||||||
},
|
node_index: NodeIndex(None),
|
||||||
),
|
elements: [
|
||||||
],
|
Interpolation(
|
||||||
flags: FStringFlags {
|
InterpolatedElement {
|
||||||
quote_style: Double,
|
range: 33..34,
|
||||||
prefix: Regular,
|
node_index: NodeIndex(None),
|
||||||
triple_quoted: true,
|
expression: Name(
|
||||||
},
|
ExprName {
|
||||||
|
node_index: NodeIndex(None),
|
||||||
|
range: 34..34,
|
||||||
|
id: Name(""),
|
||||||
|
ctx: Invalid,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
debug_text: None,
|
||||||
|
conversion: None,
|
||||||
|
format_spec: None,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
flags: FStringFlags {
|
||||||
|
quote_style: Double,
|
||||||
|
prefix: Regular,
|
||||||
|
triple_quoted: true,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
),
|
},
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -239,23 +258,7 @@ Module(
|
||||||
|
|
||||||
|
|
|
|
||||||
1 | f"{"
|
1 | f"{"
|
||||||
| ^ Syntax Error: missing closing quote in string literal
|
| ^ Syntax Error: Expected an expression
|
||||||
2 | f"{foo!r"
|
|
||||||
3 | f"{foo="
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1 | f"{"
|
|
||||||
| ^ Syntax Error: f-string: unterminated string
|
|
||||||
2 | f"{foo!r"
|
|
||||||
3 | f"{foo="
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1 | f"{"
|
|
||||||
| ^ Syntax Error: f-string: unterminated string
|
|
||||||
2 | f"{foo!r"
|
2 | f"{foo!r"
|
||||||
3 | f"{foo="
|
3 | f"{foo="
|
||||||
|
|
|
|
||||||
|
@ -264,25 +267,7 @@ Module(
|
||||||
|
|
|
|
||||||
1 | f"{"
|
1 | f"{"
|
||||||
2 | f"{foo!r"
|
2 | f"{foo!r"
|
||||||
| ^^ Syntax Error: missing closing quote in string literal
|
| ^ Syntax Error: f-string: expecting '}'
|
||||||
3 | f"{foo="
|
|
||||||
4 | f"{"
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1 | f"{"
|
|
||||||
2 | f"{foo!r"
|
|
||||||
| ^ Syntax Error: f-string: unterminated string
|
|
||||||
3 | f"{foo="
|
|
||||||
4 | f"{"
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1 | f"{"
|
|
||||||
2 | f"{foo!r"
|
|
||||||
| ^ Syntax Error: f-string: unterminated string
|
|
||||||
3 | f"{foo="
|
3 | f"{foo="
|
||||||
4 | f"{"
|
4 | f"{"
|
||||||
|
|
|
|
||||||
|
@ -292,46 +277,7 @@ Module(
|
||||||
1 | f"{"
|
1 | f"{"
|
||||||
2 | f"{foo!r"
|
2 | f"{foo!r"
|
||||||
3 | f"{foo="
|
3 | f"{foo="
|
||||||
| ^^ Syntax Error: f-string: expecting '}'
|
| ^ Syntax Error: f-string: expecting '}'
|
||||||
4 | f"{"
|
|
||||||
5 | f"""{"""
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1 | f"{"
|
|
||||||
2 | f"{foo!r"
|
|
||||||
| ^ Syntax Error: Expected FStringEnd, found Unknown
|
|
||||||
3 | f"{foo="
|
|
||||||
4 | f"{"
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1 | f"{"
|
|
||||||
2 | f"{foo!r"
|
|
||||||
3 | f"{foo="
|
|
||||||
| ^ Syntax Error: missing closing quote in string literal
|
|
||||||
4 | f"{"
|
|
||||||
5 | f"""{"""
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1 | f"{"
|
|
||||||
2 | f"{foo!r"
|
|
||||||
3 | f"{foo="
|
|
||||||
| ^ Syntax Error: f-string: unterminated string
|
|
||||||
4 | f"{"
|
|
||||||
5 | f"""{"""
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1 | f"{"
|
|
||||||
2 | f"{foo!r"
|
|
||||||
3 | f"{foo="
|
|
||||||
| ^ Syntax Error: f-string: unterminated string
|
|
||||||
4 | f"{"
|
4 | f"{"
|
||||||
5 | f"""{"""
|
5 | f"""{"""
|
||||||
|
|
|
|
||||||
|
@ -341,36 +287,14 @@ Module(
|
||||||
2 | f"{foo!r"
|
2 | f"{foo!r"
|
||||||
3 | f"{foo="
|
3 | f"{foo="
|
||||||
4 | f"{"
|
4 | f"{"
|
||||||
| ^ Syntax Error: missing closing quote in string literal
|
| ^ Syntax Error: Expected an expression
|
||||||
5 | f"""{"""
|
5 | f"""{"""
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
3 | f"{foo="
|
|
||||||
4 | f"{"
|
|
||||||
5 | f"""{"""
|
|
||||||
| ^^^^ Syntax Error: Expected FStringEnd, found FStringStart
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
|
||||||
3 | f"{foo="
|
3 | f"{foo="
|
||||||
4 | f"{"
|
4 | f"{"
|
||||||
5 | f"""{"""
|
5 | f"""{"""
|
||||||
| ^^^ Syntax Error: Expected an expression
|
| ^^^ Syntax Error: Expected an expression
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
4 | f"{"
|
|
||||||
5 | f"""{"""
|
|
||||||
| ^ Syntax Error: unexpected EOF while parsing
|
|
||||||
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
4 | f"{"
|
|
||||||
5 | f"""{"""
|
|
||||||
| ^ Syntax Error: f-string: unterminated string
|
|
||||||
|
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -127,6 +128,7 @@ Module(
|
||||||
quote_style: Double,
|
quote_style: Double,
|
||||||
prefix: Regular,
|
prefix: Regular,
|
||||||
triple_quoted: false,
|
triple_quoted: false,
|
||||||
|
unclosed: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue