@@ -10,9 +10,10 @@ use crate::clippy_project_root;
10
10
11
11
use std:: collections:: HashMap ;
12
12
use std:: process:: Command ;
13
- use std:: { fs:: write, path:: PathBuf } ;
13
+ use std:: { fmt , fs:: write, path:: PathBuf } ;
14
14
15
15
use serde:: { Deserialize , Serialize } ;
16
+ use serde_json:: Value ;
16
17
17
18
// use this to store the crates when interacting with the crates.toml file
18
19
#[ derive( Debug , Serialize , Deserialize ) ]
@@ -43,6 +44,27 @@ struct Crate {
43
44
path : PathBuf ,
44
45
}
45
46
47
+ #[ derive( Debug ) ]
48
+ struct ClippyWarning {
49
+ crate_name : String ,
50
+ crate_version : String ,
51
+ file : String ,
52
+ line : String ,
53
+ column : String ,
54
+ linttype : String ,
55
+ message : String ,
56
+ }
57
+
58
+ impl std:: fmt:: Display for ClippyWarning {
59
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
60
+ writeln ! (
61
+ f,
62
+ r#"{}/{}/{}:{}:{} {} "{}""# ,
63
+ & self . crate_name, & self . crate_version, & self . file, & self . line, & self . column, & self . linttype, & self . message
64
+ )
65
+ }
66
+ }
67
+
46
68
impl CrateSource {
47
69
fn download_and_extract ( & self ) -> Crate {
48
70
let extract_dir = PathBuf :: from ( "target/crater/crates" ) ;
@@ -96,7 +118,7 @@ impl Crate {
96
118
// src/cargo/ops/cargo_compile.rs:127:35: warning: usage of `FromIterator::from_iter`
97
119
. args ( & [
98
120
"--" ,
99
- "--message-format=short " ,
121
+ "--message-format=json " ,
100
122
"--" ,
101
123
"--cap-lints=warn" ,
102
124
"-Wclippy::pedantic" ,
@@ -105,27 +127,17 @@ impl Crate {
105
127
. current_dir ( & self . path )
106
128
. output ( )
107
129
. unwrap ( ) ;
108
- let stderr = String :: from_utf8_lossy ( & all_output. stderr ) ;
109
- let output_lines = stderr. lines ( ) ;
110
- let mut output: Vec < String > = output_lines
130
+ let stdout = String :: from_utf8_lossy ( & all_output. stdout ) ;
131
+ let output_lines = stdout. lines ( ) ;
132
+ //dbg!(&output_lines);
133
+ let warnings: Vec < ClippyWarning > = output_lines
111
134
. into_iter ( )
112
- . filter ( |line| line. contains ( ": warning: " ) )
113
- // prefix with the crate name and version
114
- // cargo-0.49.0/src/cargo/ops/cargo_compile.rs:127:35: warning: usage of `FromIterator::from_iter`
115
- . map ( |line| format ! ( "{}-{}/{}" , self . name, self . version, line) )
116
- // remove the "warning: "
117
- . map ( |line| {
118
- let remove_pat = "warning: " ;
119
- let pos = line
120
- . find ( & remove_pat)
121
- . expect ( "clippy output did not contain \" warning: \" " ) ;
122
- let mut new = line[ 0 ..pos] . to_string ( ) ;
123
- new. push_str ( & line[ pos + remove_pat. len ( ) ..] ) ;
124
- new. push ( '\n' ) ;
125
- new
126
- } )
135
+ // get all clippy warnings
136
+ . filter ( |line| line. contains ( "clippy::" ) )
137
+ . map ( |json_msg| parse_json_message ( json_msg, & self ) )
127
138
. collect ( ) ;
128
139
140
+ let mut output: Vec < String > = warnings. iter ( ) . map ( |warning| warning. to_string ( ) ) . collect ( ) ;
129
141
// sort messages alphabetically to avoid noise in the logs
130
142
output. sort ( ) ;
131
143
output
@@ -167,6 +179,30 @@ fn read_crates() -> Vec<CrateSource> {
167
179
crate_sources
168
180
}
169
181
182
+ // extract interesting data from a json lint message
183
+ fn parse_json_message ( json_message : & str , krate : & Crate ) -> ClippyWarning {
184
+ let jmsg: Value = serde_json:: from_str ( & json_message) . unwrap_or_else ( |e| panic ! ( "Failed to parse json:\n {:?}" , e) ) ;
185
+
186
+ ClippyWarning {
187
+ crate_name : krate. name . to_string ( ) ,
188
+ crate_version : krate. version . to_string ( ) ,
189
+ file : jmsg[ "message" ] [ "spans" ] [ 0 ] [ "file_name" ]
190
+ . to_string ( )
191
+ . trim_matches ( '"' )
192
+ . into ( ) ,
193
+ line : jmsg[ "message" ] [ "spans" ] [ 0 ] [ "line_start" ]
194
+ . to_string ( )
195
+ . trim_matches ( '"' )
196
+ . into ( ) ,
197
+ column : jmsg[ "message" ] [ "spans" ] [ 0 ] [ "text" ] [ 0 ] [ "highlight_start" ]
198
+ . to_string ( )
199
+ . trim_matches ( '"' )
200
+ . into ( ) ,
201
+ linttype : jmsg[ "message" ] [ "code" ] [ "code" ] . to_string ( ) . trim_matches ( '"' ) . into ( ) ,
202
+ message : jmsg[ "message" ] [ "message" ] . to_string ( ) . trim_matches ( '"' ) . into ( ) ,
203
+ }
204
+ }
205
+
170
206
// the main fn
171
207
pub fn run ( ) {
172
208
let cargo_clippy_path: PathBuf = PathBuf :: from ( "target/debug/cargo-clippy" ) ;
0 commit comments