@@ -9,6 +9,7 @@ use crate::ClippyWarning;
99#[ derive( Deserialize , Serialize ) ]
1010struct LintJson {
1111 lint : String ,
12+ krate : String ,
1213 file_name : String ,
1314 byte_pos : ( u32 , u32 ) ,
1415 file_link : String ,
@@ -19,6 +20,10 @@ impl LintJson {
1920 fn key ( & self ) -> impl Ord + ' _ {
2021 ( self . file_name . as_str ( ) , self . byte_pos , self . lint . as_str ( ) )
2122 }
23+
24+ fn info_text ( & self , action : & str ) -> String {
25+ format ! ( "{action} `{}` in `{}` at {}" , self . lint, self . krate, self . file_link)
26+ }
2227}
2328
2429/// Creates the log file output for [`crate::config::OutputFormat::Json`]
@@ -30,6 +35,7 @@ pub(crate) fn output(clippy_warnings: Vec<ClippyWarning>) -> String {
3035 LintJson {
3136 file_name : span. file_name . clone ( ) ,
3237 byte_pos : ( span. byte_start , span. byte_end ) ,
38+ krate : warning. krate ,
3339 file_link : warning. url ,
3440 lint : warning. lint ,
3541 rendered : warning. diag . rendered . unwrap ( ) ,
@@ -51,12 +57,16 @@ fn print_warnings(title: &str, warnings: &[LintJson]) {
5157 return ;
5258 }
5359
54- println ! ( "### {title}" ) ;
60+ //We have to use HTML here to be able to manually add an id.
61+ println ! ( r#"<h3 id="{title}">{title}</h3>"# ) ;
62+ println ! ( ) ;
5563 for warning in warnings {
56- println ! ( "{title} `{}` at {}" , warning. lint, warning. file_link) ;
64+ println ! ( "{}" , warning. info_text( title) ) ;
65+ println ! ( ) ;
5766 println ! ( "```" ) ;
58- print ! ( "{}" , warning. rendered) ;
67+ println ! ( "{}" , warning. rendered. trim_end ( ) ) ;
5968 println ! ( "```" ) ;
69+ println ! ( ) ;
6070 }
6171}
6272
@@ -65,11 +75,14 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)]) {
6575 return ;
6676 }
6777
68- println ! ( "### Changed" ) ;
78+ //We have to use HTML here to be able to manually add an id.
79+ println ! ( r#"<h3 id="changed">Changed</h3>"# ) ;
80+ println ! ( ) ;
6981 for ( old, new) in changed {
70- println ! ( "Changed `{}` at {}" , new. lint, new. file_link) ;
82+ println ! ( "{}" , new. info_text( "Changed" ) ) ;
83+ println ! ( ) ;
7184 println ! ( "```diff" ) ;
72- for change in diff:: lines ( & old. rendered , & new. rendered ) {
85+ for change in diff:: lines ( old. rendered . trim_end ( ) , new. rendered . trim_end ( ) ) {
7386 use diff:: Result :: { Both , Left , Right } ;
7487
7588 match change {
@@ -109,13 +122,30 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path) {
109122 }
110123
111124 print ! (
112- "{} added , {} removed , {} changed \n \n " ,
113- added. len( ) ,
114- removed. len( ) ,
115- changed. len( )
125+ r## "{}, {}, {}"## ,
126+ count_string ( " added" , added . len( ) ) ,
127+ count_string ( " removed" , removed . len( ) ) ,
128+ count_string ( " changed" , changed . len( ) ) ,
116129 ) ;
130+ println ! ( ) ;
131+ println ! ( ) ;
117132
118133 print_warnings ( "Added" , & added) ;
119134 print_warnings ( "Removed" , & removed) ;
120135 print_changed_diff ( & changed) ;
121136}
137+
138+ /// This generates the `x added` string for the start of the job summery.
139+ /// It linkifies them if possible to jump to the respective heading.
140+ fn count_string ( label : & str , count : usize ) -> String {
141+ // Headlines are only added, if anything will be displayed under the headline.
142+ // We therefore only want to add links to them if they exist
143+ if count == 0 {
144+ format ! ( "0 {label}" )
145+ } else {
146+ // GitHub's job summaries don't add HTML ids to headings. That's why we
147+ // manually have to add them. GitHub prefixes these manual ids with
148+ // `user-content-` and that's how we end up with these awesome links :D
149+ format ! ( "[{count} {label}](#user-content-{label})" )
150+ }
151+ }
0 commit comments