Skip to content

Commit bc39697

Browse files
committed
wip - trying to get needed tokens
1 parent e8518b7 commit bc39697

File tree

4 files changed

+33
-1090
lines changed

4 files changed

+33
-1090
lines changed

clippy_lints/src/format_args.rs

+25-22
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ use if_chain::if_chain;
88
use itertools::Itertools;
99
use rustc_errors::Applicability;
1010
use rustc_hir::{Expr, ExprKind, HirId, Path, QPath};
11+
// use rustc_lexer::tokenize;
12+
// use rustc_lexer::TokenKind::{CloseBrace, CloseBracket, CloseParen};
1113
use rustc_lint::{LateContext, LateLintPass};
1214
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
1315
use rustc_middle::ty::Ty;
1416
use rustc_semver::RustcVersion;
1517
use rustc_session::{declare_tool_lint, impl_lint_pass};
18+
use rustc_span::hygiene::walk_chain;
1619
use rustc_span::{sym, ExpnData, ExpnKind, Span, Symbol};
1720

1821
declare_clippy_lint! {
@@ -146,7 +149,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs {
146149
check_to_string_in_format_args(cx, name, arg.param.value);
147150
}
148151
if meets_msrv(self.msrv, msrvs::FORMAT_ARGS_CAPTURE) {
149-
check_uninlined_args(cx, &format_args, outermost_expn_data.call_site);
152+
check_uninlined_args(cx, &format_args, outermost_expn_data);
150153
}
151154
}
152155
}
@@ -155,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs {
155158
extract_msrv_attr!(LateContext);
156159
}
157160

