mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:41:23 +00:00
[ruff
] Handle empty t-strings in unnecessary-empty-iterable-within-deque-call
(RUF037
) (#20045)
Adds a method to `TStringValue` to detect whether the t-string is empty _as an iterable_. Note the subtlety here that, unlike f-strings, an empty t-string is still truthy (i.e. `bool(t"")==True`). Closes #19951
This commit is contained in:
parent
0e9d77e43a
commit
0b6ce1c788
4 changed files with 66 additions and 1 deletions
|
@ -102,3 +102,8 @@ deque("abc") # OK
|
|||
deque(b"abc") # OK
|
||||
deque(f"" "a") # OK
|
||||
deque(f"{x}" "") # OK
|
||||
|
||||
# https://github.com/astral-sh/ruff/issues/19951
|
||||
deque(t"")
|
||||
deque(t"" t"")
|
||||
deque(t"{""}") # OK
|
||||
|
|
|
@ -103,6 +103,7 @@ pub(crate) fn unnecessary_literal_within_deque_call(checker: &Checker, deque: &a
|
|||
Expr::StringLiteral(string) => string.value.is_empty(),
|
||||
Expr::BytesLiteral(bytes) => bytes.value.is_empty(),
|
||||
Expr::FString(fstring) => fstring.value.is_empty_literal(),
|
||||
Expr::TString(tstring) => tstring.value.is_empty_iterable(),
|
||||
_ => false,
|
||||
};
|
||||
if !is_empty_literal {
|
||||
|
|
|
@ -383,3 +383,42 @@ help: Replace with `deque()`
|
|||
101 101 | deque("abc") # OK
|
||||
102 102 | deque(b"abc") # OK
|
||||
103 103 | deque(f"" "a") # OK
|
||||
|
||||
RUF037 [*] Unnecessary empty iterable within a deque call
|
||||
--> RUF037.py:107:1
|
||||
|
|
||||
106 | # https://github.com/astral-sh/ruff/issues/19951
|
||||
107 | deque(t"")
|
||||
| ^^^^^^^^^^
|
||||
108 | deque(t"" t"")
|
||||
109 | deque(t"{""}") # OK
|
||||
|
|
||||
help: Replace with `deque()`
|
||||
|
||||
ℹ Safe fix
|
||||
104 104 | deque(f"{x}" "") # OK
|
||||
105 105 |
|
||||
106 106 | # https://github.com/astral-sh/ruff/issues/19951
|
||||
107 |-deque(t"")
|
||||
107 |+deque()
|
||||
108 108 | deque(t"" t"")
|
||||
109 109 | deque(t"{""}") # OK
|
||||
|
||||
RUF037 [*] Unnecessary empty iterable within a deque call
|
||||
--> RUF037.py:108:1
|
||||
|
|
||||
106 | # https://github.com/astral-sh/ruff/issues/19951
|
||||
107 | deque(t"")
|
||||
108 | deque(t"" t"")
|
||||
| ^^^^^^^^^^^^^^^
|
||||
109 | deque(t"{""}") # OK
|
||||
|
|
||||
help: Replace with `deque()`
|
||||
|
||||
ℹ Safe fix
|
||||
105 105 |
|
||||
106 106 | # https://github.com/astral-sh/ruff/issues/19951
|
||||
107 107 | deque(t"")
|
||||
108 |-deque(t"" t"")
|
||||
108 |+deque()
|
||||
109 109 | deque(t"{""}") # OK
|
||||
|
|
|
@ -515,7 +515,7 @@ impl FStringValue {
|
|||
|
||||
/// Returns `true` if the node represents an empty f-string literal.
|
||||
///
|
||||
/// Noteh that a [`FStringValue`] node will always have >= 1 [`FStringPart`]s inside it.
|
||||
/// Note that a [`FStringValue`] node will always have >= 1 [`FStringPart`]s inside it.
|
||||
/// This method checks whether the value of the concatenated parts is equal to the empty
|
||||
/// f-string, not whether the f-string has 0 parts inside it.
|
||||
pub fn is_empty_literal(&self) -> bool {
|
||||
|
@ -681,6 +681,22 @@ impl TStringValue {
|
|||
pub fn elements(&self) -> impl Iterator<Item = &InterpolatedStringElement> {
|
||||
self.iter().flat_map(|tstring| tstring.elements.iter())
|
||||
}
|
||||
|
||||
/// Returns `true` if the node represents an empty t-string in the
|
||||
/// sense that `__iter__` returns an empty iterable.
|
||||
///
|
||||
/// Beware that empty t-strings are still truthy, i.e. `bool(t"") == True`.
|
||||
///
|
||||
/// Note that a [`TStringValue`] node will always contain at least one
|
||||
/// [`TString`] node. This method checks whether each of the constituent
|
||||
/// t-strings (in an implicitly concatenated t-string) are empty
|
||||
/// in the above sense.
|
||||
pub fn is_empty_iterable(&self) -> bool {
|
||||
match &self.inner {
|
||||
TStringValueInner::Single(tstring) => tstring.is_empty(),
|
||||
TStringValueInner::Concatenated(tstrings) => tstrings.iter().all(TString::is_empty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a TStringValue {
|
||||
|
@ -1182,6 +1198,10 @@ impl TString {
|
|||
pub fn quote_style(&self) -> Quote {
|
||||
self.flags.quote_style()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.elements.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TString> for Expr {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue