@@ -10,9 +10,10 @@ use crate::clippy_project_root;
1010
1111use std:: collections:: HashMap ;
1212use std:: process:: Command ;
13- use std:: { fs:: write, path:: PathBuf } ;
13+ use std:: { fmt , fs:: write, path:: PathBuf } ;
1414
1515use serde:: { Deserialize , Serialize } ;
16+ use serde_json:: Value ;
1617
1718// use this to store the crates when interacting with the crates.toml file
1819#[ derive( Debug , Serialize , Deserialize ) ]
@@ -43,6 +44,27 @@ struct Crate {
4344 path : PathBuf ,
4445}
4546
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+
4668impl CrateSource {
4769 fn download_and_extract ( & self ) -> Crate {
4870 let extract_dir = PathBuf :: from ( "target/crater/crates" ) ;
@@ -96,7 +118,7 @@ impl Crate {
96118 // src/cargo/ops/cargo_compile.rs:127:35: warning: usage of `FromIterator::from_iter`
97119 . args ( & [
98120 "--" ,
99- "--message-format=short " ,
121+ "--message-format=json " ,
100122 "--" ,
101123 "--cap-lints=warn" ,
102124 "-Wclippy::pedantic" ,
@@ -105,27 +127,17 @@ impl Crate {
105127 . current_dir ( & self . path )
106128 . output ( )
107129 . 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
111134 . 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 ) )
127138 . collect ( ) ;
128139
140+ let mut output: Vec < String > = warnings. iter ( ) . map ( |warning| warning. to_string ( ) ) . collect ( ) ;
129141 // sort messages alphabetically to avoid noise in the logs
130142 output. sort ( ) ;
131143 output
@@ -167,6 +179,30 @@ fn read_crates() -> Vec<CrateSource> {
167179 crate_sources
168180}
169181
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+
170206// the main fn
171207pub fn run ( ) {
172208 let cargo_clippy_path: PathBuf = PathBuf :: from ( "target/debug/cargo-clippy" ) ;
0 commit comments