1
+ use std:: fmt:: Write ;
1
2
use std:: fs;
2
3
use std:: path:: Path ;
3
4
@@ -52,11 +53,13 @@ fn load_warnings(path: &Path) -> Vec<LintJson> {
52
53
serde_json:: from_slice ( & file) . unwrap_or_else ( |e| panic ! ( "failed to deserialize {}: {e}" , path. display( ) ) )
53
54
}
54
55
55
- fn print_warnings ( title : & str , warnings : & [ LintJson ] ) {
56
+ fn print_warnings ( title : & str , mut warnings : Vec < LintJson > ) {
56
57
if warnings. is_empty ( ) {
57
58
return ;
58
59
}
59
60
61
+ let redacted_msg = limit_by_lint ( & mut warnings, |lint| & lint. lint ) ;
62
+
60
63
//We have to use HTML here to be able to manually add an id.
61
64
println ! ( r#"<h3 id="{title}">{title}</h3>"# ) ;
62
65
println ! ( ) ;
@@ -68,13 +71,19 @@ fn print_warnings(title: &str, warnings: &[LintJson]) {
68
71
println ! ( "```" ) ;
69
72
println ! ( ) ;
70
73
}
74
+
75
+ if let Some ( redacted_msg) = redacted_msg {
76
+ println ! ( "{redacted_msg}" ) ;
77
+ }
71
78
}
72
79
73
- fn print_changed_diff ( changed : & [ ( LintJson , LintJson ) ] ) {
80
+ fn print_changed_diff ( mut changed : Vec < ( LintJson , LintJson ) > ) {
74
81
if changed. is_empty ( ) {
75
82
return ;
76
83
}
77
84
85
+ let redacted_msg = limit_by_lint ( & mut changed, |( lint, _) | & lint. lint ) ;
86
+
78
87
//We have to use HTML here to be able to manually add an id.
79
88
println ! ( r#"<h3 id="changed">Changed</h3>"# ) ;
80
89
println ! ( ) ;
@@ -99,6 +108,10 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)]) {
99
108
}
100
109
println ! ( "```" ) ;
101
110
}
111
+
112
+ if let Some ( redacted_msg) = redacted_msg {
113
+ println ! ( "{redacted_msg}" ) ;
114
+ }
102
115
}
103
116
104
117
pub ( crate ) fn diff ( old_path : & Path , new_path : & Path ) {
@@ -130,9 +143,65 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path) {
130
143
println ! ( ) ;
131
144
println ! ( ) ;
132
145
133
- print_warnings ( "Added" , & added) ;
134
- print_warnings ( "Removed" , & removed) ;
135
- print_changed_diff ( & changed) ;
146
+ print_warnings ( "Added" , added) ;
147
+ print_warnings ( "Removed" , removed) ;
148
+ print_changed_diff ( changed) ;
149
+ }
150
+
151
+ /// This function limits the number of lints in the collection if needed.
152
+ ///
153
+ /// It's honestly amazing that a function like this is needed. But some restriction
154
+ /// lints (Looking at you `implicit_return` and `if_then_some_else_none`) trigger a lot
155
+ /// like 60'000+ times in our CI.
156
+ ///
157
+ /// Each lint in the list will be limited to 200 messages
158
+ fn limit_by_lint < T , F > ( list : & mut Vec < T > , lint_key : F ) -> Option < String >
159
+ where
160
+ F : Fn ( & T ) -> & str ,
161
+ {
162
+ const PER_LINT_LIMIT : usize = 200 ;
163
+
164
+ // Everything is fine, nothing to see here.
165
+ if list. len ( ) < PER_LINT_LIMIT {
166
+ return None ;
167
+ }
168
+
169
+ let mut keyed_list: Vec < _ > = list
170
+ . drain ( ..)
171
+ . map ( |warning| ( lint_key ( & warning) . to_string ( ) , warning) )
172
+ . collect ( ) ;
173
+
174
+ keyed_list. sort_unstable_by ( |( a, _) , ( b, _) | a. cmp ( b) ) ;
175
+
176
+ let last_idx = keyed_list. len ( ) - 1 ;
177
+ let mut current_key = keyed_list[ 0 ] . 0 . clone ( ) ;
178
+ let mut current_ctn = 0 ;
179
+ let mut limit_message = String :: new ( ) ;
180
+ keyed_list
181
+ . drain ( ..)
182
+ . enumerate ( )
183
+ . filter_map ( |( idx, ( key, warning) ) | {
184
+ if key != current_key || idx == last_idx {
185
+ if current_ctn >= PER_LINT_LIMIT {
186
+ writeln ! (
187
+ & mut limit_message,
188
+ "* Hid {} messages for `{}`" ,
189
+ current_ctn - PER_LINT_LIMIT ,
190
+ key
191
+ )
192
+ . unwrap ( ) ;
193
+ }
194
+ current_key = key;
195
+ current_ctn = 0 ;
196
+ }
197
+
198
+ current_ctn += 1 ;
199
+
200
+ ( current_ctn < PER_LINT_LIMIT ) . then_some ( warning)
201
+ } )
202
+ . collect_into ( list) ;
203
+
204
+ Some ( limit_message)
136
205
}
137
206
138
207
/// This generates the `x added` string for the start of the job summery.
0 commit comments