1- #![ expect( unused) ]
2-
31use std:: collections:: BTreeSet ;
4- use std:: fmt:: Write ;
52use std:: fs;
63use std:: path:: Path ;
74
@@ -10,6 +7,7 @@ use serde::{Deserialize, Serialize};
107
118use crate :: ClippyWarning ;
129
10+ /// This is the total number. 300 warnings results in 100 messages per section.
1311const DEFAULT_LIMIT_PER_LINT : usize = 300 ;
1412const TRUNCATION_TOTAL_TARGET : usize = 1000 ;
1513
@@ -59,77 +57,6 @@ fn load_warnings(path: &Path) -> Vec<LintJson> {
5957 serde_json:: from_slice ( & file) . unwrap_or_else ( |e| panic ! ( "failed to deserialize {}: {e}" , path. display( ) ) )
6058}
6159
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-
13360pub ( crate ) fn diff ( old_path : & Path , new_path : & Path , truncate : bool ) {
13461 let old_warnings = load_warnings ( old_path) ;
13562 let new_warnings = load_warnings ( new_path) ;
@@ -156,40 +83,21 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) {
15683 println ! ( ) ;
15784
15885 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 )
16190 } else {
16291 // No lint should ever each this number of lint emissions, so this is equivialent to
16392 // No truncation
16493 usize:: MAX
16594 } ;
16695
16796 for lint in lint_warnings {
168- print_lint_warnings ( & lint, truncate_after)
97+ print_lint_warnings ( & lint, truncate_after) ;
16998 }
17099}
171100
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-
193101#[ derive( Debug ) ]
194102struct LintWarnings {
195103 name : String ,
@@ -209,7 +117,7 @@ fn group_by_lint(
209117 F : FnMut ( & T ) -> bool ,
210118 {
211119 let mut items = vec ! [ ] ;
212- while iter. peek ( ) . map_or ( false , |item| condition ( item ) ) {
120+ while iter. peek ( ) . map_or ( false , & mut condition) {
213121 items. push ( iter. next ( ) . unwrap ( ) ) ;
214122 }
215123 items
@@ -234,7 +142,7 @@ fn group_by_lint(
234142 let mut changed_iter = changed. into_iter ( ) . peekable ( ) ;
235143
236144 let mut lints = vec ! [ ] ;
237- for name in lint_names. into_iter ( ) {
145+ for name in lint_names {
238146 lints. push ( LintWarnings {
239147 added : collect_while ( & mut added_iter, |warning| warning. lint == name) ,
240148 removed : collect_while ( & mut removed_iter, |warning| warning. lint == name) ,
@@ -246,13 +154,26 @@ fn group_by_lint(
246154 lints
247155}
248156
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+ }
256177
257178fn print_summary_table ( lints : & [ LintWarnings ] ) {
258179 println ! ( "| Lint | Added | Removed | Changed |" ) ;
@@ -269,8 +190,83 @@ fn print_summary_table(lints: &[LintWarnings]) {
269190 }
270191}
271192
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.
272268fn to_html_id ( lint_name : & str ) -> String {
273- lint_name. replace ( "clippy::" , "" ) . replace ( "_" , "-" )
269+ lint_name. replace ( "clippy::" , "" ) . replace ( '_' , "-" )
274270}
275271
276272/// 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 {
281277 if count == 0 {
282278 format ! ( "0 {label}" )
283279 } else {
284- let lint_id = to_html_id ( lint) ;
280+ let html_id = to_html_id ( lint) ;
285281 // GitHub's job summaries don't add HTML ids to headings. That's why we
286282 // manually have to add them. GitHub prefixes these manual ids with
287283 // `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})" )
289285 }
290286}
0 commit comments