mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-04 18:58:04 +00:00
[pyupgrade
] Preserve parenthesis when fixing native literals containing newlines (UP018
) (#17220)
This commit is contained in:
parent
48a85c4ed4
commit
a01f25107a
14 changed files with 128 additions and 0 deletions
6
.gitattributes
vendored
6
.gitattributes
vendored
|
@ -12,6 +12,12 @@ crates/ruff_python_parser/resources/invalid/re_lexing/line_continuation_windows_
|
|||
crates/ruff_python_parser/resources/invalid/re_lex_logical_token_windows_eol.py text eol=crlf
|
||||
crates/ruff_python_parser/resources/invalid/re_lex_logical_token_mac_eol.py text eol=cr
|
||||
|
||||
crates/ruff_linter/resources/test/fixtures/ruff/RUF046_CR.py text eol=cr
|
||||
crates/ruff_linter/resources/test/fixtures/ruff/RUF046_LF.py text eol=lf
|
||||
|
||||
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_CR.py text eol=cr
|
||||
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_LF.py text eol=lf
|
||||
|
||||
crates/ruff_python_parser/resources/inline linguist-generated=true
|
||||
|
||||
ruff.schema.json -diff linguist-generated=true text=auto eol=lf
|
||||
|
|
5
crates/ruff_linter/resources/test/fixtures/pyupgrade/.editorconfig
vendored
Normal file
5
crates/ruff_linter/resources/test/fixtures/pyupgrade/.editorconfig
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# These rules test for reformatting with specific line endings.
|
||||
# Using a formatter fixes that and breaks the tests
|
||||
[UP018_{CR,LF}.py]
|
||||
generated_code = true
|
||||
ij_formatter_enabled = false
|
1
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_CR.py
vendored
Normal file
1
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_CR.py
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
# Keep parenthesis around preserved CR
int(-
1)
int(+
1)
|
7
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_LF.py
vendored
Normal file
7
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018_LF.py
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Keep parentheses around preserved \n
|
||||
|
||||
int(-
|
||||
1)
|
||||
|
||||
int(+
|
||||
1)
|
5
crates/ruff_linter/resources/test/fixtures/ruff/.editorconfig
vendored
Normal file
5
crates/ruff_linter/resources/test/fixtures/ruff/.editorconfig
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# These rules test for reformatting with specific line endings.
|
||||
# Using a formatter fixes that and breaks the tests
|
||||
[RUF046_{CR,LF}.py]
|
||||
generated_code = true
|
||||
ij_formatter_enabled = false
|
1
crates/ruff_linter/resources/test/fixtures/ruff/RUF046_CR.py
vendored
Normal file
1
crates/ruff_linter/resources/test/fixtures/ruff/RUF046_CR.py
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
int(-
1) # Carriage return as newline
|
3
crates/ruff_linter/resources/test/fixtures/ruff/RUF046_LF.py
vendored
Normal file
3
crates/ruff_linter/resources/test/fixtures/ruff/RUF046_LF.py
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# \n as newline
|
||||
int(-
|
||||
1)
|
|
@ -36,6 +36,8 @@ mod tests {
|
|||
#[test_case(Rule::LRUCacheWithMaxsizeNone, Path::new("UP033_1.py"))]
|
||||
#[test_case(Rule::LRUCacheWithoutParameters, Path::new("UP011.py"))]
|
||||
#[test_case(Rule::NativeLiterals, Path::new("UP018.py"))]
|
||||
#[test_case(Rule::NativeLiterals, Path::new("UP018_CR.py"))]
|
||||
#[test_case(Rule::NativeLiterals, Path::new("UP018_LF.py"))]
|
||||
#[test_case(Rule::NonPEP585Annotation, Path::new("UP006_0.py"))]
|
||||
#[test_case(Rule::NonPEP585Annotation, Path::new("UP006_1.py"))]
|
||||
#[test_case(Rule::NonPEP585Annotation, Path::new("UP006_2.py"))]
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::str::FromStr;
|
|||
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||
use ruff_python_ast::{self as ast, Expr, Int, LiteralExpressionRef, OperatorPrecedence, UnaryOp};
|
||||
use ruff_source_file::find_newline;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
@ -244,6 +245,9 @@ pub(crate) fn native_literals(
|
|||
let arg_code = checker.locator().slice(arg);
|
||||
|
||||
let content = match (parent_expr, literal_type, has_unary_op) {
|
||||
// Expressions including newlines must be parenthesised to be valid syntax
|
||||
(_, _, true) if find_newline(arg_code).is_some() => format!("({arg_code})"),
|
||||
|
||||
// Attribute access on an integer requires the integer to be parenthesized to disambiguate from a float
|
||||
// Ex) `(7).denominator` is valid but `7.denominator` is not
|
||||
// Note that floats do not have this problem
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pyupgrade/mod.rs
|
||||
---
|
||||
UP018_CR.py:2:1: UP018 [*] Unnecessary `int` call (rewrite as a literal)
|
||||
|
|
||||
1 | # Keep parenthesis around preserved CR
int(-
1)
int(+
1)
|
||||
| ^^^^^^^^^^^ UP018
|
||||
|
|
||||
= help: Replace with integer literal
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | # Keep parenthesis around preserved CR
2 |-int(-
2 |+(-
3 3 | 1)
4 4 | int(+
5 5 | 1)
|
||||
|
||||
UP018_CR.py:4:1: UP018 [*] Unnecessary `int` call (rewrite as a literal)
|
||||
|
|
||||
2 | int(-
1)
int(+
1)
|
||||
| ^^^^^^^^^^^ UP018
|
||||
|
|
||||
= help: Replace with integer literal
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | # Keep parenthesis around preserved CR
2 2 | int(-
3 3 | 1)
4 |-int(+
4 |+(+
5 5 | 1)
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/pyupgrade/mod.rs
|
||||
---
|
||||
UP018_LF.py:3:1: UP018 [*] Unnecessary `int` call (rewrite as a literal)
|
||||
|
|
||||
1 | # Keep parentheses around preserved \n
|
||||
2 |
|
||||
3 | / int(-
|
||||
4 | | 1)
|
||||
| |______^ UP018
|
||||
5 |
|
||||
6 | int(+
|
||||
|
|
||||
= help: Replace with integer literal
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | # Keep parentheses around preserved \n
|
||||
2 2 |
|
||||
3 |-int(-
|
||||
3 |+(-
|
||||
4 4 | 1)
|
||||
5 5 |
|
||||
6 6 | int(+
|
||||
|
||||
UP018_LF.py:6:1: UP018 [*] Unnecessary `int` call (rewrite as a literal)
|
||||
|
|
||||
4 | 1)
|
||||
5 |
|
||||
6 | / int(+
|
||||
7 | | 1)
|
||||
| |______^ UP018
|
||||
|
|
||||
= help: Replace with integer literal
|
||||
|
||||
ℹ Safe fix
|
||||
3 3 | int(-
|
||||
4 4 | 1)
|
||||
5 5 |
|
||||
6 |-int(+
|
||||
6 |+(+
|
||||
7 7 | 1)
|
|
@ -84,6 +84,8 @@ mod tests {
|
|||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.py"))]
|
||||
#[test_case(Rule::UnnecessaryNestedLiteral, Path::new("RUF041.pyi"))]
|
||||
#[test_case(Rule::UnnecessaryCastToInt, Path::new("RUF046.py"))]
|
||||
#[test_case(Rule::UnnecessaryCastToInt, Path::new("RUF046_CR.py"))]
|
||||
#[test_case(Rule::UnnecessaryCastToInt, Path::new("RUF046_LF.py"))]
|
||||
#[test_case(Rule::NeedlessElse, Path::new("RUF047_if.py"))]
|
||||
#[test_case(Rule::NeedlessElse, Path::new("RUF047_for.py"))]
|
||||
#[test_case(Rule::NeedlessElse, Path::new("RUF047_while.py"))]
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF046_CR.py:1:1: RUF046 [*] Value being cast to `int` is already an integer
|
||||
|
|
||||
1 | int(-
1) # Carriage return as newline
|
||||
| ^^^^^^^^^^^ RUF046
|
||||
|
|
||||
= help: Remove unnecessary `int` call
|
||||
|
||||
ℹ Safe fix
|
||||
1 |-int(-
1 |+(-
2 2 | 1) # Carriage return as newline
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/ruff/mod.rs
|
||||
---
|
||||
RUF046_LF.py:2:1: RUF046 [*] Value being cast to `int` is already an integer
|
||||
|
|
||||
1 | # \n as newline
|
||||
2 | / int(-
|
||||
3 | | 1)
|
||||
| |______^ RUF046
|
||||
|
|
||||
= help: Remove unnecessary `int` call
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | # \n as newline
|
||||
2 |-int(-
|
||||
2 |+(-
|
||||
3 3 | 1)
|
Loading…
Add table
Add a link
Reference in a new issue