mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:42:02 +00:00
Implement autofix for F541 (#1577)
This commit is contained in:
parent
8aeec35bfb
commit
03a8ece954
6 changed files with 206 additions and 19 deletions
8
resources/test/fixtures/pyflakes/F541.py
vendored
8
resources/test/fixtures/pyflakes/F541.py
vendored
|
@ -9,6 +9,14 @@ e = (
|
||||||
f"def" +
|
f"def" +
|
||||||
"ghi"
|
"ghi"
|
||||||
)
|
)
|
||||||
|
f = (
|
||||||
|
f"a"
|
||||||
|
F"b"
|
||||||
|
"c"
|
||||||
|
rf"d"
|
||||||
|
fr"e"
|
||||||
|
)
|
||||||
|
g = f""
|
||||||
|
|
||||||
# OK
|
# OK
|
||||||
g = f"ghi{123:{45}}"
|
g = f"ghi{123:{45}}"
|
||||||
|
|
|
@ -9,6 +9,7 @@ use rustpython_ast::{
|
||||||
};
|
};
|
||||||
use rustpython_parser::lexer;
|
use rustpython_parser::lexer;
|
||||||
use rustpython_parser::lexer::Tok;
|
use rustpython_parser::lexer::Tok;
|
||||||
|
use rustpython_parser::token::StringKind;
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::types::Range;
|
||||||
use crate::SourceCodeLocator;
|
use crate::SourceCodeLocator;
|
||||||
|
@ -470,6 +471,43 @@ pub fn except_range(handler: &Excepthandler, locator: &SourceCodeLocator) -> Ran
|
||||||
range
|
range
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find f-strings that don't contain any formatted values in a `JoinedStr`.
|
||||||
|
pub fn find_useless_f_strings(expr: &Expr, locator: &SourceCodeLocator) -> Vec<(Range, Range)> {
|
||||||
|
let contents = locator.slice_source_code_range(&Range::from_located(expr));
|
||||||
|
lexer::make_tokenizer_located(&contents, expr.location)
|
||||||
|
.flatten()
|
||||||
|
.filter_map(|(location, tok, end_location)| match tok {
|
||||||
|
Tok::String {
|
||||||
|
kind: StringKind::FString | StringKind::RawFString,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let first_char = locator.slice_source_code_range(&Range {
|
||||||
|
location,
|
||||||
|
end_location: Location::new(location.row(), location.column() + 1),
|
||||||
|
});
|
||||||
|
// f"..." => f_position = 0
|
||||||
|
// fr"..." => f_position = 0
|
||||||
|
// rf"..." => f_position = 1
|
||||||
|
let f_position = usize::from(!(first_char == "f" || first_char == "F"));
|
||||||
|
Some((
|
||||||
|
Range {
|
||||||
|
location: Location::new(location.row(), location.column() + f_position),
|
||||||
|
end_location: Location::new(
|
||||||
|
location.row(),
|
||||||
|
location.column() + f_position + 1,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
Range {
|
||||||
|
location,
|
||||||
|
end_location,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the `Range` of `else` in `For`, `AsyncFor`, and `While` statements.
|
/// Return the `Range` of `else` in `For`, `AsyncFor`, and `While` statements.
|
||||||
pub fn else_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Option<Range> {
|
pub fn else_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Option<Range> {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
|
|
|
@ -2280,15 +2280,7 @@ where
|
||||||
}
|
}
|
||||||
ExprKind::JoinedStr { values } => {
|
ExprKind::JoinedStr { values } => {
|
||||||
if self.settings.enabled.contains(&CheckCode::F541) {
|
if self.settings.enabled.contains(&CheckCode::F541) {
|
||||||
if !values
|
pyflakes::plugins::f_string_missing_placeholders(expr, values, self);
|
||||||
.iter()
|
|
||||||
.any(|value| matches!(value.node, ExprKind::FormattedValue { .. }))
|
|
||||||
{
|
|
||||||
self.add_check(Check::new(
|
|
||||||
CheckKind::FStringMissingPlaceholders,
|
|
||||||
Range::from_located(expr),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::BinOp {
|
ExprKind::BinOp {
|
||||||
|
|
25
src/pyflakes/plugins/f_string_missing_placeholders.rs
Normal file
25
src/pyflakes/plugins/f_string_missing_placeholders.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use rustpython_ast::{Expr, ExprKind};
|
||||||
|
|
||||||
|
use crate::ast::helpers::find_useless_f_strings;
|
||||||
|
use crate::autofix::Fix;
|
||||||
|
use crate::checkers::ast::Checker;
|
||||||
|
use crate::registry::{Check, CheckCode, CheckKind};
|
||||||
|
|
||||||
|
/// F541
|
||||||
|
pub fn f_string_missing_placeholders(expr: &Expr, values: &[Expr], checker: &mut Checker) {
|
||||||
|
if !values
|
||||||
|
.iter()
|
||||||
|
.any(|value| matches!(value.node, ExprKind::FormattedValue { .. }))
|
||||||
|
{
|
||||||
|
for (prefix_range, tok_range) in find_useless_f_strings(expr, checker.locator) {
|
||||||
|
let mut check = Check::new(CheckKind::FStringMissingPlaceholders, tok_range);
|
||||||
|
if checker.patch(&CheckCode::F541) {
|
||||||
|
check.amend(Fix::deletion(
|
||||||
|
prefix_range.location,
|
||||||
|
prefix_range.end_location,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
checker.add_check(check);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
pub use assert_tuple::assert_tuple;
|
pub use assert_tuple::assert_tuple;
|
||||||
|
pub use f_string_missing_placeholders::f_string_missing_placeholders;
|
||||||
pub use if_tuple::if_tuple;
|
pub use if_tuple::if_tuple;
|
||||||
pub use invalid_literal_comparisons::invalid_literal_comparison;
|
pub use invalid_literal_comparisons::invalid_literal_comparison;
|
||||||
pub use invalid_print_syntax::invalid_print_syntax;
|
pub use invalid_print_syntax::invalid_print_syntax;
|
||||||
|
@ -13,6 +14,7 @@ pub(crate) use strings::{
|
||||||
};
|
};
|
||||||
|
|
||||||
mod assert_tuple;
|
mod assert_tuple;
|
||||||
|
mod f_string_missing_placeholders;
|
||||||
mod if_tuple;
|
mod if_tuple;
|
||||||
mod invalid_literal_comparisons;
|
mod invalid_literal_comparisons;
|
||||||
mod invalid_print_syntax;
|
mod invalid_print_syntax;
|
||||||
|
|
|
@ -9,7 +9,14 @@ expression: checks
|
||||||
end_location:
|
end_location:
|
||||||
row: 6
|
row: 6
|
||||||
column: 10
|
column: 10
|
||||||
fix: ~
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 6
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 6
|
||||||
|
column: 5
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind: FStringMissingPlaceholders
|
- kind: FStringMissingPlaceholders
|
||||||
location:
|
location:
|
||||||
|
@ -18,7 +25,14 @@ expression: checks
|
||||||
end_location:
|
end_location:
|
||||||
row: 7
|
row: 7
|
||||||
column: 10
|
column: 10
|
||||||
fix: ~
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 7
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 7
|
||||||
|
column: 5
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind: FStringMissingPlaceholders
|
- kind: FStringMissingPlaceholders
|
||||||
location:
|
location:
|
||||||
|
@ -27,7 +41,62 @@ expression: checks
|
||||||
end_location:
|
end_location:
|
||||||
row: 9
|
row: 9
|
||||||
column: 10
|
column: 10
|
||||||
fix: ~
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 9
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 9
|
||||||
|
column: 5
|
||||||
|
parent: ~
|
||||||
|
- kind: FStringMissingPlaceholders
|
||||||
|
location:
|
||||||
|
row: 13
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 13
|
||||||
|
column: 8
|
||||||
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 13
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 13
|
||||||
|
column: 5
|
||||||
|
parent: ~
|
||||||
|
- kind: FStringMissingPlaceholders
|
||||||
|
location:
|
||||||
|
row: 14
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 14
|
||||||
|
column: 8
|
||||||
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 14
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 14
|
||||||
|
column: 5
|
||||||
|
parent: ~
|
||||||
|
- kind: FStringMissingPlaceholders
|
||||||
|
location:
|
||||||
|
row: 16
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 16
|
||||||
|
column: 9
|
||||||
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 16
|
||||||
|
column: 5
|
||||||
|
end_location:
|
||||||
|
row: 16
|
||||||
|
column: 6
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind: FStringMissingPlaceholders
|
- kind: FStringMissingPlaceholders
|
||||||
location:
|
location:
|
||||||
|
@ -35,25 +104,78 @@ expression: checks
|
||||||
column: 4
|
column: 4
|
||||||
end_location:
|
end_location:
|
||||||
row: 17
|
row: 17
|
||||||
|
column: 9
|
||||||
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 17
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 17
|
||||||
|
column: 5
|
||||||
|
parent: ~
|
||||||
|
- kind: FStringMissingPlaceholders
|
||||||
|
location:
|
||||||
|
row: 19
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 19
|
||||||
|
column: 7
|
||||||
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 19
|
||||||
|
column: 4
|
||||||
|
end_location:
|
||||||
|
row: 19
|
||||||
|
column: 5
|
||||||
|
parent: ~
|
||||||
|
- kind: FStringMissingPlaceholders
|
||||||
|
location:
|
||||||
|
row: 25
|
||||||
|
column: 12
|
||||||
|
end_location:
|
||||||
|
row: 25
|
||||||
column: 16
|
column: 16
|
||||||
fix: ~
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 25
|
||||||
|
column: 12
|
||||||
|
end_location:
|
||||||
|
row: 25
|
||||||
|
column: 13
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind: FStringMissingPlaceholders
|
- kind: FStringMissingPlaceholders
|
||||||
location:
|
location:
|
||||||
row: 26
|
row: 34
|
||||||
column: 6
|
column: 6
|
||||||
end_location:
|
end_location:
|
||||||
row: 26
|
row: 34
|
||||||
column: 13
|
column: 13
|
||||||
fix: ~
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 34
|
||||||
|
column: 6
|
||||||
|
end_location:
|
||||||
|
row: 34
|
||||||
|
column: 7
|
||||||
parent: ~
|
parent: ~
|
||||||
- kind: FStringMissingPlaceholders
|
- kind: FStringMissingPlaceholders
|
||||||
location:
|
location:
|
||||||
row: 27
|
row: 35
|
||||||
column: 3
|
column: 3
|
||||||
end_location:
|
end_location:
|
||||||
row: 27
|
row: 35
|
||||||
column: 6
|
column: 6
|
||||||
fix: ~
|
fix:
|
||||||
|
content: ""
|
||||||
|
location:
|
||||||
|
row: 35
|
||||||
|
column: 3
|
||||||
|
end_location:
|
||||||
|
row: 35
|
||||||
|
column: 4
|
||||||
parent: ~
|
parent: ~
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue