diff --git a/crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs b/crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs index 187837905f..1303a2b25b 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs +++ b/crates/ruff_linter/src/rules/flake8_pyi/rules/unnecessary_literal_union.rs @@ -1,9 +1,10 @@ -use ruff_diagnostics::{Diagnostic, Violation}; +use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::{self as ast, Expr}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; +use crate::registry::AsRule; use crate::rules::flake8_pyi::helpers::traverse_union; /// ## What it does @@ -31,7 +32,7 @@ pub struct UnnecessaryLiteralUnion { members: Vec, } -impl Violation for UnnecessaryLiteralUnion { +impl AlwaysFixableViolation for UnnecessaryLiteralUnion { #[derive_message_formats] fn message(&self) -> String { format!( @@ -39,13 +40,17 @@ impl Violation for UnnecessaryLiteralUnion { self.members.join(", ") ) } + + fn fix_title(&self) -> String { + format!("Replace with a single `Literal`") + } } /// PYI030 pub(crate) fn unnecessary_literal_union<'a>(checker: &mut Checker, expr: &'a Expr) { let mut literal_exprs = Vec::new(); - // Adds a member to `literal_exprs` if it is a `Literal` annotation + // Adds a member to `literal_exprs` if it is a `Literal` annotation. let mut collect_literal_expr = |expr: &'a Expr, _| { if let Expr::Subscript(ast::ExprSubscript { value, slice, .. }) = expr { if checker.semantic().match_typing_expr(value, "Literal") { @@ -54,21 +59,30 @@ pub(crate) fn unnecessary_literal_union<'a>(checker: &mut Checker, expr: &'a Exp } }; - // Traverse the union, collect all literal members + // Traverse the union, collect all literal members. traverse_union(&mut collect_literal_expr, checker.semantic(), expr, None); - // Raise a violation if more than one + // Raise a violation if more than one. if literal_exprs.len() > 1 { - let diagnostic = Diagnostic::new( + let literal_members: Vec = literal_exprs + .into_iter() + .map(|expr| checker.locator().slice(expr.as_ref()).to_string()) + .collect(); + + let mut diagnostic = Diagnostic::new( UnnecessaryLiteralUnion { - members: literal_exprs - .into_iter() - .map(|expr| checker.locator().slice(expr.as_ref()).to_string()) - .collect(), + members: literal_members.clone(), }, expr.range(), ); + if checker.patch(diagnostic.kind.rule()) { + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( + format!("Literal[{}]", literal_members.join(", ")), + expr.range(), + ))); + } + checker.diagnostics.push(diagnostic); } } diff --git a/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI030_PYI030.py.snap b/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI030_PYI030.py.snap index 8f6838bde1..feaf41e790 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI030_PYI030.py.snap +++ b/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI030_PYI030.py.snap @@ -1,7 +1,7 @@ --- source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs --- -PYI030.py:9:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +PYI030.py:9:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 8 | # Should emit for duplicate field types. 9 | field2: Literal[1] | Literal[2] # Error @@ -9,24 +9,57 @@ PYI030.py:9:9: PYI030 Multiple literal members in a union. Use a single literal, 10 | 11 | # Should emit for union types in arguments. | + = help: Replace with a single `Literal` -PYI030.py:12:17: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +6 6 | field1: Literal[1] # OK +7 7 | +8 8 | # Should emit for duplicate field types. +9 |-field2: Literal[1] | Literal[2] # Error + 9 |+field2: Literal[1, 2] # Error +10 10 | +11 11 | # Should emit for union types in arguments. +12 12 | def func1(arg1: Literal[1] | Literal[2]): # Error + +PYI030.py:12:17: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 11 | # Should emit for union types in arguments. 12 | def func1(arg1: Literal[1] | Literal[2]): # Error | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 13 | print(arg1) | + = help: Replace with a single `Literal` -PYI030.py:17:16: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +9 9 | field2: Literal[1] | Literal[2] # Error +10 10 | +11 11 | # Should emit for union types in arguments. +12 |-def func1(arg1: Literal[1] | Literal[2]): # Error + 12 |+def func1(arg1: Literal[1, 2]): # Error +13 13 | print(arg1) +14 14 | +15 15 | + +PYI030.py:17:16: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 16 | # Should emit for unions in return types. 17 | def func2() -> Literal[1] | Literal[2]: # Error | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 18 | return "my Literal[1]ing" | + = help: Replace with a single `Literal` -PYI030.py:22:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +14 14 | +15 15 | +16 16 | # Should emit for unions in return types. +17 |-def func2() -> Literal[1] | Literal[2]: # Error + 17 |+def func2() -> Literal[1, 2]: # Error +18 18 | return "my Literal[1]ing" +19 19 | +20 20 | + +PYI030.py:22:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 21 | # Should emit in longer unions, even if not directly adjacent. 22 | field3: Literal[1] | Literal[2] | str # Error @@ -34,8 +67,19 @@ PYI030.py:22:9: PYI030 Multiple literal members in a union. Use a single literal 23 | field4: str | Literal[1] | Literal[2] # Error 24 | field5: Literal[1] | str | Literal[2] # Error | + = help: Replace with a single `Literal` -PYI030.py:23:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +19 19 | +20 20 | +21 21 | # Should emit in longer unions, even if not directly adjacent. +22 |-field3: Literal[1] | Literal[2] | str # Error + 22 |+field3: Literal[1, 2] # Error +23 23 | field4: str | Literal[1] | Literal[2] # Error +24 24 | field5: Literal[1] | str | Literal[2] # Error +25 25 | field6: Literal[1] | bool | Literal[2] | str # Error + +PYI030.py:23:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 21 | # Should emit in longer unions, even if not directly adjacent. 22 | field3: Literal[1] | Literal[2] | str # Error @@ -44,8 +88,19 @@ PYI030.py:23:9: PYI030 Multiple literal members in a union. Use a single literal 24 | field5: Literal[1] | str | Literal[2] # Error 25 | field6: Literal[1] | bool | Literal[2] | str # Error | + = help: Replace with a single `Literal` -PYI030.py:24:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +20 20 | +21 21 | # Should emit in longer unions, even if not directly adjacent. +22 22 | field3: Literal[1] | Literal[2] | str # Error +23 |-field4: str | Literal[1] | Literal[2] # Error + 23 |+field4: Literal[1, 2] # Error +24 24 | field5: Literal[1] | str | Literal[2] # Error +25 25 | field6: Literal[1] | bool | Literal[2] | str # Error +26 26 | + +PYI030.py:24:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 22 | field3: Literal[1] | Literal[2] | str # Error 23 | field4: str | Literal[1] | Literal[2] # Error @@ -53,8 +108,19 @@ PYI030.py:24:9: PYI030 Multiple literal members in a union. Use a single literal | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 25 | field6: Literal[1] | bool | Literal[2] | str # Error | + = help: Replace with a single `Literal` -PYI030.py:25:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +21 21 | # Should emit in longer unions, even if not directly adjacent. +22 22 | field3: Literal[1] | Literal[2] | str # Error +23 23 | field4: str | Literal[1] | Literal[2] # Error +24 |-field5: Literal[1] | str | Literal[2] # Error + 24 |+field5: Literal[1, 2] # Error +25 25 | field6: Literal[1] | bool | Literal[2] | str # Error +26 26 | +27 27 | # Should emit for non-type unions. + +PYI030.py:25:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 23 | field4: str | Literal[1] | Literal[2] # Error 24 | field5: Literal[1] | str | Literal[2] # Error @@ -63,8 +129,19 @@ PYI030.py:25:9: PYI030 Multiple literal members in a union. Use a single literal 26 | 27 | # Should emit for non-type unions. | + = help: Replace with a single `Literal` -PYI030.py:28:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +22 22 | field3: Literal[1] | Literal[2] | str # Error +23 23 | field4: str | Literal[1] | Literal[2] # Error +24 24 | field5: Literal[1] | str | Literal[2] # Error +25 |-field6: Literal[1] | bool | Literal[2] | str # Error + 25 |+field6: Literal[1, 2] # Error +26 26 | +27 27 | # Should emit for non-type unions. +28 28 | field7 = Literal[1] | Literal[2] # Error + +PYI030.py:28:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 27 | # Should emit for non-type unions. 28 | field7 = Literal[1] | Literal[2] # Error @@ -72,8 +149,19 @@ PYI030.py:28:10: PYI030 Multiple literal members in a union. Use a single litera 29 | 30 | # Should emit for parenthesized unions. | + = help: Replace with a single `Literal` -PYI030.py:31:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +25 25 | field6: Literal[1] | bool | Literal[2] | str # Error +26 26 | +27 27 | # Should emit for non-type unions. +28 |-field7 = Literal[1] | Literal[2] # Error + 28 |+field7 = Literal[1, 2] # Error +29 29 | +30 30 | # Should emit for parenthesized unions. +31 31 | field8: Literal[1] | (Literal[2] | str) # Error + +PYI030.py:31:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 30 | # Should emit for parenthesized unions. 31 | field8: Literal[1] | (Literal[2] | str) # Error @@ -81,16 +169,38 @@ PYI030.py:31:9: PYI030 Multiple literal members in a union. Use a single literal 32 | 33 | # Should handle user parentheses when fixing. | + = help: Replace with a single `Literal` -PYI030.py:34:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +28 28 | field7 = Literal[1] | Literal[2] # Error +29 29 | +30 30 | # Should emit for parenthesized unions. +31 |-field8: Literal[1] | (Literal[2] | str) # Error + 31 |+field8: Literal[1, 2] # Error +32 32 | +33 33 | # Should handle user parentheses when fixing. +34 34 | field9: Literal[1] | (Literal[2] | str) # Error + +PYI030.py:34:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 33 | # Should handle user parentheses when fixing. 34 | field9: Literal[1] | (Literal[2] | str) # Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 35 | field10: (Literal[1] | str) | Literal[2] # Error | + = help: Replace with a single `Literal` -PYI030.py:35:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +31 31 | field8: Literal[1] | (Literal[2] | str) # Error +32 32 | +33 33 | # Should handle user parentheses when fixing. +34 |-field9: Literal[1] | (Literal[2] | str) # Error + 34 |+field9: Literal[1, 2] # Error +35 35 | field10: (Literal[1] | str) | Literal[2] # Error +36 36 | +37 37 | # Should emit for union in generic parent type. + +PYI030.py:35:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 33 | # Should handle user parentheses when fixing. 34 | field9: Literal[1] | (Literal[2] | str) # Error @@ -99,12 +209,31 @@ PYI030.py:35:10: PYI030 Multiple literal members in a union. Use a single litera 36 | 37 | # Should emit for union in generic parent type. | + = help: Replace with a single `Literal` -PYI030.py:38:15: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +32 32 | +33 33 | # Should handle user parentheses when fixing. +34 34 | field9: Literal[1] | (Literal[2] | str) # Error +35 |-field10: (Literal[1] | str) | Literal[2] # Error + 35 |+field10: Literal[1, 2] # Error +36 36 | +37 37 | # Should emit for union in generic parent type. +38 38 | field11: dict[Literal[1] | Literal[2], str] # Error + +PYI030.py:38:15: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 37 | # Should emit for union in generic parent type. 38 | field11: dict[Literal[1] | Literal[2], str] # Error | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 | + = help: Replace with a single `Literal` + +ℹ Fix +35 35 | field10: (Literal[1] | str) | Literal[2] # Error +36 36 | +37 37 | # Should emit for union in generic parent type. +38 |-field11: dict[Literal[1] | Literal[2], str] # Error + 38 |+field11: dict[Literal[1, 2], str] # Error diff --git a/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI030_PYI030.pyi.snap b/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI030_PYI030.pyi.snap index 6e9214a8a4..c496520623 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI030_PYI030.pyi.snap +++ b/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI030_PYI030.pyi.snap @@ -1,7 +1,7 @@ --- source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs --- -PYI030.pyi:9:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +PYI030.pyi:9:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 8 | # Should emit for duplicate field types. 9 | field2: Literal[1] | Literal[2] # Error @@ -9,24 +9,57 @@ PYI030.pyi:9:9: PYI030 Multiple literal members in a union. Use a single literal 10 | 11 | # Should emit for union types in arguments. | + = help: Replace with a single `Literal` -PYI030.pyi:12:17: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +6 6 | field1: Literal[1] # OK +7 7 | +8 8 | # Should emit for duplicate field types. +9 |-field2: Literal[1] | Literal[2] # Error + 9 |+field2: Literal[1, 2] # Error +10 10 | +11 11 | # Should emit for union types in arguments. +12 12 | def func1(arg1: Literal[1] | Literal[2]): # Error + +PYI030.pyi:12:17: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 11 | # Should emit for union types in arguments. 12 | def func1(arg1: Literal[1] | Literal[2]): # Error | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 13 | print(arg1) | + = help: Replace with a single `Literal` -PYI030.pyi:17:16: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +9 9 | field2: Literal[1] | Literal[2] # Error +10 10 | +11 11 | # Should emit for union types in arguments. +12 |-def func1(arg1: Literal[1] | Literal[2]): # Error + 12 |+def func1(arg1: Literal[1, 2]): # Error +13 13 | print(arg1) +14 14 | +15 15 | + +PYI030.pyi:17:16: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 16 | # Should emit for unions in return types. 17 | def func2() -> Literal[1] | Literal[2]: # Error | ^^^^^^^^^^^^^^^^^^^^^^^ PYI030 18 | return "my Literal[1]ing" | + = help: Replace with a single `Literal` -PYI030.pyi:22:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +14 14 | +15 15 | +16 16 | # Should emit for unions in return types. +17 |-def func2() -> Literal[1] | Literal[2]: # Error + 17 |+def func2() -> Literal[1, 2]: # Error +18 18 | return "my Literal[1]ing" +19 19 | +20 20 | + +PYI030.pyi:22:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 21 | # Should emit in longer unions, even if not directly adjacent. 22 | field3: Literal[1] | Literal[2] | str # Error @@ -34,8 +67,19 @@ PYI030.pyi:22:9: PYI030 Multiple literal members in a union. Use a single litera 23 | field4: str | Literal[1] | Literal[2] # Error 24 | field5: Literal[1] | str | Literal[2] # Error | + = help: Replace with a single `Literal` -PYI030.pyi:23:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +19 19 | +20 20 | +21 21 | # Should emit in longer unions, even if not directly adjacent. +22 |-field3: Literal[1] | Literal[2] | str # Error + 22 |+field3: Literal[1, 2] # Error +23 23 | field4: str | Literal[1] | Literal[2] # Error +24 24 | field5: Literal[1] | str | Literal[2] # Error +25 25 | field6: Literal[1] | bool | Literal[2] | str # Error + +PYI030.pyi:23:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 21 | # Should emit in longer unions, even if not directly adjacent. 22 | field3: Literal[1] | Literal[2] | str # Error @@ -44,8 +88,19 @@ PYI030.pyi:23:9: PYI030 Multiple literal members in a union. Use a single litera 24 | field5: Literal[1] | str | Literal[2] # Error 25 | field6: Literal[1] | bool | Literal[2] | str # Error | + = help: Replace with a single `Literal` -PYI030.pyi:24:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +20 20 | +21 21 | # Should emit in longer unions, even if not directly adjacent. +22 22 | field3: Literal[1] | Literal[2] | str # Error +23 |-field4: str | Literal[1] | Literal[2] # Error + 23 |+field4: Literal[1, 2] # Error +24 24 | field5: Literal[1] | str | Literal[2] # Error +25 25 | field6: Literal[1] | bool | Literal[2] | str # Error +26 26 | + +PYI030.pyi:24:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 22 | field3: Literal[1] | Literal[2] | str # Error 23 | field4: str | Literal[1] | Literal[2] # Error @@ -53,8 +108,19 @@ PYI030.pyi:24:9: PYI030 Multiple literal members in a union. Use a single litera | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 25 | field6: Literal[1] | bool | Literal[2] | str # Error | + = help: Replace with a single `Literal` -PYI030.pyi:25:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +21 21 | # Should emit in longer unions, even if not directly adjacent. +22 22 | field3: Literal[1] | Literal[2] | str # Error +23 23 | field4: str | Literal[1] | Literal[2] # Error +24 |-field5: Literal[1] | str | Literal[2] # Error + 24 |+field5: Literal[1, 2] # Error +25 25 | field6: Literal[1] | bool | Literal[2] | str # Error +26 26 | +27 27 | # Should emit for non-type unions. + +PYI030.pyi:25:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 23 | field4: str | Literal[1] | Literal[2] # Error 24 | field5: Literal[1] | str | Literal[2] # Error @@ -63,8 +129,19 @@ PYI030.pyi:25:9: PYI030 Multiple literal members in a union. Use a single litera 26 | 27 | # Should emit for non-type unions. | + = help: Replace with a single `Literal` -PYI030.pyi:28:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +22 22 | field3: Literal[1] | Literal[2] | str # Error +23 23 | field4: str | Literal[1] | Literal[2] # Error +24 24 | field5: Literal[1] | str | Literal[2] # Error +25 |-field6: Literal[1] | bool | Literal[2] | str # Error + 25 |+field6: Literal[1, 2] # Error +26 26 | +27 27 | # Should emit for non-type unions. +28 28 | field7 = Literal[1] | Literal[2] # Error + +PYI030.pyi:28:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 27 | # Should emit for non-type unions. 28 | field7 = Literal[1] | Literal[2] # Error @@ -72,8 +149,19 @@ PYI030.pyi:28:10: PYI030 Multiple literal members in a union. Use a single liter 29 | 30 | # Should emit for parenthesized unions. | + = help: Replace with a single `Literal` -PYI030.pyi:31:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +25 25 | field6: Literal[1] | bool | Literal[2] | str # Error +26 26 | +27 27 | # Should emit for non-type unions. +28 |-field7 = Literal[1] | Literal[2] # Error + 28 |+field7 = Literal[1, 2] # Error +29 29 | +30 30 | # Should emit for parenthesized unions. +31 31 | field8: Literal[1] | (Literal[2] | str) # Error + +PYI030.pyi:31:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 30 | # Should emit for parenthesized unions. 31 | field8: Literal[1] | (Literal[2] | str) # Error @@ -81,16 +169,38 @@ PYI030.pyi:31:9: PYI030 Multiple literal members in a union. Use a single litera 32 | 33 | # Should handle user parentheses when fixing. | + = help: Replace with a single `Literal` -PYI030.pyi:34:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +28 28 | field7 = Literal[1] | Literal[2] # Error +29 29 | +30 30 | # Should emit for parenthesized unions. +31 |-field8: Literal[1] | (Literal[2] | str) # Error + 31 |+field8: Literal[1, 2] # Error +32 32 | +33 33 | # Should handle user parentheses when fixing. +34 34 | field9: Literal[1] | (Literal[2] | str) # Error + +PYI030.pyi:34:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 33 | # Should handle user parentheses when fixing. 34 | field9: Literal[1] | (Literal[2] | str) # Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 35 | field10: (Literal[1] | str) | Literal[2] # Error | + = help: Replace with a single `Literal` -PYI030.pyi:35:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +31 31 | field8: Literal[1] | (Literal[2] | str) # Error +32 32 | +33 33 | # Should handle user parentheses when fixing. +34 |-field9: Literal[1] | (Literal[2] | str) # Error + 34 |+field9: Literal[1, 2] # Error +35 35 | field10: (Literal[1] | str) | Literal[2] # Error +36 36 | +37 37 | # Should emit for union in generic parent type. + +PYI030.pyi:35:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 33 | # Should handle user parentheses when fixing. 34 | field9: Literal[1] | (Literal[2] | str) # Error @@ -99,8 +209,19 @@ PYI030.pyi:35:10: PYI030 Multiple literal members in a union. Use a single liter 36 | 37 | # Should emit for union in generic parent type. | + = help: Replace with a single `Literal` -PYI030.pyi:38:15: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +32 32 | +33 33 | # Should handle user parentheses when fixing. +34 34 | field9: Literal[1] | (Literal[2] | str) # Error +35 |-field10: (Literal[1] | str) | Literal[2] # Error + 35 |+field10: Literal[1, 2] # Error +36 36 | +37 37 | # Should emit for union in generic parent type. +38 38 | field11: dict[Literal[1] | Literal[2], str] # Error + +PYI030.pyi:38:15: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 37 | # Should emit for union in generic parent type. 38 | field11: dict[Literal[1] | Literal[2], str] # Error @@ -108,16 +229,38 @@ PYI030.pyi:38:15: PYI030 Multiple literal members in a union. Use a single liter 39 | 40 | # Should emit for unions with more than two cases | + = help: Replace with a single `Literal` -PYI030.pyi:41:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]` +ℹ Fix +35 35 | field10: (Literal[1] | str) | Literal[2] # Error +36 36 | +37 37 | # Should emit for union in generic parent type. +38 |-field11: dict[Literal[1] | Literal[2], str] # Error + 38 |+field11: dict[Literal[1, 2], str] # Error +39 39 | +40 40 | # Should emit for unions with more than two cases +41 41 | field12: Literal[1] | Literal[2] | Literal[3] # Error + +PYI030.pyi:41:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]` | 40 | # Should emit for unions with more than two cases 41 | field12: Literal[1] | Literal[2] | Literal[3] # Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error | + = help: Replace with a single `Literal` -PYI030.pyi:42:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]` +ℹ Fix +38 38 | field11: dict[Literal[1] | Literal[2], str] # Error +39 39 | +40 40 | # Should emit for unions with more than two cases +41 |-field12: Literal[1] | Literal[2] | Literal[3] # Error + 41 |+field12: Literal[1, 2, 3] # Error +42 42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error +43 43 | +44 44 | # Should emit for unions with more than two cases, even if not directly adjacent + +PYI030.pyi:42:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]` | 40 | # Should emit for unions with more than two cases 41 | field12: Literal[1] | Literal[2] | Literal[3] # Error @@ -126,8 +269,19 @@ PYI030.pyi:42:10: PYI030 Multiple literal members in a union. Use a single liter 43 | 44 | # Should emit for unions with more than two cases, even if not directly adjacent | + = help: Replace with a single `Literal` -PYI030.pyi:45:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]` +ℹ Fix +39 39 | +40 40 | # Should emit for unions with more than two cases +41 41 | field12: Literal[1] | Literal[2] | Literal[3] # Error +42 |-field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error + 42 |+field13: Literal[1, 2, 3, 4] # Error +43 43 | +44 44 | # Should emit for unions with more than two cases, even if not directly adjacent +45 45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error + +PYI030.pyi:45:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]` | 44 | # Should emit for unions with more than two cases, even if not directly adjacent 45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error @@ -135,8 +289,19 @@ PYI030.pyi:45:10: PYI030 Multiple literal members in a union. Use a single liter 46 | 47 | # Should emit for unions with mixed literal internal types | + = help: Replace with a single `Literal` -PYI030.pyi:48:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, "foo", True]` +ℹ Fix +42 42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error +43 43 | +44 44 | # Should emit for unions with more than two cases, even if not directly adjacent +45 |-field14: Literal[1] | Literal[2] | str | Literal[3] # Error + 45 |+field14: Literal[1, 2, 3] # Error +46 46 | +47 47 | # Should emit for unions with mixed literal internal types +48 48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error + +PYI030.pyi:48:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, "foo", True]` | 47 | # Should emit for unions with mixed literal internal types 48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error @@ -144,8 +309,19 @@ PYI030.pyi:48:10: PYI030 Multiple literal members in a union. Use a single liter 49 | 50 | # Shouldn't emit for duplicate field types with same value; covered by Y016 | + = help: Replace with a single `Literal` -PYI030.pyi:51:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 1]` +ℹ Fix +45 45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error +46 46 | +47 47 | # Should emit for unions with mixed literal internal types +48 |-field15: Literal[1] | Literal["foo"] | Literal[True] # Error + 48 |+field15: Literal[1, "foo", True] # Error +49 49 | +50 50 | # Shouldn't emit for duplicate field types with same value; covered by Y016 +51 51 | field16: Literal[1] | Literal[1] # OK + +PYI030.pyi:51:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 1]` | 50 | # Shouldn't emit for duplicate field types with same value; covered by Y016 51 | field16: Literal[1] | Literal[1] # OK @@ -153,8 +329,19 @@ PYI030.pyi:51:10: PYI030 Multiple literal members in a union. Use a single liter 52 | 53 | # Shouldn't emit if in new parent type | + = help: Replace with a single `Literal` -PYI030.pyi:60:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +48 48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error +49 49 | +50 50 | # Shouldn't emit for duplicate field types with same value; covered by Y016 +51 |-field16: Literal[1] | Literal[1] # OK + 51 |+field16: Literal[1, 1] # OK +52 52 | +53 53 | # Shouldn't emit if in new parent type +54 54 | field17: Literal[1] | dict[Literal[2], str] # OK + +PYI030.pyi:60:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 59 | # Should respect name of literal type used 60 | field19: typing.Literal[1] | typing.Literal[2] # Error @@ -162,8 +349,19 @@ PYI030.pyi:60:10: PYI030 Multiple literal members in a union. Use a single liter 61 | 62 | # Should emit in cases with newlines | + = help: Replace with a single `Literal` -PYI030.pyi:63:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +57 57 | field18: dict[Literal[1], Literal[2]] # OK +58 58 | +59 59 | # Should respect name of literal type used +60 |-field19: typing.Literal[1] | typing.Literal[2] # Error + 60 |+field19: Literal[1, 2] # Error +61 61 | +62 62 | # Should emit in cases with newlines +63 63 | field20: typing.Union[ + +PYI030.pyi:63:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 62 | # Should emit in cases with newlines 63 | field20: typing.Union[ @@ -177,8 +375,24 @@ PYI030.pyi:63:10: PYI030 Multiple literal members in a union. Use a single liter 69 | 70 | # Should handle multiple unions with multiple members | + = help: Replace with a single `Literal` -PYI030.pyi:71:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]` +ℹ Fix +60 60 | field19: typing.Literal[1] | typing.Literal[2] # Error +61 61 | +62 62 | # Should emit in cases with newlines +63 |-field20: typing.Union[ +64 |- Literal[ +65 |- 1 # test +66 |- ], +67 |- Literal[2], +68 |-] # Error, newline and comment will not be emitted in message + 63 |+field20: Literal[1, 2] # Error, newline and comment will not be emitted in message +69 64 | +70 65 | # Should handle multiple unions with multiple members +71 66 | field21: Literal[1, 2] | Literal[3, 4] # Error + +PYI030.pyi:71:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]` | 70 | # Should handle multiple unions with multiple members 71 | field21: Literal[1, 2] | Literal[3, 4] # Error @@ -186,8 +400,19 @@ PYI030.pyi:71:10: PYI030 Multiple literal members in a union. Use a single liter 72 | 73 | # Should emit in cases with `typing.Union` instead of `|` | + = help: Replace with a single `Literal` -PYI030.pyi:74:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +68 68 | ] # Error, newline and comment will not be emitted in message +69 69 | +70 70 | # Should handle multiple unions with multiple members +71 |-field21: Literal[1, 2] | Literal[3, 4] # Error + 71 |+field21: Literal[1, 2, 3, 4] # Error +72 72 | +73 73 | # Should emit in cases with `typing.Union` instead of `|` +74 74 | field22: typing.Union[Literal[1], Literal[2]] # Error + +PYI030.pyi:74:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 73 | # Should emit in cases with `typing.Union` instead of `|` 74 | field22: typing.Union[Literal[1], Literal[2]] # Error @@ -195,8 +420,19 @@ PYI030.pyi:74:10: PYI030 Multiple literal members in a union. Use a single liter 75 | 76 | # Should emit in cases with `typing_extensions.Literal` | + = help: Replace with a single `Literal` -PYI030.pyi:77:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +71 71 | field21: Literal[1, 2] | Literal[3, 4] # Error +72 72 | +73 73 | # Should emit in cases with `typing.Union` instead of `|` +74 |-field22: typing.Union[Literal[1], Literal[2]] # Error + 74 |+field22: Literal[1, 2] # Error +75 75 | +76 76 | # Should emit in cases with `typing_extensions.Literal` +77 77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error + +PYI030.pyi:77:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 76 | # Should emit in cases with `typing_extensions.Literal` 77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error @@ -204,8 +440,19 @@ PYI030.pyi:77:10: PYI030 Multiple literal members in a union. Use a single liter 78 | 79 | # Should emit in cases with nested `typing.Union` | + = help: Replace with a single `Literal` -PYI030.pyi:80:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +74 74 | field22: typing.Union[Literal[1], Literal[2]] # Error +75 75 | +76 76 | # Should emit in cases with `typing_extensions.Literal` +77 |-field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error + 77 |+field23: Literal[1, 2] # Error +78 78 | +79 79 | # Should emit in cases with nested `typing.Union` +80 80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error + +PYI030.pyi:80:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 79 | # Should emit in cases with nested `typing.Union` 80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error @@ -213,8 +460,19 @@ PYI030.pyi:80:10: PYI030 Multiple literal members in a union. Use a single liter 81 | 82 | # Should emit in cases with mixed `typing.Union` and `|` | + = help: Replace with a single `Literal` -PYI030.pyi:83:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` +ℹ Fix +77 77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error +78 78 | +79 79 | # Should emit in cases with nested `typing.Union` +80 |-field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error + 80 |+field24: Literal[1, 2] # Error +81 81 | +82 82 | # Should emit in cases with mixed `typing.Union` and `|` +83 83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error + +PYI030.pyi:83:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]` | 82 | # Should emit in cases with mixed `typing.Union` and `|` 83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error @@ -222,12 +480,31 @@ PYI030.pyi:83:10: PYI030 Multiple literal members in a union. Use a single liter 84 | 85 | # Should emit only once in cases with multiple nested `typing.Union` | + = help: Replace with a single `Literal` -PYI030.pyi:86:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]` +ℹ Fix +80 80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error +81 81 | +82 82 | # Should emit in cases with mixed `typing.Union` and `|` +83 |-field25: typing.Union[Literal[1], Literal[2] | str] # Error + 83 |+field25: Literal[1, 2] # Error +84 84 | +85 85 | # Should emit only once in cases with multiple nested `typing.Union` +86 86 | field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error + +PYI030.pyi:86:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]` | 85 | # Should emit only once in cases with multiple nested `typing.Union` 86 | field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030 | + = help: Replace with a single `Literal` + +ℹ Fix +83 83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error +84 84 | +85 85 | # Should emit only once in cases with multiple nested `typing.Union` +86 |-field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error + 86 |+field24: Literal[1, 2, 3, 4] # Error