1
- use std:: collections:: BTreeSet ;
2
1
use std:: fs;
3
2
use std:: path:: Path ;
4
3
5
- use itertools:: EitherOrBoth ;
4
+ use itertools:: { EitherOrBoth , Itertools } ;
6
5
use serde:: { Deserialize , Serialize } ;
7
6
8
7
use crate :: ClippyWarning ;
@@ -23,7 +22,7 @@ struct LintJson {
23
22
24
23
impl LintJson {
25
24
fn key ( & self ) -> impl Ord + ' _ {
26
- ( self . file_name . as_str ( ) , self . byte_pos , self . lint . as_str ( ) )
25
+ ( self . lint . as_str ( ) , self . file_name . as_str ( ) , self . byte_pos )
27
26
}
28
27
29
28
fn info_text ( & self , action : & str ) -> String {
@@ -61,23 +60,35 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) {
61
60
let old_warnings = load_warnings ( old_path) ;
62
61
let new_warnings = load_warnings ( new_path) ;
63
62
64
- let mut added = Vec :: new ( ) ;
65
- let mut removed = Vec :: new ( ) ;
66
- let mut changed = Vec :: new ( ) ;
67
-
68
- for change in itertools:: merge_join_by ( old_warnings, new_warnings, |old, new| old. key ( ) . cmp ( & new. key ( ) ) ) {
69
- match change {
70
- EitherOrBoth :: Both ( old, new) => {
71
- if old. rendered != new. rendered {
72
- changed. push ( ( old, new) ) ;
73
- }
74
- } ,
75
- EitherOrBoth :: Left ( old) => removed. push ( old) ,
76
- EitherOrBoth :: Right ( new) => added. push ( new) ,
63
+ let mut lint_warnings = vec ! [ ] ;
64
+
65
+ for ( name, changes) in & itertools:: merge_join_by ( old_warnings, new_warnings, |old, new| old. key ( ) . cmp ( & new. key ( ) ) )
66
+ . chunk_by ( |change| change. as_ref ( ) . into_left ( ) . lint . to_string ( ) )
67
+ {
68
+ let mut added = Vec :: new ( ) ;
69
+ let mut removed = Vec :: new ( ) ;
70
+ let mut changed = Vec :: new ( ) ;
71
+ for change in changes {
72
+ match change {
73
+ EitherOrBoth :: Both ( old, new) => {
74
+ if old. rendered != new. rendered {
75
+ changed. push ( ( old, new) ) ;
76
+ }
77
+ } ,
78
+ EitherOrBoth :: Left ( old) => removed. push ( old) ,
79
+ EitherOrBoth :: Right ( new) => added. push ( new) ,
80
+ }
77
81
}
78
- }
79
82
80
- let lint_warnings = group_by_lint ( added, removed, changed) ;
83
+ if !added. is_empty ( ) || !removed. is_empty ( ) || !changed. is_empty ( ) {
84
+ lint_warnings. push ( LintWarnings {
85
+ name,
86
+ added,
87
+ removed,
88
+ changed,
89
+ } ) ;
90
+ }
91
+ }
81
92
82
93
print_summary_table ( & lint_warnings) ;
83
94
println ! ( ) ;
@@ -110,60 +121,12 @@ struct LintWarnings {
110
121
changed : Vec < ( LintJson , LintJson ) > ,
111
122
}
112
123
113
- fn group_by_lint (
114
- mut added : Vec < LintJson > ,
115
- mut removed : Vec < LintJson > ,
116
- mut changed : Vec < ( LintJson , LintJson ) > ,
117
- ) -> Vec < LintWarnings > {
118
- /// Collects items from an iterator while the condition is met
119
- fn collect_while < T , F > ( iter : & mut std:: iter:: Peekable < impl Iterator < Item = T > > , mut condition : F ) -> Vec < T >
120
- where
121
- F : FnMut ( & T ) -> bool ,
122
- {
123
- let mut items = vec ! [ ] ;
124
- while iter. peek ( ) . map_or ( false , & mut condition) {
125
- items. push ( iter. next ( ) . unwrap ( ) ) ;
126
- }
127
- items
128
- }
129
-
130
- // Sort
131
- added. sort_unstable_by ( |a, b| a. lint . cmp ( & b. lint ) ) ;
132
- removed. sort_unstable_by ( |a, b| a. lint . cmp ( & b. lint ) ) ;
133
- changed. sort_unstable_by ( |( a, _) , ( b, _) | a. lint . cmp ( & b. lint ) ) ;
134
-
135
- // Collect lint names
136
- let lint_names: BTreeSet < _ > = added
137
- . iter ( )
138
- . chain ( removed. iter ( ) )
139
- . chain ( changed. iter ( ) . map ( |( a, _) | a) )
140
- . map ( |warning| & warning. lint )
141
- . cloned ( )
142
- . collect ( ) ;
143
-
144
- let mut added_iter = added. into_iter ( ) . peekable ( ) ;
145
- let mut removed_iter = removed. into_iter ( ) . peekable ( ) ;
146
- let mut changed_iter = changed. into_iter ( ) . peekable ( ) ;
147
-
148
- let mut lints = vec ! [ ] ;
149
- for name in lint_names {
150
- lints. push ( LintWarnings {
151
- added : collect_while ( & mut added_iter, |warning| warning. lint == name) ,
152
- removed : collect_while ( & mut removed_iter, |warning| warning. lint == name) ,
153
- changed : collect_while ( & mut changed_iter, |( warning, _) | warning. lint == name) ,
154
- name,
155
- } ) ;
156
- }
157
-
158
- lints
159
- }
160
-
161
124
fn print_lint_warnings ( lint : & LintWarnings , truncate_after : usize ) {
162
125
let name = & lint. name ;
163
126
let html_id = to_html_id ( name) ;
164
127
165
128
// The additional anchor is added for non GH viewers that don't prefix ID's
166
- println ! ( r#"## `{name}` <a id="user-content-{html_id}"/ >"# ) ;
129
+ println ! ( r#"## `{name}` <a id="user-content-{html_id}"></a >"# ) ;
167
130
println ! ( ) ;
168
131
169
132
print ! (
@@ -264,7 +227,7 @@ fn truncate<T>(list: &[T], truncate_after: usize) -> &[T] {
264
227
fn print_h3 ( lint : & str , title : & str ) {
265
228
let html_id = to_html_id ( lint) ;
266
229
// We have to use HTML here to be able to manually add an id.
267
- println ! ( r#"### {title} <a id="user-content-{html_id}-{title}"/ >"# ) ;
230
+ println ! ( r#"### {title} <a id="user-content-{html_id}-{title}"></a >"# ) ;
268
231
}
269
232
270
233
/// GitHub's markdown parsers doesn't like IDs with `::` and `_`. This simplifies
0 commit comments