@@ -131,10 +131,11 @@ struct DrainState<'cfg> {
131131 diag_dedupe : DiagDedupe < ' cfg > ,
132132 /// Count of warnings, used to print a summary after the job succeeds.
133133 ///
134- /// First value is the total number of warnings, and the second value is
134+ /// First value is the total number of warnings, the second value is
135135 /// the number that were suppressed because they were duplicates of a
136- /// previous warning.
137- warning_count : HashMap < JobId , ( usize , usize ) > ,
136+ /// previous warning, and the third value is for the number of fixable
137+ /// warnings (set to -1 if there are any errors).
138+ warning_count : HashMap < JobId , ( usize , usize , isize ) > ,
138139 active : HashMap < JobId , Unit > ,
139140 compiled : HashSet < PackageId > ,
140141 documented : HashSet < PackageId > ,
@@ -311,10 +312,12 @@ enum Message {
311312 id : JobId ,
312313 level : String ,
313314 diag : String ,
315+ fixable : bool ,
314316 } ,
315317 WarningCount {
316318 id : JobId ,
317319 emitted : bool ,
320+ fixable : bool ,
318321 } ,
319322 FixDiagnostic ( diagnostic_server:: Message ) ,
320323 Token ( io:: Result < Acquired > ) ,
@@ -363,20 +366,22 @@ impl<'a, 'cfg> JobState<'a, 'cfg> {
363366 Ok ( ( ) )
364367 }
365368
366- pub fn emit_diag ( & self , level : String , diag : String ) -> CargoResult < ( ) > {
369+ pub fn emit_diag ( & self , level : String , diag : String , fixable : bool ) -> CargoResult < ( ) > {
367370 if let Some ( dedupe) = self . output {
368371 let emitted = dedupe. emit_diag ( & diag) ?;
369372 if level == "warning" {
370373 self . messages . push ( Message :: WarningCount {
371374 id : self . id ,
372375 emitted,
376+ fixable,
373377 } ) ;
374378 }
375379 } else {
376380 self . messages . push_bounded ( Message :: Diagnostic {
377381 id : self . id ,
378382 level,
379383 diag,
384+ fixable,
380385 } ) ;
381386 }
382387 Ok ( ( ) )
@@ -679,14 +684,31 @@ impl<'cfg> DrainState<'cfg> {
679684 shell. print_ansi_stderr ( err. as_bytes ( ) ) ?;
680685 shell. err ( ) . write_all ( b"\n " ) ?;
681686 }
682- Message :: Diagnostic { id, level, diag } => {
687+ Message :: Diagnostic {
688+ id,
689+ level,
690+ diag,
691+ fixable,
692+ } => {
683693 let emitted = self . diag_dedupe . emit_diag ( & diag) ?;
684694 if level == "warning" {
685- self . bump_warning_count ( id, emitted) ;
695+ self . bump_warning_count ( id, emitted, fixable) ;
696+ }
697+ if level == "error" {
698+ // If there is an error set fixable count to -1 so the `cargo fix`
699+ // message does not show
700+ let cnts = self . warning_count . entry ( id) . or_default ( ) ;
701+ if fixable {
702+ cnts. 2 = -1 ;
703+ }
686704 }
687705 }
688- Message :: WarningCount { id, emitted } => {
689- self . bump_warning_count ( id, emitted) ;
706+ Message :: WarningCount {
707+ id,
708+ emitted,
709+ fixable,
710+ } => {
711+ self . bump_warning_count ( id, emitted, fixable) ;
690712 }
691713 Message :: FixDiagnostic ( msg) => {
692714 self . print . print ( & msg) ?;
@@ -1127,18 +1149,34 @@ impl<'cfg> DrainState<'cfg> {
11271149 Ok ( ( ) )
11281150 }
11291151
1130- fn bump_warning_count ( & mut self , id : JobId , emitted : bool ) {
1152+ fn bump_warning_count ( & mut self , id : JobId , emitted : bool , fixable : bool ) {
11311153 let cnts = self . warning_count . entry ( id) . or_default ( ) ;
11321154 cnts. 0 += 1 ;
11331155 if !emitted {
11341156 cnts. 1 += 1 ;
1157+ // Don't add to fixable if it's already been emitted
1158+ } else if fixable {
1159+ // Do not add anything to the fixable warning count if
1160+ // is `-1` since that indicates there was an error while
1161+ // building this `Unit`
1162+ if cnts. 2 >= 0 {
1163+ cnts. 2 += 1 ;
1164+ }
11351165 }
11361166 }
11371167
11381168 /// Displays a final report of the warnings emitted by a particular job.
11391169 fn report_warning_count ( & mut self , config : & Config , id : JobId ) {
11401170 let count = match self . warning_count . remove ( & id) {
1141- Some ( count) => count,
1171+ Some ( count) => {
1172+ // An error could add an entry for a `Unit`
1173+ // with 0 warnings but with count.2 = -1
1174+ if count. 0 > 0 {
1175+ count
1176+ } else {
1177+ return ;
1178+ }
1179+ }
11421180 None => return ,
11431181 } ;
11441182 let unit = & self . active [ & id] ;
@@ -1160,6 +1198,41 @@ impl<'cfg> DrainState<'cfg> {
11601198 1 => message. push_str ( " (1 duplicate)" ) ,
11611199 n => drop ( write ! ( message, " ({} duplicates)" , n) ) ,
11621200 }
1201+ // Only show the `cargo fix` message if its a local `Unit`
1202+ if unit. is_local ( ) {
1203+ match count. 2 {
1204+ // Do not show this if there are any errors (-1) or no fixable warnings
1205+ -1 | 0 => { }
1206+ n => {
1207+ // `cargo fix` doesnt have an option for custom builds
1208+ if !unit. target . is_custom_build ( ) {
1209+ let mut command = {
1210+ let named = unit. target . description_named ( ) ;
1211+ // if its a lib we need to add the package to fix
1212+ if named == "lib" {
1213+ format ! ( "{} -p {}" , named, unit. pkg. name( ) )
1214+ } else {
1215+ named
1216+ }
1217+ } ;
1218+ if unit. mode . is_rustc_test ( )
1219+ && !( unit. target . is_test ( ) || unit. target . is_bench ( ) )
1220+ {
1221+ command. push_str ( " --tests" ) ;
1222+ }
1223+ let mut suggestions = format ! ( "{} suggestion" , n) ;
1224+ if n > 1 {
1225+ suggestions. push_str ( "s" )
1226+ }
1227+ drop ( write ! (
1228+ message,
1229+ " (run `cargo fix --{}` to apply {})" ,
1230+ command, suggestions
1231+ ) )
1232+ }
1233+ }
1234+ }
1235+ }
11631236 // Errors are ignored here because it is tricky to handle them
11641237 // correctly, and they aren't important.
11651238 drop ( config. shell ( ) . warn ( message) ) ;
0 commit comments