Skip to content

Commit 67ab61f

Browse files
committed
fix suggestions
1 parent ba8899a commit 67ab61f

File tree

3 files changed

+42
-37
lines changed

3 files changed

+42
-37
lines changed

clippy_lints/src/path_from_format.rs

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::macros::{root_macro_call, FormatArgsExpn};
3-
use clippy_utils::source::snippet_with_applicability;
3+
use clippy_utils::sugg::Sugg;
44
use clippy_utils::ty::is_type_diagnostic_item;
55
use rustc_errors::Applicability;
66
use rustc_hir::{Expr, ExprKind};
@@ -45,46 +45,44 @@ impl<'tcx> LateLintPass<'tcx> for PathFromFormat {
4545
if let Some(macro_call) = root_macro_call(args[0].span);
4646
if cx.tcx.item_name(macro_call.def_id) == sym::format;
4747
if let Some(format_args) = FormatArgsExpn::find_nested(cx, &args[0], macro_call.expn);
48-
let mut applicability = Applicability::MachineApplicable;
49-
let format_args_snip = snippet_with_applicability(cx, format_args.inputs_span(), "..", &mut applicability);
50-
if let Some(end_of_literal) = format_args_snip.find("\",");
48+
let format_string_parts = format_args.format_string_parts;
49+
let format_value_args = format_args.value_args;
5150
then {
52-
let (literal, vars) = format_args_snip.split_at(end_of_literal);
53-
let mut literal = literal.to_string();
54-
literal.remove(0);
55-
let v: Vec<&str> = literal.split("{}").collect();
56-
let real_vars = vars.strip_prefix("\", ").unwrap_or(vars);
57-
if v.len() != 2 || real_vars.contains(',') {
58-
span_lint_and_help(
59-
cx,
60-
PATH_FROM_FORMAT,
61-
expr.span,
62-
"`format!(..)` used to form `PathBuf`",
63-
None,
64-
"consider using `.join()` to avoid the extra allocation",
65-
);
66-
return;
67-
}
68-
let sugg = {
69-
if v[0].is_empty() {
70-
let mut str1 = v[1].to_string();
71-
if str1.starts_with('\\') || str1.starts_with('/') {
72-
str1.remove(0);
51+
let mut string_parts: Vec<&str> = format_string_parts.iter().map(|x| x.as_str()).collect();
52+
string_parts.push("");
53+
let mut applicability = Applicability::MachineApplicable;
54+
let real_vars: Vec<Sugg<'_>> = format_value_args.iter().map(|x| Sugg::hir_with_applicability(cx, x, "..", &mut applicability)).collect();
55+
let order_of_real_vars: Vec<usize> = format_args.formatters.iter().map(|(x, _)| x.clone()).collect();
56+
let mut sugg = String::new();
57+
for n in 0..real_vars.len() {
58+
if n == 0 {
59+
if string_parts[0].is_empty() {
60+
sugg = format!("Path::new({})", real_vars[order_of_real_vars[0]]);
61+
}
62+
else {
63+
sugg = format!("Path::new(\"{}\").join({y})", string_parts[0], y = real_vars[order_of_real_vars[0]]);
7364
}
74-
format!("Path::new({real_vars}).join(\"{str1}\")")
75-
}
76-
else if v[1].is_empty() {
77-
let str1 = v[0].to_string();
78-
format!("Path::new(\"{str1}\").join({real_vars})")
7965
}
8066
else {
81-
let (str1, mut str2) = (v[0].to_string(), v[1].to_string());
82-
if str2.starts_with('\\') || str2.starts_with('/') {
83-
str2.remove(0);
67+
if string_parts[n].is_empty() {
68+
sugg = format!("{sugg}.join({})", real_vars[order_of_real_vars[n]]);
69+
}
70+
else {
71+
let mut string = String::from(string_parts[n]);
72+
if string.starts_with('/') || string.starts_with('\\') {
73+
string.remove(0);
74+
}
75+
sugg = format!("{sugg}.join(\"{}\").join({y})", string, y = real_vars[order_of_real_vars[n]]);
8476
}
85-
format!("Path::new(\"{str1}\").join({real_vars}).join(\"{str2}\")")
8677
}
87-
};
78+
}
79+
if !string_parts[real_vars.len()].is_empty() {
80+
let mut string = String::from(string_parts[real_vars.len()]);
81+
if string.starts_with('/') || string.starts_with('\\') {
82+
string.remove(0);
83+
}
84+
sugg = format!("{sugg}.join(\"{}\")", string);
85+
}
8886
span_lint_and_sugg(
8987
cx,
9088
PATH_FROM_FORMAT,

tests/ui/path_from_format.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ fn main() {
88
PathBuf::from(format!("/foo/bar/{}", base_path1));
99
PathBuf::from(format!("/foo/{}/bar", base_path1));
1010
PathBuf::from(format!("foo/{}/bar", base_path1));
11+
PathBuf::from(format!("foo/{base_path1}/bar"));
1112
}

tests/ui/path_from_format.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,11 @@ error: `format!(..)` used to form `PathBuf`
2424
LL | PathBuf::from(format!("foo/{}/bar", base_path1));
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.join()` to avoid the extra allocation: `Path::new("foo/").join(base_path1).join("bar")`
2626

27-
error: aborting due to 4 previous errors
27+
error: `format!(..)` used to form `PathBuf`
28+
--> $DIR/path_from_format.rs:11:5
29+
|
30+
LL | PathBuf::from(format!("foo/{base_path1}/bar"));
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.join()` to avoid the extra allocation: `Path::new("foo/").join(base_path1).join("bar")`
32+
33+
error: aborting due to 5 previous errors
2834

0 commit comments

Comments
 (0)