|
1 | | -use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; |
| 1 | +use clippy_utils::diagnostics::span_lint_and_sugg; |
2 | 2 | use clippy_utils::macros::{root_macro_call, FormatArgsExpn}; |
3 | | -use clippy_utils::source::snippet_with_applicability; |
| 3 | +use clippy_utils::sugg::Sugg; |
4 | 4 | use clippy_utils::ty::is_type_diagnostic_item; |
5 | 5 | use rustc_errors::Applicability; |
6 | 6 | use rustc_hir::{Expr, ExprKind}; |
@@ -45,46 +45,44 @@ impl<'tcx> LateLintPass<'tcx> for PathFromFormat { |
45 | 45 | if let Some(macro_call) = root_macro_call(args[0].span); |
46 | 46 | if cx.tcx.item_name(macro_call.def_id) == sym::format; |
47 | 47 | 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; |
51 | 50 | 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]]); |
73 | 64 | } |
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})") |
79 | 65 | } |
80 | 66 | 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]]); |
84 | 76 | } |
85 | | - format!("Path::new(\"{str1}\").join({real_vars}).join(\"{str2}\")") |
86 | 77 | } |
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 | + } |
88 | 86 | span_lint_and_sugg( |
89 | 87 | cx, |
90 | 88 | PATH_FROM_FORMAT, |
|
0 commit comments