@@ -129,12 +129,8 @@ struct DrainState<'cfg> {
129
129
messages : Arc < Queue < Message > > ,
130
130
/// Diagnostic deduplication support.
131
131
diag_dedupe : DiagDedupe < ' cfg > ,
132
- /// Count of warnings, used to print a summary after the job succeeds.
133
- ///
134
- /// First value is the total number of warnings, and the second value is
135
- /// the number that were suppressed because they were duplicates of a
136
- /// previous warning.
137
- warning_count : HashMap < JobId , ( usize , usize ) > ,
132
+ /// Count of warnings, used to print a summary after the job succeeds
133
+ warning_count : HashMap < JobId , WarningCount > ,
138
134
active : HashMap < JobId , Unit > ,
139
135
compiled : HashSet < PackageId > ,
140
136
documented : HashSet < PackageId > ,
@@ -170,6 +166,50 @@ struct DrainState<'cfg> {
170
166
per_package_future_incompat_reports : Vec < FutureIncompatReportPackage > ,
171
167
}
172
168
169
+ /// Count of warnings, used to print a summary after the job succeeds
170
+ #[ derive( Default ) ]
171
+ pub struct WarningCount {
172
+ /// total number of warnings
173
+ pub total : usize ,
174
+ /// number of warnings that were suppressed because they
175
+ /// were duplicates of a previous warning
176
+ pub duplicates : usize ,
177
+ /// number of fixable warnings set to `NotAllowed`
178
+ /// if any errors have been seen ofr the current
179
+ /// target
180
+ pub fixable : FixableWarnings ,
181
+ }
182
+
183
+ impl WarningCount {
184
+ /// If an error is seen this should be called
185
+ /// to set `fixable` to `NotAllowed`
186
+ fn disallow_fixable ( & mut self ) {
187
+ self . fixable = FixableWarnings :: NotAllowed ;
188
+ }
189
+
190
+ /// Checks fixable if warnings are allowed
191
+ /// fixable warnings are allowed if no
192
+ /// errors have been seen for the current
193
+ /// target. If an error was seen `fixable`
194
+ /// will be `NotAllowed`.
195
+ fn fixable_allowed ( & self ) -> bool {
196
+ match & self . fixable {
197
+ FixableWarnings :: NotAllowed => false ,
198
+ _ => true ,
199
+ }
200
+ }
201
+ }
202
+
203
+ /// Used to keep track of how many fixable warnings there are
204
+ /// and if fixable warnings are allowed
205
+ #[ derive( Default ) ]
206
+ pub enum FixableWarnings {
207
+ NotAllowed ,
208
+ #[ default]
209
+ Zero ,
210
+ Positive ( usize ) ,
211
+ }
212
+
173
213
pub struct ErrorsDuringDrain {
174
214
pub count : usize ,
175
215
}
@@ -311,10 +351,12 @@ enum Message {
311
351
id : JobId ,
312
352
level : String ,
313
353
diag : String ,
354
+ fixable : bool ,
314
355
} ,
315
356
WarningCount {
316
357
id : JobId ,
317
358
emitted : bool ,
359
+ fixable : bool ,
318
360
} ,
319
361
FixDiagnostic ( diagnostic_server:: Message ) ,
320
362
Token ( io:: Result < Acquired > ) ,
@@ -363,20 +405,22 @@ impl<'a, 'cfg> JobState<'a, 'cfg> {
363
405
Ok ( ( ) )
364
406
}
365
407
366
- pub fn emit_diag ( & self , level : String , diag : String ) -> CargoResult < ( ) > {
408
+ pub fn emit_diag ( & self , level : String , diag : String , fixable : bool ) -> CargoResult < ( ) > {
367
409
if let Some ( dedupe) = self . output {
368
410
let emitted = dedupe. emit_diag ( & diag) ?;
369
411
if level == "warning" {
370
412
self . messages . push ( Message :: WarningCount {
371
413
id : self . id ,
372
414
emitted,
415
+ fixable,
373
416
} ) ;
374
417
}
375
418
} else {
376
419
self . messages . push_bounded ( Message :: Diagnostic {
377
420
id : self . id ,
378
421
level,
379
422
diag,
423
+ fixable,
380
424
} ) ;
381
425
}
382
426
Ok ( ( ) )
@@ -679,14 +723,28 @@ impl<'cfg> DrainState<'cfg> {
679
723
shell. print_ansi_stderr ( err. as_bytes ( ) ) ?;
680
724
shell. err ( ) . write_all ( b"\n " ) ?;
681
725
}
682
- Message :: Diagnostic { id, level, diag } => {
726
+ Message :: Diagnostic {
727
+ id,
728
+ level,
729
+ diag,
730
+ fixable,
731
+ } => {
683
732
let emitted = self . diag_dedupe . emit_diag ( & diag) ?;
684
733
if level == "warning" {
685
- self . bump_warning_count ( id, emitted) ;
734
+ self . bump_warning_count ( id, emitted, fixable) ;
735
+ }
736
+ if level == "error" {
737
+ let cnts = self . warning_count . entry ( id) . or_default ( ) ;
738
+ // If there is an error, the `cargo fix` message should not show
739
+ cnts. disallow_fixable ( ) ;
686
740
}
687
741
}
688
- Message :: WarningCount { id, emitted } => {
689
- self . bump_warning_count ( id, emitted) ;
742
+ Message :: WarningCount {
743
+ id,
744
+ emitted,
745
+ fixable,
746
+ } => {
747
+ self . bump_warning_count ( id, emitted, fixable) ;
690
748
}
691
749
Message :: FixDiagnostic ( msg) => {
692
750
self . print . print ( & msg) ?;
@@ -1127,19 +1185,34 @@ impl<'cfg> DrainState<'cfg> {
1127
1185
Ok ( ( ) )
1128
1186
}
1129
1187
1130
- fn bump_warning_count ( & mut self , id : JobId , emitted : bool ) {
1188
+ fn bump_warning_count ( & mut self , id : JobId , emitted : bool , fixable : bool ) {
1131
1189
let cnts = self . warning_count . entry ( id) . or_default ( ) ;
1132
- cnts. 0 += 1 ;
1190
+ cnts. total += 1 ;
1133
1191
if !emitted {
1134
- cnts. 1 += 1 ;
1192
+ cnts. duplicates += 1 ;
1193
+ // Don't add to fixable if it's already been emitted
1194
+ } else if fixable {
1195
+ // Do not add anything to the fixable warning count if
1196
+ // is `NotAllowed` since that indicates there was an
1197
+ // error while building this `Unit`
1198
+ if cnts. fixable_allowed ( ) {
1199
+ cnts. fixable = match cnts. fixable {
1200
+ FixableWarnings :: NotAllowed => FixableWarnings :: NotAllowed ,
1201
+ FixableWarnings :: Zero => FixableWarnings :: Positive ( 1 ) ,
1202
+ FixableWarnings :: Positive ( fixable) => FixableWarnings :: Positive ( fixable + 1 ) ,
1203
+ } ;
1204
+ }
1135
1205
}
1136
1206
}
1137
1207
1138
1208
/// Displays a final report of the warnings emitted by a particular job.
1139
1209
fn report_warning_count ( & mut self , config : & Config , id : JobId ) {
1140
1210
let count = match self . warning_count . remove ( & id) {
1141
- Some ( count) => count,
1142
- None => return ,
1211
+ // An error could add an entry for a `Unit`
1212
+ // with 0 warnings but having fixable
1213
+ // warnings be disallowed
1214
+ Some ( count) if count. total > 0 => count,
1215
+ None | Some ( _) => return ,
1143
1216
} ;
1144
1217
let unit = & self . active [ & id] ;
1145
1218
let mut message = format ! ( "`{}` ({}" , unit. pkg. name( ) , unit. target. description_named( ) ) ;
@@ -1151,15 +1224,47 @@ impl<'cfg> DrainState<'cfg> {
1151
1224
message. push_str ( " doc" ) ;
1152
1225
}
1153
1226
message. push_str ( ") generated " ) ;
1154
- match count. 0 {
1227
+ match count. total {
1155
1228
1 => message. push_str ( "1 warning" ) ,
1156
1229
n => drop ( write ! ( message, "{} warnings" , n) ) ,
1157
1230
} ;
1158
- match count. 1 {
1231
+ match count. duplicates {
1159
1232
0 => { }
1160
1233
1 => message. push_str ( " (1 duplicate)" ) ,
1161
1234
n => drop ( write ! ( message, " ({} duplicates)" , n) ) ,
1162
1235
}
1236
+ // Only show the `cargo fix` message if its a local `Unit`
1237
+ if unit. is_local ( ) && config. nightly_features_allowed {
1238
+ // Do not show this if there are any errors or no fixable warnings
1239
+ if let FixableWarnings :: Positive ( fixable) = count. fixable {
1240
+ // `cargo fix` doesnt have an option for custom builds
1241
+ if !unit. target . is_custom_build ( ) {
1242
+ let mut command = {
1243
+ let named = unit. target . description_named ( ) ;
1244
+ // if its a lib we need to add the package to fix
1245
+ if unit. target . is_lib ( ) {
1246
+ format ! ( "{} -p {}" , named, unit. pkg. name( ) )
1247
+ } else {
1248
+ named
1249
+ }
1250
+ } ;
1251
+ if unit. mode . is_rustc_test ( )
1252
+ && !( unit. target . is_test ( ) || unit. target . is_bench ( ) )
1253
+ {
1254
+ command. push_str ( " --tests" ) ;
1255
+ }
1256
+ let mut suggestions = format ! ( "{} suggestion" , fixable) ;
1257
+ if fixable > 1 {
1258
+ suggestions. push_str ( "s" )
1259
+ }
1260
+ drop ( write ! (
1261
+ message,
1262
+ " (run `cargo fix --{}` to apply {})" ,
1263
+ command, suggestions
1264
+ ) )
1265
+ }
1266
+ }
1267
+ }
1163
1268
// Errors are ignored here because it is tricky to handle them
1164
1269
// correctly, and they aren't important.
1165
1270
drop ( config. shell ( ) . warn ( message) ) ;
0 commit comments