@@ -131,10 +131,11 @@ struct DrainState<'cfg> {
131
131
diag_dedupe : DiagDedupe < ' cfg > ,
132
132
/// Count of warnings, used to print a summary after the job succeeds.
133
133
///
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
135
135
/// 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 ) > ,
138
139
active : HashMap < JobId , Unit > ,
139
140
compiled : HashSet < PackageId > ,
140
141
documented : HashSet < PackageId > ,
@@ -311,10 +312,12 @@ enum Message {
311
312
id : JobId ,
312
313
level : String ,
313
314
diag : String ,
315
+ fixable : bool ,
314
316
} ,
315
317
WarningCount {
316
318
id : JobId ,
317
319
emitted : bool ,
320
+ fixable : bool ,
318
321
} ,
319
322
FixDiagnostic ( diagnostic_server:: Message ) ,
320
323
Token ( io:: Result < Acquired > ) ,
@@ -363,20 +366,22 @@ impl<'a, 'cfg> JobState<'a, 'cfg> {
363
366
Ok ( ( ) )
364
367
}
365
368
366
- pub fn emit_diag ( & self , level : String , diag : String ) -> CargoResult < ( ) > {
369
+ pub fn emit_diag ( & self , level : String , diag : String , fixable : bool ) -> CargoResult < ( ) > {
367
370
if let Some ( dedupe) = self . output {
368
371
let emitted = dedupe. emit_diag ( & diag) ?;
369
372
if level == "warning" {
370
373
self . messages . push ( Message :: WarningCount {
371
374
id : self . id ,
372
375
emitted,
376
+ fixable,
373
377
} ) ;
374
378
}
375
379
} else {
376
380
self . messages . push_bounded ( Message :: Diagnostic {
377
381
id : self . id ,
378
382
level,
379
383
diag,
384
+ fixable,
380
385
} ) ;
381
386
}
382
387
Ok ( ( ) )
@@ -679,14 +684,31 @@ impl<'cfg> DrainState<'cfg> {
679
684
shell. print_ansi_stderr ( err. as_bytes ( ) ) ?;
680
685
shell. err ( ) . write_all ( b"\n " ) ?;
681
686
}
682
- Message :: Diagnostic { id, level, diag } => {
687
+ Message :: Diagnostic {
688
+ id,
689
+ level,
690
+ diag,
691
+ fixable,
692
+ } => {
683
693
let emitted = self . diag_dedupe . emit_diag ( & diag) ?;
684
694
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
+ }
686
704
}
687
705
}
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) ;
690
712
}
691
713
Message :: FixDiagnostic ( msg) => {
692
714
self . print . print ( & msg) ?;
@@ -1127,18 +1149,34 @@ impl<'cfg> DrainState<'cfg> {
1127
1149
Ok ( ( ) )
1128
1150
}
1129
1151
1130
- fn bump_warning_count ( & mut self , id : JobId , emitted : bool ) {
1152
+ fn bump_warning_count ( & mut self , id : JobId , emitted : bool , fixable : bool ) {
1131
1153
let cnts = self . warning_count . entry ( id) . or_default ( ) ;
1132
1154
cnts. 0 += 1 ;
1133
1155
if !emitted {
1134
1156
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
+ }
1135
1165
}
1136
1166
}
1137
1167
1138
1168
/// Displays a final report of the warnings emitted by a particular job.
1139
1169
fn report_warning_count ( & mut self , config : & Config , id : JobId ) {
1140
1170
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
+ }
1142
1180
None => return ,
1143
1181
} ;
1144
1182
let unit = & self . active [ & id] ;
@@ -1160,6 +1198,41 @@ impl<'cfg> DrainState<'cfg> {
1160
1198
1 => message. push_str ( " (1 duplicate)" ) ,
1161
1199
n => drop ( write ! ( message, " ({} duplicates)" , n) ) ,
1162
1200
}
1201
+ // Only show the `cargo fix` message if its a local `Unit`
1202
+ if unit. is_local ( ) && config. nightly_features_allowed {
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
+ }
1163
1236
// Errors are ignored here because it is tricky to handle them
1164
1237
// correctly, and they aren't important.
1165
1238
drop ( config. shell ( ) . warn ( message) ) ;
0 commit comments