158-
fn check_uninlined_args(cx: &LateContext<'_>, args: &FormatArgsExpn<'_>, call_site: Span) {
161+
fn check_uninlined_args(cx: &LateContext<'_>, args: &FormatArgsExpn<'_>, outermost_expn_data: ExpnData) {
159162
let mut fixes = Vec::new();
160163
// If any of the arguments are referenced by an index number,
161164
// and that argument is not a simple variable and cannot be inlined,
@@ -179,21 +182,21 @@ fn check_uninlined_args(cx: &LateContext<'_>, args: &FormatArgsExpn<'_>, call_si
179182
// and ensure we do not see any closing brackets/braces/parens.
180183
// This might be a relatively expensive test, so do it only we are ready to replace.
181184

182-
/*
183-
let fmt_str_span = args.format_string.span;
184-
println!("1st: {}", snippet_opt(cx, fmt_str_span).unwrap());
185-
let first_arg_span = walk_chain(fmt_str_span, fmt_str_span.ctxt());
186-
println!("2nd: {}", snippet_opt(cx, first_arg_span).unwrap());
187-
let between = fmt_str_span.with_lo(fmt_str_span.hi()).with_hi(first_arg_span.lo());
188-
println!("3rd: {}", snippet_opt(cx, between).unwrap());
189-
if let Some(between_snippet) = snippet_opt(cx, between) {
190-
if !tokenize(&between_snippet).any(|t| matches!(t.kind, CloseParen | CloseBrace | CloseBracket))
191-
*/
185+
// let fmt_str_span = args.format_string.span;
186+
// let first_arg_span = walk_chain(fmt_str_span, fmt_str_span.ctxt());
187+
// let first_arg_span = walk_chain(fmt_str_span, outermost_expn_data.call_site.ctxt());
188+
// let between = fmt_str_span.with_lo(fmt_str_span.hi()).with_hi(first_arg_span.lo());
189+
// if let Some(between_snippet) = snippet_opt(cx, between) {
190+
// if !tokenize(&between_snippet).any(|t| matches!(t.kind, CloseParen | CloseBrace |
191+
// CloseBracket))
192+
// println!("2nd: {}", snippet_opt(cx, first_arg_span).unwrap());
193+
// println!("3nd: {}", snippet_opt(cx, first_arg_span).unwrap());
194+
// println!("3rd: {}", snippet_opt(cx, between).unwrap());
192195

193196
span_lint_and_then(
194197
cx,
195198
UNINLINED_FORMAT_ARGS,
196-
call_site,
199+
outermost_expn_data.call_site,
197200
"variables can be used directly in the `format!` string",
198201
|diag| {
199202
diag.multipart_suggestion("change this to", fixes, Applicability::MachineApplicable);
@@ -208,17 +211,17 @@ fn check_one_arg(cx: &LateContext<'_>, param: &FormatParam<'_>, fixes: &mut Vec<
208211
&& let [segment] = segments
209212
{
210213
let replacement = match param.usage {
211-
FormatParamUsage::Argument => segment.ident.name.to_string(),
214+
FormatParamUsage::Argument => segment.ident.name.to_string(),
212215
FormatParamUsage::Width => format!("{}$", segment.ident.name),
213216
FormatParamUsage::Precision => format!(".{}$", segment.ident.name),
214-
};
215-
fixes.push((param.span, replacement));
216-
let arg_span = expand_past_previous_comma(cx, *span);
217-
fixes.push((arg_span, String::new()));
218-
true // successful inlining, continue checking
219-
} else {
220-
// if we can't inline a numbered argument, we can't continue
221-
param.kind != Numbered
217+
};
218+
fixes.push((param.span, replacement));
219+
let arg_span = expand_past_previous_comma(cx, *span);
220+
fixes.push((arg_span, String::new()));
221+
true // successful inlining, continue checking
222+
} else {
223+
// if we can't inline a numbered argument, we can't continue
224+
param.kind != Numbered
222225
}
223226
}
224227

tests/ui/uninlined_format_args.fixed

+1-104
Original file line numberDiff line numberDiff line change
@@ -18,110 +18,7 @@ fn tester(fn_arg: i32) {
1818
let prec = 5;
1919
let val = 6;
2020

21-
// make sure this file hasn't been corrupted with tabs converted to spaces
22-
// let _ = ' '; // <- this is a single tab character
23-
let _: &[u8; 3] = b" "; // <- <tab><space><tab>
24-
25-
println!("val='{local_i32}'");
26-
println!("val='{local_i32}'"); // 3 spaces
27-
println!("val='{local_i32}'"); // tab
28-
println!("val='{local_i32}'"); // space+tab
29-
println!("val='{local_i32}'"); // tab+space
30-
println!(
31-
"val='{local_i32}'"
32-
);
33-
println!("{local_i32}");
34-
println!("{fn_arg}");
35-
println!("{local_i32:?}");
36-
println!("{local_i32:#?}");
37-
println!("{local_i32:4}");
38-
println!("{local_i32:04}");
39-
println!("{local_i32:<3}");
40-
println!("{local_i32:#010x}");
41-
println!("{local_f64:.1}");
42-
println!("Hello {} is {local_f64:.local_i32$}", "x");
43-
println!("Hello {local_i32} is {local_f64:.*}", 5);
44-
println!("Hello {local_i32} is {local_f64:.*}", 5);
45-
println!("{local_i32} {local_f64}");
46-
println!("{local_i32}, {}", local_opt.unwrap());
47-
println!("{val}");
48-
println!("{val}");
49-
println!("{} {1}", local_i32, 42);
50-
println!("val='{local_i32}'");
51-
println!("val='{local_i32}'");
52-
println!("val='{local_i32}'");
53-
println!("val='{fn_arg}'");
54-
println!("{local_i32}");
55-
println!("{local_i32:?}");
56-
println!("{local_i32:#?}");
57-
println!("{local_i32:04}");
58-
println!("{local_i32:<3}");
59-
println!("{local_i32:#010x}");
60-
println!("{local_f64:.1}");
61-
println!("{local_i32} {local_i32}");
62-
println!("{local_f64} {local_i32} {local_i32} {local_f64}");
63-
println!("{local_i32} {local_f64}");
64-
println!("{local_f64} {local_i32}");
65-
println!("{local_f64} {local_i32} {local_f64} {local_i32}");
66-
println!("{1} {0}", "str", local_i32);
67-
println!("{local_i32}");
68-
println!("{local_i32:width$}");
69-
println!("{local_i32:width$}");
70-
println!("{local_i32:.prec$}");
71-
println!("{local_i32:.prec$}");
72-
println!("{val:val$}");
73-
println!("{val:val$}");
74-
println!("{val:val$.val$}");
75-
println!("{val:val$.val$}");
76-
println!("{val:val$.val$}");
77-
println!("{val:val$.val$}");
78-
println!("{val:val$.val$}");
79-
println!("{val:val$.val$}");
80-
println!("{val:val$.val$}");
81-
println!("{val:val$.val$}");
82-
println!("{width:width$}");
83-
println!("{local_i32:width$}");
84-
println!("{width:width$}");
85-
println!("{local_i32:width$}");
86-
println!("{prec:.prec$}");
87-
println!("{local_i32:.prec$}");
88-
println!("{prec:.prec$}");
89-
println!("{local_i32:.prec$}");
90-
println!("{width:width$.prec$}");
91-
println!("{width:width$.prec$}");
92-
println!("{local_f64:width$.prec$}");
93-
println!("{local_f64:width$.prec$} {local_f64} {width} {prec}");
94-
println!(
95-
"{local_i32:width$.prec$} {local_i32:prec$.width$} {width:local_i32$.prec$} {width:prec$.local_i32$} {prec:local_i32$.width$} {prec:width$.local_i32$}",
96-
);
97-
println!(
98-
"{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$} {3}",
99-
local_i32,
100-
width,
101-
prec,
102-
1 + 2
103-
);
104-
println!("Width = {local_i32}, value with width = {local_f64:local_i32$}");
105-
println!("{local_i32:width$.prec$}");
106-
println!("{width:width$.prec$}");
107-
println!("{}", format!("{local_i32}"));
108-
109-
// indoc crate's equivalent of print!(indoc!(...))
110-
printdoc!("foo={}", local_i32);
111-
112-
// these should NOT be modified by the lint
113-
// println!(indoc!("foo={}"), local_i32);
114-
println!(concat!("nope ", "{}"), local_i32);
115-
println!("val='{local_i32}'");
116-
println!("val='{local_i32 }'");
117-
println!("val='{local_i32 }'"); // with tab
118-
println!("val='{local_i32\n}'");
119-
println!("{}", usize::MAX);
120-
println!("{}", local_opt.unwrap());
121-
println!(
122-
"val='{local_i32
123-
}'"
124-
);
21+
println!(indoc!("foo={local_i32}"));
12522
}
12623

12724
fn main() {

tests/ui/uninlined_format_args.rs

+1-119
Original file line numberDiff line numberDiff line change
@@ -18,127 +18,9 @@ fn tester(fn_arg: i32) {
1818
let prec = 5;
1919
let val = 6;
2020

21-
// make sure this file hasn't been corrupted with tabs converted to spaces
22-
// let _ = ' '; // <- this is a single tab character
23-
let _: &[u8; 3] = b" "; // <- <tab><space><tab>
24-
25-
println!("val='{}'", local_i32);
26-
println!("val='{ }'", local_i32); // 3 spaces
27-
println!("val='{ }'", local_i32); // tab
28-
println!("val='{ }'", local_i32); // space+tab
29-
println!("val='{ }'", local_i32); // tab+space
30-
println!(
31-
"val='{
32-
}'",
33-
local_i32
34-
);
35-
println!("{}", local_i32);
36-
println!("{}", fn_arg);
37-
println!("{:?}", local_i32);
38-
println!("{:#?}", local_i32);
39-
println!("{:4}", local_i32);
40-
println!("{:04}", local_i32);
41-
println!("{:<3}", local_i32);
42-
println!("{:#010x}", local_i32);
43-
println!("{:.1}", local_f64);
44-
println!("Hello {} is {:.*}", "x", local_i32, local_f64);
45-
println!("Hello {} is {:.*}", local_i32, 5, local_f64);
46-
println!("Hello {} is {2:.*}", local_i32, 5, local_f64);
47-
println!("{} {}", local_i32, local_f64);
48-
println!("{}, {}", local_i32, local_opt.unwrap());
49-
println!("{}", val);
50-
println!("{}", v = val);
51-
println!("{} {1}", local_i32, 42);
52-
println!("val='{\t }'", local_i32);
53-
println!("val='{\n }'", local_i32);
54-
println!("val='{local_i32}'", local_i32 = local_i32);
55-
println!("val='{local_i32}'", local_i32 = fn_arg);
56-
println!("{0}", local_i32);
57-
println!("{0:?}", local_i32);
58-
println!("{0:#?}", local_i32);
59-
println!("{0:04}", local_i32);
60-
println!("{0:<3}", local_i32);
61-
println!("{0:#010x}", local_i32);
62-
println!("{0:.1}", local_f64);
63-
println!("{0} {0}", local_i32);
64-
println!("{1} {} {0} {}", local_i32, local_f64);
65-
println!("{0} {1}", local_i32, local_f64);
66-
println!("{1} {0}", local_i32, local_f64);
67-
println!("{1} {0} {1} {0}", local_i32, local_f64);
68-
println!("{1} {0}", "str", local_i32);
69-
println!("{v}", v = local_i32);
70-
println!("{local_i32:0$}", width);
71-
println!("{local_i32:w$}", w = width);
72-
println!("{local_i32:.0$}", prec);
73-
println!("{local_i32:.p$}", p = prec);
74-
println!("{:0$}", v = val);
75-
println!("{0:0$}", v = val);
76-
println!("{:0$.0$}", v = val);
77-
println!("{0:0$.0$}", v = val);
78-
println!("{0:0$.v$}", v = val);
79-
println!("{0:v$.0$}", v = val);
80-
println!("{v:0$.0$}", v = val);
81-
println!("{v:v$.0$}", v = val);
82-
println!("{v:0$.v$}", v = val);
83-
println!("{v:v$.v$}", v = val);
84-
println!("{:0$}", width);
85-
println!("{:1$}", local_i32, width);
86-
println!("{:w$}", w = width);
87-
println!("{:w$}", local_i32, w = width);
88-
println!("{:.0$}", prec);
89-
println!("{:.1$}", local_i32, prec);
90-
println!("{:.p$}", p = prec);
91-
println!("{:.p$}", local_i32, p = prec);
92-
println!("{:0$.1$}", width, prec);
93-
println!("{:0$.w$}", width, w = prec);
94-
println!("{:1$.2$}", local_f64, width, prec);
95-
println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec);
96-
println!(
97-
"{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}",
98-
local_i32, width, prec,
99-
);
100-
println!(
101-
"{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$} {3}",
102-
local_i32,
103-
width,
104-
prec,
105-
1 + 2
106-
);
107-
println!("Width = {}, value with width = {:0$}", local_i32, local_f64);
108-
println!("{:w$.p$}", local_i32, w = width, p = prec);
109-
println!("{:w$.p$}", w = width, p = prec);
110-
println!("{}", format!("{}", local_i32));
111-
112-
// indoc crate's equivalent of print!(indoc!(...))
113-
printdoc!("foo={}", local_i32);
114-
115-
// these should NOT be modified by the lint
116-
// println!(indoc!("foo={}"), local_i32);
117-
println!(concat!("nope ", "{}"), local_i32);
118-
println!("val='{local_i32}'");
119-
println!("val='{local_i32 }'");
120-
println!("val='{local_i32 }'"); // with tab
121-
println!("val='{local_i32\n}'");
122-
println!("{}", usize::MAX);
123-
println!("{}", local_opt.unwrap());
124-
println!(
125-
"val='{local_i32
126-
}'"
127-
);
21+
println!(indoc!("foo={}"), local_i32);
12822
}
12923

13024
fn main() {
13125
tester(42);
13226
}
133-
134-
fn _under_msrv() {
135-
#![clippy::msrv = "1.57"]
136-
let local_i32 = 1;
137-
println!("don't expand='{}'", local_i32);
138-
}
139-
140-
fn _meets_msrv() {
141-
#![clippy::msrv = "1.58"]
142-
let local_i32 = 1;
143-
println!("expand='{}'", local_i32);
144-
}

0 commit comments

Comments
 (0)