mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 13:33:50 +00:00
[ruff
] Implement unnecessary-nested-literal
(RUF041
) (#14323)
Co-authored-by: Micha Reiser <micha@reiser.io> Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
187974eff4
commit
11a2929ed7
10 changed files with 770 additions and 1 deletions
31
crates/ruff_linter/resources/test/fixtures/ruff/RUF041.py
vendored
Normal file
31
crates/ruff_linter/resources/test/fixtures/ruff/RUF041.py
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
from typing import Literal
|
||||
import typing as t
|
||||
import typing_extensions
|
||||
|
||||
|
||||
y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
Literal[1, Literal[1]]
|
||||
Literal[1, 2, Literal[1, 2]]
|
||||
Literal[1, Literal[1], Literal[1]]
|
||||
Literal[1, Literal[2], Literal[2]]
|
||||
t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
Literal[
|
||||
1, # comment 1
|
||||
Literal[ # another comment
|
||||
1 # yet annother comment
|
||||
]
|
||||
] # once
|
||||
|
||||
# Ensure issue is only raised once, even on nested literals
|
||||
MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
|
||||
# nested literals, all equivalent to `Literal[1]`
|
||||
Literal[Literal[1]]
|
||||
Literal[Literal[Literal[1], Literal[1]]]
|
||||
Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
|
||||
# OK
|
||||
x: Literal[True, False, True, False]
|
||||
z: Literal[{1, 3, 5}, "foobar", {1,3,5}]
|
||||
typing_extensions.Literal[1, 1, 1]
|
||||
n: Literal["No", "duplicates", "here", 1, "1"]
|
31
crates/ruff_linter/resources/test/fixtures/ruff/RUF041.pyi
vendored
Normal file
31
crates/ruff_linter/resources/test/fixtures/ruff/RUF041.pyi
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
from typing import Literal
|
||||
import typing as t
|
||||
import typing_extensions
|
||||
|
||||
|
||||
y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
Literal[1, Literal[1]]
|
||||
Literal[1, 2, Literal[1, 2]]
|
||||
Literal[1, Literal[1], Literal[1]]
|
||||
Literal[1, Literal[2], Literal[2]]
|
||||
t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
Literal[
|
||||
1, # comment 1
|
||||
Literal[ # another comment
|
||||
1 # yet annother comment
|
||||
]
|
||||
] # once
|
||||
|
||||
# Ensure issue is only raised once, even on nested literals
|
||||
MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
|
||||
# nested literals, all equivalent to `Literal[1]`
|
||||
Literal[Literal[1]]
|
||||
Literal[Literal[Literal[1], Literal[1]]]
|
||||
Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
|
||||
# OK
|
||||
x: Literal[True, False, True, False]
|
||||
z: Literal[{1, 3, 5}, "foobar", {1,3,5}]
|
||||
typing_extensions.Literal[1, 1, 1]
|
||||
n: Literal["No", "duplicates", "here", 1, "1"]
|
|
@ -108,6 +108,7 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
Rule::DuplicateLiteralMember,
|
||||
Rule::RedundantBoolLiteral,
|
||||
Rule::RedundantNoneLiteral,
|
||||
Rule::UnnecessaryNestedLiteral,
|
||||
]) {
|
||||
if !checker.semantic.in_nested_literal() {
|
||||
if checker.enabled(Rule::DuplicateLiteralMember) {
|
||||
|
@ -119,6 +120,9 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
|
|||
if checker.enabled(Rule::RedundantNoneLiteral) {
|
||||
flake8_pyi::rules::redundant_none_literal(checker, expr);
|
||||
}
|
||||
if checker.enabled(Rule::UnnecessaryNestedLiteral) {
|
||||
ruff::rules::unnecessary_nested_literal(checker, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -980,9 +980,10 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
|||
(Ruff, "035") => (RuleGroup::Preview, rules::ruff::rules::UnsafeMarkupUse),
|
||||
(Ruff, "036") => (RuleGroup::Preview, rules::ruff::rules::NoneNotAtEndOfUnion),
|
||||
(Ruff, "038") => (RuleGroup::Preview, rules::ruff::rules::RedundantBoolLiteral),
|
||||
(Ruff, "048") => (RuleGroup::Preview, rules::ruff::rules::MapIntVersionParsing),
|
||||
(Ruff, "039") => (RuleGroup::Preview, rules::ruff::rules::UnrawRePattern),
|
||||
(Ruff, "040") => (RuleGroup::Preview, rules::ruff::rules::InvalidAssertMessageLiteralArgument),
|
||||
(Ruff, "041") => (RuleGroup::Preview, rules::ruff::rules::UnnecessaryNestedLiteral),
|
||||
(Ruff, "048") => (RuleGroup::Preview, rules::ruff::rules::MapIntVersionParsing),
|
||||
(Ruff, "100") => (RuleGroup::Stable, rules::ruff::rules::UnusedNOQA),
|
||||
(Ruff, "101") => (RuleGroup::Stable, rules::ruff::rules::RedirectedNOQA),
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ mod tests {
|
|||
#[test_case(Rule::RedundantBoolLiteral, Path::new("RUF038.py"))]
|
||||
#[test_case(Rule::RedundantBoolLiteral, Path::new("RUF038.pyi"))]
|
||||
#[test_case(Rule::InvalidAssertMessageLiteralArgument, Path::new("RUF040.py"))]
|
||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.py"))]
|
||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.pyi"))]
|
||||
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
|
|
|
@ -32,6 +32,7 @@ pub(crate) use static_key_dict_comprehension::*;
|
|||
pub(crate) use test_rules::*;
|
||||
pub(crate) use unnecessary_iterable_allocation_for_first_element::*;
|
||||
pub(crate) use unnecessary_key_check::*;
|
||||
pub(crate) use unnecessary_nested_literal::*;
|
||||
pub(crate) use unraw_re_pattern::*;
|
||||
pub(crate) use unsafe_markup_use::*;
|
||||
pub(crate) use unused_async::*;
|
||||
|
@ -77,6 +78,7 @@ mod suppression_comment_visitor;
|
|||
pub(crate) mod test_rules;
|
||||
mod unnecessary_iterable_allocation_for_first_element;
|
||||
mod unnecessary_key_check;
|
||||
mod unnecessary_nested_literal;
|
||||
mod unraw_re_pattern;
|
||||
mod unsafe_markup_use;
|
||||
mod unused_async;
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
use ruff_diagnostics::{Applicability, Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||
use ruff_python_ast::{AnyNodeRef, Expr, ExprContext, ExprSubscript, ExprTuple};
|
||||
use ruff_python_semantic::analyze::typing::traverse_literal;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for unnecessary nested `Literal`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// Prefer using a single `Literal`, which is equivalent and more concise.
|
||||
///
|
||||
/// Parameterization of literals by other literals is supported as an ergonomic
|
||||
/// feature as proposed in [PEP 586], to enable patterns such as:
|
||||
/// ```python
|
||||
/// ReadOnlyMode = Literal["r", "r+"]
|
||||
/// WriteAndTruncateMode = Literal["w", "w+", "wt", "w+t"]
|
||||
/// WriteNoTruncateMode = Literal["r+", "r+t"]
|
||||
/// AppendMode = Literal["a", "a+", "at", "a+t"]
|
||||
///
|
||||
/// AllModes = Literal[ReadOnlyMode, WriteAndTruncateMode,
|
||||
/// WriteNoTruncateMode, AppendMode]
|
||||
/// ```
|
||||
///
|
||||
/// As a consequence, type checkers also support nesting of literals
|
||||
/// which is less readable than a flat `Literal`:
|
||||
/// ```python
|
||||
/// AllModes = Literal[Literal["r", "r+"], Literal["w", "w+", "wt", "w+t"],
|
||||
/// Literal["r+", "r+t"], Literal["a", "a+", "at", "a+t"]]
|
||||
/// ```
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// AllModes = Literal[
|
||||
/// Literal["r", "r+"],
|
||||
/// Literal["w", "w+", "wt", "w+t"],
|
||||
/// Literal["r+", "r+t"],
|
||||
/// Literal["a", "a+", "at", "a+t"],
|
||||
/// ]
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// AllModes = Literal[
|
||||
/// "r", "r+", "w", "w+", "wt", "w+t", "r+", "r+t", "a", "a+", "at", "a+t"
|
||||
/// ]
|
||||
/// ```
|
||||
///
|
||||
/// or assign the literal to a variable as in the first example.
|
||||
///
|
||||
/// ## Fix safety
|
||||
/// The fix for this rule is marked as unsafe when the `Literal` slice is split
|
||||
/// across multiple lines and some of the lines have trailing comments.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Typing documentation: Legal parameters for `Literal` at type check time](https://typing.readthedocs.io/en/latest/spec/literal.html#legal-parameters-for-literal-at-type-check-time)
|
||||
///
|
||||
/// [PEP 586](https://peps.python.org/pep-0586/)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct UnnecessaryNestedLiteral;
|
||||
|
||||
impl Violation for UnnecessaryNestedLiteral {
|
||||
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"Unnecessary nested `Literal`".to_string()
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> Option<String> {
|
||||
Some("Replace with flattened `Literal`".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// RUF039
|
||||
pub(crate) fn unnecessary_nested_literal<'a>(checker: &mut Checker, literal_expr: &'a Expr) {
|
||||
let mut is_nested = false;
|
||||
|
||||
// Traverse the type expressions in the `Literal`.
|
||||
traverse_literal(
|
||||
&mut |_: &'a Expr, parent: &'a Expr| {
|
||||
// If the parent is not equal to the `literal_expr` then we know we are traversing recursively.
|
||||
if !AnyNodeRef::ptr_eq(parent.into(), literal_expr.into()) {
|
||||
is_nested = true;
|
||||
};
|
||||
},
|
||||
checker.semantic(),
|
||||
literal_expr,
|
||||
);
|
||||
|
||||
if !is_nested {
|
||||
return;
|
||||
}
|
||||
|
||||
// Collect the literal nodes for the fix
|
||||
let mut nodes: Vec<&Expr> = Vec::new();
|
||||
|
||||
traverse_literal(
|
||||
&mut |expr, _| {
|
||||
nodes.push(expr);
|
||||
},
|
||||
checker.semantic(),
|
||||
literal_expr,
|
||||
);
|
||||
|
||||
let mut diagnostic = Diagnostic::new(UnnecessaryNestedLiteral, literal_expr.range());
|
||||
|
||||
// Create a [`Fix`] that flattens all nodes.
|
||||
if let Expr::Subscript(subscript) = literal_expr {
|
||||
let subscript = Expr::Subscript(ExprSubscript {
|
||||
slice: Box::new(if let [elt] = nodes.as_slice() {
|
||||
(*elt).clone()
|
||||
} else {
|
||||
Expr::Tuple(ExprTuple {
|
||||
elts: nodes.into_iter().cloned().collect(),
|
||||
range: TextRange::default(),
|
||||
ctx: ExprContext::Load,
|
||||
parenthesized: false,
|
||||
})
|
||||
}),
|
||||
value: subscript.value.clone(),
|
||||
range: TextRange::default(),
|
||||
ctx: ExprContext::Load,
|
||||
});
|
||||
let fix = Fix::applicable_edit(
|
||||
Edit::range_replacement(checker.generator().expr(&subscript), literal_expr.range()),
|
||||
if checker.comment_ranges().intersects(literal_expr.range()) {
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
},
|
||||
);
|
||||
diagnostic.set_fix(fix);
|
||||
};
|
||||
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
RUF041.py:6:4: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
7 | Literal[1, Literal[1]]
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
3 3 | import typing_extensions
|
||||
4 4 |
|
||||
5 5 |
|
||||
6 |-y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
6 |+y: Literal[1, print("hello"), 3, 4, 1]
|
||||
7 7 | Literal[1, Literal[1]]
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
|
||||
RUF041.py:7:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 | Literal[1, Literal[1]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
4 4 |
|
||||
5 5 |
|
||||
6 6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 |-Literal[1, Literal[1]]
|
||||
7 |+Literal[1, 1]
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
|
||||
RUF041.py:8:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 | Literal[1, Literal[1]]
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
5 5 |
|
||||
6 6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 7 | Literal[1, Literal[1]]
|
||||
8 |-Literal[1, 2, Literal[1, 2]]
|
||||
8 |+Literal[1, 2, 1, 2]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
|
||||
RUF041.py:9:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
7 | Literal[1, Literal[1]]
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
6 6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 7 | Literal[1, Literal[1]]
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 |-Literal[1, Literal[1], Literal[1]]
|
||||
9 |+Literal[1, 1, 1]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 12 | Literal[
|
||||
|
||||
RUF041.py:10:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 | Literal[
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
7 7 | Literal[1, Literal[1]]
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 |-Literal[1, Literal[2], Literal[2]]
|
||||
10 |+Literal[1, 2, 2]
|
||||
11 11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 12 | Literal[
|
||||
13 13 | 1, # comment 1
|
||||
|
||||
RUF041.py:11:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
12 | Literal[
|
||||
13 | 1, # comment 1
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 |-t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
11 |+t.Literal[1, 2, 1]
|
||||
12 12 | Literal[
|
||||
13 13 | 1, # comment 1
|
||||
14 14 | Literal[ # another comment
|
||||
|
||||
RUF041.py:12:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 | / Literal[
|
||||
13 | | 1, # comment 1
|
||||
14 | | Literal[ # another comment
|
||||
15 | | 1 # yet annother comment
|
||||
16 | | ]
|
||||
17 | | ] # once
|
||||
| |_^ RUF041
|
||||
18 |
|
||||
19 | # Ensure issue is only raised once, even on nested literals
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Unsafe fix
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 |-Literal[
|
||||
13 |- 1, # comment 1
|
||||
14 |- Literal[ # another comment
|
||||
15 |- 1 # yet annother comment
|
||||
16 |- ]
|
||||
17 |-] # once
|
||||
12 |+Literal[1, 1] # once
|
||||
18 13 |
|
||||
19 14 | # Ensure issue is only raised once, even on nested literals
|
||||
20 15 | MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
|
||||
RUF041.py:20:10: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
19 | # Ensure issue is only raised once, even on nested literals
|
||||
20 | MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
21 |
|
||||
22 | # nested literals, all equivalent to `Literal[1]`
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
17 17 | ] # once
|
||||
18 18 |
|
||||
19 19 | # Ensure issue is only raised once, even on nested literals
|
||||
20 |-MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
20 |+MyType = Literal["foo", True, False, True, "bar"]
|
||||
21 21 |
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
|
||||
RUF041.py:23:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 | Literal[Literal[1]]
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
20 20 | MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
21 21 |
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 |-Literal[Literal[1]]
|
||||
23 |+Literal[1]
|
||||
24 24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
26 26 |
|
||||
|
||||
RUF041.py:24:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 | Literal[Literal[1]]
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
21 21 |
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
24 |-Literal[Literal[Literal[1], Literal[1]]]
|
||||
24 |+Literal[1, 1]
|
||||
25 25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
26 26 |
|
||||
27 27 | # OK
|
||||
|
||||
RUF041.py:24:9: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 | Literal[Literal[1]]
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
21 21 |
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
24 |-Literal[Literal[Literal[1], Literal[1]]]
|
||||
24 |+Literal[Literal[1, 1]]
|
||||
25 25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
26 26 |
|
||||
27 27 | # OK
|
||||
|
||||
RUF041.py:25:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
23 | Literal[Literal[1]]
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
26 |
|
||||
27 | # OK
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
24 24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 |-Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
25 |+Literal[1, 1]
|
||||
26 26 |
|
||||
27 27 | # OK
|
||||
28 28 | x: Literal[True, False, True, False]
|
||||
|
||||
RUF041.py:25:29: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
23 | Literal[Literal[1]]
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
26 |
|
||||
27 | # OK
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
24 24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 |-Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
25 |+Literal[Literal[1], Literal[Literal[1]]]
|
||||
26 26 |
|
||||
27 27 | # OK
|
||||
28 28 | x: Literal[True, False, True, False]
|
|
@ -0,0 +1,279 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
snapshot_kind: text
|
||||
---
|
||||
RUF041.pyi:6:4: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
7 | Literal[1, Literal[1]]
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
3 3 | import typing_extensions
|
||||
4 4 |
|
||||
5 5 |
|
||||
6 |-y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
6 |+y: Literal[1, print("hello"), 3, 4, 1]
|
||||
7 7 | Literal[1, Literal[1]]
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
|
||||
RUF041.pyi:7:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 | Literal[1, Literal[1]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
4 4 |
|
||||
5 5 |
|
||||
6 6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 |-Literal[1, Literal[1]]
|
||||
7 |+Literal[1, 1]
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
|
||||
RUF041.pyi:8:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 | Literal[1, Literal[1]]
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
5 5 |
|
||||
6 6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 7 | Literal[1, Literal[1]]
|
||||
8 |-Literal[1, 2, Literal[1, 2]]
|
||||
8 |+Literal[1, 2, 1, 2]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
|
||||
RUF041.pyi:9:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
7 | Literal[1, Literal[1]]
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
6 6 | y: Literal[1, print("hello"), 3, Literal[4, 1]]
|
||||
7 7 | Literal[1, Literal[1]]
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 |-Literal[1, Literal[1], Literal[1]]
|
||||
9 |+Literal[1, 1, 1]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 12 | Literal[
|
||||
|
||||
RUF041.pyi:10:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 | Literal[
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
7 7 | Literal[1, Literal[1]]
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 |-Literal[1, Literal[2], Literal[2]]
|
||||
10 |+Literal[1, 2, 2]
|
||||
11 11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 12 | Literal[
|
||||
13 13 | 1, # comment 1
|
||||
|
||||
RUF041.pyi:11:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
12 | Literal[
|
||||
13 | 1, # comment 1
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
8 8 | Literal[1, 2, Literal[1, 2]]
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 |-t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
11 |+t.Literal[1, 2, 1]
|
||||
12 12 | Literal[
|
||||
13 13 | 1, # comment 1
|
||||
14 14 | Literal[ # another comment
|
||||
|
||||
RUF041.pyi:12:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 | / Literal[
|
||||
13 | | 1, # comment 1
|
||||
14 | | Literal[ # another comment
|
||||
15 | | 1 # yet annother comment
|
||||
16 | | ]
|
||||
17 | | ] # once
|
||||
| |_^ RUF041
|
||||
18 |
|
||||
19 | # Ensure issue is only raised once, even on nested literals
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Unsafe fix
|
||||
9 9 | Literal[1, Literal[1], Literal[1]]
|
||||
10 10 | Literal[1, Literal[2], Literal[2]]
|
||||
11 11 | t.Literal[1, t.Literal[2, t.Literal[1]]]
|
||||
12 |-Literal[
|
||||
13 |- 1, # comment 1
|
||||
14 |- Literal[ # another comment
|
||||
15 |- 1 # yet annother comment
|
||||
16 |- ]
|
||||
17 |-] # once
|
||||
12 |+Literal[1, 1] # once
|
||||
18 13 |
|
||||
19 14 | # Ensure issue is only raised once, even on nested literals
|
||||
20 15 | MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
|
||||
RUF041.pyi:20:10: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
19 | # Ensure issue is only raised once, even on nested literals
|
||||
20 | MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
21 |
|
||||
22 | # nested literals, all equivalent to `Literal[1]`
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
17 17 | ] # once
|
||||
18 18 |
|
||||
19 19 | # Ensure issue is only raised once, even on nested literals
|
||||
20 |-MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
20 |+MyType = Literal["foo", True, False, True, "bar"]
|
||||
21 21 |
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
|
||||
RUF041.pyi:23:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 | Literal[Literal[1]]
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
20 20 | MyType = Literal["foo", Literal[True, False, True], "bar"]
|
||||
21 21 |
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 |-Literal[Literal[1]]
|
||||
23 |+Literal[1]
|
||||
24 24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
26 26 |
|
||||
|
||||
RUF041.pyi:24:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 | Literal[Literal[1]]
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
21 21 |
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
24 |-Literal[Literal[Literal[1], Literal[1]]]
|
||||
24 |+Literal[1, 1]
|
||||
25 25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
26 26 |
|
||||
27 27 | # OK
|
||||
|
||||
RUF041.pyi:24:9: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 | Literal[Literal[1]]
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
21 21 |
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
24 |-Literal[Literal[Literal[1], Literal[1]]]
|
||||
24 |+Literal[Literal[1, 1]]
|
||||
25 25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
26 26 |
|
||||
27 27 | # OK
|
||||
|
||||
RUF041.pyi:25:1: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
23 | Literal[Literal[1]]
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
26 |
|
||||
27 | # OK
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
24 24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 |-Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
25 |+Literal[1, 1]
|
||||
26 26 |
|
||||
27 27 | # OK
|
||||
28 28 | x: Literal[True, False, True, False]
|
||||
|
||||
RUF041.pyi:25:29: RUF041 [*] Unnecessary nested `Literal`
|
||||
|
|
||||
23 | Literal[Literal[1]]
|
||||
24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 | Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
| ^^^^^^^^^^^^^^^^^^^ RUF041
|
||||
26 |
|
||||
27 | # OK
|
||||
|
|
||||
= help: Replace with flattened `Literal`
|
||||
|
||||
ℹ Safe fix
|
||||
22 22 | # nested literals, all equivalent to `Literal[1]`
|
||||
23 23 | Literal[Literal[1]]
|
||||
24 24 | Literal[Literal[Literal[1], Literal[1]]]
|
||||
25 |-Literal[Literal[1], Literal[Literal[Literal[1]]]]
|
||||
25 |+Literal[Literal[1], Literal[Literal[1]]]
|
||||
26 26 |
|
||||
27 27 | # OK
|
||||
28 28 | x: Literal[True, False, True, False]
|
1
ruff.schema.json
generated
1
ruff.schema.json
generated
|
@ -3841,6 +3841,7 @@
|
|||
"RUF039",
|
||||
"RUF04",
|
||||
"RUF040",
|
||||
"RUF041",
|
||||
"RUF048",
|
||||
"RUF1",
|
||||
"RUF10",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue