1
- #![ expect( unused) ]
2
-
3
1
use std:: collections:: BTreeSet ;
4
- use std:: fmt:: Write ;
5
2
use std:: fs;
6
3
use std:: path:: Path ;
7
4
@@ -10,6 +7,7 @@ use serde::{Deserialize, Serialize};
10
7
11
8
use crate :: ClippyWarning ;
12
9
10
+ /// This is the total number. 300 warnings results in 100 messages per section.
13
11
const DEFAULT_LIMIT_PER_LINT : usize = 300 ;
14
12
const TRUNCATION_TOTAL_TARGET : usize = 1000 ;
15
13
@@ -59,77 +57,6 @@ fn load_warnings(path: &Path) -> Vec<LintJson> {
59
57
serde_json:: from_slice ( & file) . unwrap_or_else ( |e| panic ! ( "failed to deserialize {}: {e}" , path. display( ) ) )
60
58
}
61
59
62
- fn print_warnings ( title : & str , warnings : & [ LintJson ] , truncate_after : usize ) {
63
- if warnings. is_empty ( ) {
64
- return ;
65
- }
66
-
67
- print_h3 ( & warnings[ 0 ] . lint , title) ;
68
- println ! ( ) ;
69
-
70
- let warnings = truncate ( warnings, truncate_after) ;
71
-
72
- for warning in warnings {
73
- println ! ( "{}" , warning. info_text( title) ) ;
74
- println ! ( ) ;
75
- println ! ( "```" ) ;
76
- println ! ( "{}" , warning. rendered. trim_end( ) ) ;
77
- println ! ( "```" ) ;
78
- println ! ( ) ;
79
- }
80
- }
81
-
82
- fn print_changed_diff ( changed : & [ ( LintJson , LintJson ) ] , truncate_after : usize ) {
83
- if changed. is_empty ( ) {
84
- return ;
85
- }
86
-
87
- print_h3 ( & changed[ 0 ] . 0 . lint , "Changed" ) ;
88
- println ! ( ) ;
89
-
90
- let changes = truncate ( changed, truncate_after) ;
91
-
92
- for ( old, new) in changed {
93
- println ! ( "{}" , new. info_text( "Changed" ) ) ;
94
- println ! ( ) ;
95
- println ! ( "```diff" ) ;
96
- for change in diff:: lines ( old. rendered . trim_end ( ) , new. rendered . trim_end ( ) ) {
97
- use diff:: Result :: { Both , Left , Right } ;
98
-
99
- match change {
100
- Both ( unchanged, _) => {
101
- println ! ( " {unchanged}" ) ;
102
- } ,
103
- Left ( removed) => {
104
- println ! ( "-{removed}" ) ;
105
- } ,
106
- Right ( added) => {
107
- println ! ( "+{added}" ) ;
108
- } ,
109
- }
110
- }
111
- println ! ( "```" ) ;
112
- }
113
- }
114
-
115
- fn print_h3 ( lint : & str , title : & str ) {
116
- let html_id = to_html_id ( lint) ;
117
- // We have to use HTML here to be able to manually add an id.
118
- println ! ( r#"<h3 id="user-content-{html_id}-{title}">{title}</h3>"# ) ;
119
- }
120
-
121
- fn truncate < T > ( list : & [ T ] , truncate_after : usize ) -> & [ T ] {
122
- if list. len ( ) > truncate_after {
123
- println ! ( "{} warnings have been truncated for this summary." , list. len( ) - truncate_after) ;
124
- println ! ( ) ;
125
-
126
- list. split_at ( truncate_after) . 0
127
- } else {
128
- list
129
- }
130
-
131
- }
132
-
133
60
pub ( crate ) fn diff ( old_path : & Path , new_path : & Path , truncate : bool ) {
134
61
let old_warnings = load_warnings ( old_path) ;
135
62
let new_warnings = load_warnings ( new_path) ;
@@ -156,40 +83,21 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) {
156
83
println ! ( ) ;
157
84
158
85
let truncate_after = if truncate {
159
- // Max 9 ensures that we at least have three messages per lint
160
- DEFAULT_LIMIT_PER_LINT . min ( TRUNCATION_TOTAL_TARGET / lint_warnings. len ( ) ) . max ( 9 )
86
+ // Max 15 ensures that we at least have five messages per lint
87
+ DEFAULT_LIMIT_PER_LINT
88
+ . min ( TRUNCATION_TOTAL_TARGET / lint_warnings. len ( ) )
89
+ . max ( 15 )
161
90
} else {
162
91
// No lint should ever each this number of lint emissions, so this is equivialent to
163
92
// No truncation
164
93
usize:: MAX
165
94
} ;
166
95
167
96
for lint in lint_warnings {
168
- print_lint_warnings ( & lint, truncate_after)
97
+ print_lint_warnings ( & lint, truncate_after) ;
169
98
}
170
99
}
171
100
172
- fn print_lint_warnings ( lint : & LintWarnings , truncate_after : usize ) {
173
- let name = & lint. name ;
174
- let html_id = to_html_id ( name) ;
175
-
176
- // The additional anchor is added for non GH viewers that don't prefix ID's
177
- println ! ( r#"<h2 id="user-content-{html_id}">{name}</h2>"# ) ;
178
- println ! ( ) ;
179
-
180
- print ! (
181
- r##"{}, {}, {}"## ,
182
- count_string( name, "added" , lint. added. len( ) ) ,
183
- count_string( name, "removed" , lint. removed. len( ) ) ,
184
- count_string( name, "changed" , lint. changed. len( ) ) ,
185
- ) ;
186
- println ! ( ) ;
187
-
188
- print_warnings ( "Added" , & lint. added , truncate_after / 3 ) ;
189
- print_warnings ( "Removed" , & lint. removed , truncate_after / 3 ) ;
190
- print_changed_diff ( & lint. changed , truncate_after / 3 ) ;
191
- }
192
-
193
101
#[ derive( Debug ) ]
194
102
struct LintWarnings {
195
103
name : String ,
@@ -209,7 +117,7 @@ fn group_by_lint(
209
117
F : FnMut ( & T ) -> bool ,
210
118
{
211
119
let mut items = vec ! [ ] ;
212
- while iter. peek ( ) . map_or ( false , |item| condition ( item ) ) {
120
+ while iter. peek ( ) . map_or ( false , & mut condition) {
213
121
items. push ( iter. next ( ) . unwrap ( ) ) ;
214
122
}
215
123
items
@@ -234,7 +142,7 @@ fn group_by_lint(
234
142
let mut changed_iter = changed. into_iter ( ) . peekable ( ) ;
235
143
236
144
let mut lints = vec ! [ ] ;
237
- for name in lint_names. into_iter ( ) {
145
+ for name in lint_names {
238
146
lints. push ( LintWarnings {
239
147
added : collect_while ( & mut added_iter, |warning| warning. lint == name) ,
240
148
removed : collect_while ( & mut removed_iter, |warning| warning. lint == name) ,
@@ -246,13 +154,26 @@ fn group_by_lint(
246
154
lints
247
155
}
248
156
249
- // This function limits the number of lints in the collection if needed.
250
- //
251
- // It's honestly amazing that a function like this is needed. But some restriction
252
- // lints (Looking at you `implicit_return` and `if_then_some_else_none`) trigger a lot
253
- // like 60'000+ times in our CI.
254
- //
255
- // Each lint in the list will be limited to 200 messages
157
+ fn print_lint_warnings ( lint : & LintWarnings , truncate_after : usize ) {
158
+ let name = & lint. name ;
159
+ let html_id = to_html_id ( name) ;
160
+
161
+ // The additional anchor is added for non GH viewers that don't prefix ID's
162
+ println ! ( r#"## `{name}` <a id="user-content-{html_id}"/>"# ) ;
163
+ println ! ( ) ;
164
+
165
+ print ! (
166
+ r##"{}, {}, {}"## ,
167
+ count_string( name, "added" , lint. added. len( ) ) ,
168
+ count_string( name, "removed" , lint. removed. len( ) ) ,
169
+ count_string( name, "changed" , lint. changed. len( ) ) ,
170
+ ) ;
171
+ println ! ( ) ;
172
+
173
+ print_warnings ( "Added" , & lint. added , truncate_after / 3 ) ;
174
+ print_warnings ( "Removed" , & lint. removed , truncate_after / 3 ) ;
175
+ print_changed_diff ( & lint. changed , truncate_after / 3 ) ;
176
+ }
256
177
257
178
fn print_summary_table ( lints : & [ LintWarnings ] ) {
258
179
println ! ( "| Lint | Added | Removed | Changed |" ) ;
@@ -269,8 +190,83 @@ fn print_summary_table(lints: &[LintWarnings]) {
269
190
}
270
191
}
271
192
193
+ fn print_warnings ( title : & str , warnings : & [ LintJson ] , truncate_after : usize ) {
194
+ if warnings. is_empty ( ) {
195
+ return ;
196
+ }
197
+
198
+ print_h3 ( & warnings[ 0 ] . lint , title) ;
199
+ println ! ( ) ;
200
+
201
+ let warnings = truncate ( warnings, truncate_after) ;
202
+
203
+ for warning in warnings {
204
+ println ! ( "{}" , warning. info_text( title) ) ;
205
+ println ! ( ) ;
206
+ println ! ( "```" ) ;
207
+ println ! ( "{}" , warning. rendered. trim_end( ) ) ;
208
+ println ! ( "```" ) ;
209
+ println ! ( ) ;
210
+ }
211
+ }
212
+
213
+ fn print_changed_diff ( changed : & [ ( LintJson , LintJson ) ] , truncate_after : usize ) {
214
+ if changed. is_empty ( ) {
215
+ return ;
216
+ }
217
+
218
+ print_h3 ( & changed[ 0 ] . 0 . lint , "Changed" ) ;
219
+ println ! ( ) ;
220
+
221
+ let changed = truncate ( changed, truncate_after) ;
222
+
223
+ for ( old, new) in changed {
224
+ println ! ( "{}" , new. info_text( "Changed" ) ) ;
225
+ println ! ( ) ;
226
+ println ! ( "```diff" ) ;
227
+ for change in diff:: lines ( old. rendered . trim_end ( ) , new. rendered . trim_end ( ) ) {
228
+ use diff:: Result :: { Both , Left , Right } ;
229
+
230
+ match change {
231
+ Both ( unchanged, _) => {
232
+ println ! ( " {unchanged}" ) ;
233
+ } ,
234
+ Left ( removed) => {
235
+ println ! ( "-{removed}" ) ;
236
+ } ,
237
+ Right ( added) => {
238
+ println ! ( "+{added}" ) ;
239
+ } ,
240
+ }
241
+ }
242
+ println ! ( "```" ) ;
243
+ }
244
+ }
245
+
246
+ fn truncate < T > ( list : & [ T ] , truncate_after : usize ) -> & [ T ] {
247
+ if list. len ( ) > truncate_after {
248
+ println ! (
249
+ "{} warnings have been truncated for this summary." ,
250
+ list. len( ) - truncate_after
251
+ ) ;
252
+ println ! ( ) ;
253
+
254
+ list. split_at ( truncate_after) . 0
255
+ } else {
256
+ list
257
+ }
258
+ }
259
+
260
+ fn print_h3 ( lint : & str , title : & str ) {
261
+ let html_id = to_html_id ( lint) ;
262
+ // We have to use HTML here to be able to manually add an id.
263
+ println ! ( r#"### {title} <a id="user-content-{html_id}-{title}"/>"# ) ;
264
+ }
265
+
266
+ /// GitHub's markdown parsers doesn't like IDs with `::` and `_`. This simplifies
267
+ /// the lint name for the HTML ID.
272
268
fn to_html_id ( lint_name : & str ) -> String {
273
- lint_name. replace ( "clippy::" , "" ) . replace ( "_" , "-" )
269
+ lint_name. replace ( "clippy::" , "" ) . replace ( '_' , "-" )
274
270
}
275
271
276
272
/// This generates the `x added` string for the start of the job summery.
@@ -281,10 +277,10 @@ fn count_string(lint: &str, label: &str, count: usize) -> String {
281
277
if count == 0 {
282
278
format ! ( "0 {label}" )
283
279
} else {
284
- let lint_id = to_html_id ( lint) ;
280
+ let html_id = to_html_id ( lint) ;
285
281
// GitHub's job summaries don't add HTML ids to headings. That's why we
286
282
// manually have to add them. GitHub prefixes these manual ids with
287
283
// `user-content-` and that's how we end up with these awesome links :D
288
- format ! ( "[{count} {label}](#user-content-{lint_id }-{label})" )
284
+ format ! ( "[{count} {label}](#user-content-{html_id }-{label})" )
289
285
}
290
286
}
0 commit comments