Skip to content

Commit

Permalink
Revert "add autofix for PYI030" (#7943)
Browse files Browse the repository at this point in the history
This reverts commit #7880 (d8c0360)
which does not perform the correct fix per
#7934
  • Loading branch information
zanieb authored Oct 13, 2023
1 parent 60ca688 commit 8255e4e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 465 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_diagnostics::{Diagnostic, Violation};
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::rules::flake8_pyi::helpers::traverse_union;

/// ## What it does
Expand Down Expand Up @@ -32,25 +31,21 @@ pub struct UnnecessaryLiteralUnion {
members: Vec<String>,
}

impl AlwaysFixableViolation for UnnecessaryLiteralUnion {
impl Violation for UnnecessaryLiteralUnion {
#[derive_message_formats]
fn message(&self) -> String {
format!(
"Multiple literal members in a union. Use a single literal, e.g. `Literal[{}]`",
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") {
Expand All @@ -59,28 +54,21 @@ 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 literal_members: Vec<String> = literal_exprs
.into_iter()
.map(|expr| checker.locator().slice(expr.as_ref()).to_string())
.collect();

let mut diagnostic = Diagnostic::new(
let diagnostic = Diagnostic::new(
UnnecessaryLiteralUnion {
members: literal_members.clone(),
members: literal_exprs
.into_iter()
.map(|expr| checker.locator().slice(expr.as_ref()).to_string())
.collect(),
},
expr.range(),
);

diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
format!("Literal[{}]", literal_members.join(", ")),
expr.range(),
)));

checker.diagnostics.push(diagnostic);
}
}
Original file line number Diff line number Diff line change
@@ -1,85 +1,41 @@
---
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
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
10 |
11 | # Should emit for union types in arguments.
|
= help: Replace with a single `Literal`

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]`
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`

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]`
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`

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]`
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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
23 | field4: str | Literal[1] | Literal[2] # Error
24 | field5: Literal[1] | str | Literal[2] # Error
|
= help: Replace with a single `Literal`

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]`
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
Expand All @@ -88,39 +44,17 @@ PYI030.py:23:9: PYI030 [*] Multiple literal members in a union. Use a single lit
24 | field5: Literal[1] | str | Literal[2] # Error
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
= help: Replace with a single `Literal`

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]`
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
24 | field5: Literal[1] | str | Literal[2] # Error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
= help: Replace with a single `Literal`

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]`
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
Expand All @@ -129,78 +63,34 @@ PYI030.py:25:9: PYI030 [*] Multiple literal members in a union. Use a single lit
26 |
27 | # Should emit for non-type unions.
|
= help: Replace with a single `Literal`

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]`
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
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
29 |
30 | # Should emit for parenthesized unions.
|
= help: Replace with a single `Literal`

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]`
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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
32 |
33 | # Should handle user parentheses when fixing.
|
= help: Replace with a single `Literal`

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]`
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`

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]`
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
Expand All @@ -209,31 +99,12 @@ PYI030.py:35:10: PYI030 [*] Multiple literal members in a union. Use a single li
36 |
37 | # Should emit for union in generic parent type.
|
= help: Replace with a single `Literal`

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]`
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


Loading

0 comments on commit 8255e4e

Please sign in to comment.