12
12
// - TODO xFrednet 2021-02-13: Collect depreciations and maybe renames
13
13
14
14
use if_chain:: if_chain;
15
+ use rustc_ast:: LitKind ;
15
16
use rustc_data_structures:: fx:: FxHashMap ;
16
17
use rustc_hir:: {
17
18
self as hir, def:: DefKind , intravisit, intravisit:: Visitor , ExprKind , Item , ItemKind , Mutability , QPath ,
@@ -41,6 +42,8 @@ const BLACK_LISTED_LINTS: [&str; 3] = ["lint_author", "deep_code_inspection", "i
41
42
const IGNORED_LINT_GROUPS : [ & str ; 1 ] = [ "clippy::all" ] ;
42
43
/// Lints within this group will be excluded from the collection
43
44
const EXCLUDED_LINT_GROUPS : [ & str ; 1 ] = [ "clippy::internal" ] ;
45
+ /// Collected deprecated lint will be assigned to this group in the JSON output
46
+ const DEPRECATED_LINT_GROUP_STR : & str = "deprecated" ;
44
47
45
48
const LINT_EMISSION_FUNCTIONS : [ & [ & str ] ; 7 ] = [
46
49
& [ "clippy_utils" , "diagnostics" , "span_lint" ] ,
@@ -66,8 +69,12 @@ const SUGGESTION_FUNCTIONS: [&[&str]; 2] = [
66
69
& [ "clippy_utils" , "diagnostics" , "multispan_sugg" ] ,
67
70
& [ "clippy_utils" , "diagnostics" , "multispan_sugg_with_applicability" ] ,
68
71
] ;
72
+ const REGISTER_REMOVED_METHOD : & str = "register_removed" ;
73
+ const REGISTER_REMOVED_LINT_ID_INDEX : usize = 1 ;
74
+ const REGISTER_REMOVED_REASON_INDEX : usize = 2 ;
75
+ const CLIPPY_LINT_PREFIX : & str = "clippy::" ;
69
76
70
- /// The index of the applicability name of `paths::APPLICABILITY_VALUES`
77
+ /// The index of the applicability name in `paths::APPLICABILITY_VALUES`
71
78
const APPLICABILITY_NAME_INDEX : usize = 2 ;
72
79
73
80
declare_clippy_lint ! {
@@ -246,9 +253,10 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
246
253
}
247
254
}
248
255
249
- /// Collecting constant applicability from the actual lint emissions
256
+ /// Collecting the applicability from the actual lint emissions and removed lints with
257
+ /// the reasoning behind the removal.
250
258
///
251
- /// Example:
259
+ /// Example of the extracted `Applicability` value :
252
260
/// ```rust, ignore
253
261
/// span_lint_and_sugg(
254
262
/// cx,
@@ -261,6 +269,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
261
269
/// );
262
270
/// ```
263
271
fn check_expr ( & mut self , cx : & LateContext < ' hir > , expr : & ' hir hir:: Expr < ' _ > ) {
272
+ // Applicability value extraction
264
273
if let Some ( args) = match_lint_emission ( cx, expr) {
265
274
let mut emission_info = extract_emission_info ( cx, args) ;
266
275
if emission_info. is_empty ( ) {
@@ -277,6 +286,29 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
277
286
app_info. applicability = applicability;
278
287
app_info. is_multi_part_suggestion = is_multi_part;
279
288
}
289
+
290
+ return ;
291
+ }
292
+
293
+ // Removed lint extraction
294
+ if let Some ( args) = match_removed_emission ( cx, expr) {
295
+ if let Some ( ( id, reason) ) = extract_deprecation_info ( args) {
296
+ if let Some ( clippy_id) = id. strip_prefix ( CLIPPY_LINT_PREFIX ) {
297
+ let id_span = SerializableSpan :: from_span ( cx, args[ REGISTER_REMOVED_LINT_ID_INDEX ] . span ) ;
298
+ self . lints . push ( LintMetadata :: new (
299
+ clippy_id. to_ascii_lowercase ( ) ,
300
+ id_span,
301
+ DEPRECATED_LINT_GROUP_STR . to_string ( ) ,
302
+ format_deprecation_reason ( & reason) ,
303
+ ) ) ;
304
+ }
305
+ } else {
306
+ lint_collection_error_span (
307
+ cx,
308
+ expr. span ,
309
+ "Unable to extract arguments, please make sure to only use string literals" ,
310
+ )
311
+ }
280
312
}
281
313
}
282
314
}
@@ -359,6 +391,55 @@ fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &s
359
391
) ;
360
392
}
361
393
394
+ fn lint_collection_error_span ( cx : & LateContext < ' _ > , span : Span , message : & str ) {
395
+ span_lint (
396
+ cx,
397
+ INTERNAL_METADATA_COLLECTOR ,
398
+ span,
399
+ & format ! ( "metadata collection error: {}" , message) ,
400
+ ) ;
401
+ }
402
+
403
+ // ==================================================================
404
+ // Removed lints
405
+ // ==================================================================
406
+ fn match_removed_emission < ' hir > ( cx : & LateContext < ' hir > , expr : & ' hir hir:: Expr < ' _ > ) -> Option < & ' hir [ hir:: Expr < ' hir > ] > {
407
+ if_chain ! {
408
+ // Type
409
+ if let ExprKind :: MethodCall ( path, _path_span, args, _arg_span) = & expr. kind;
410
+ let ( self_ty, _) = walk_ptrs_ty_depth( cx. typeck_results( ) . expr_ty( & args[ 0 ] ) ) ;
411
+ if match_type( cx, self_ty, & paths:: RUSTC_LINT_STORE ) ;
412
+ // Method
413
+ if path. ident. name. as_str( ) == REGISTER_REMOVED_METHOD ;
414
+ then {
415
+ return Some ( & args)
416
+ }
417
+ }
418
+
419
+ None
420
+ }
421
+
422
+ fn extract_deprecation_info ( args : & [ hir:: Expr < ' _ > ] ) -> Option < ( String , String ) > {
423
+ let lint_id = extract_string_literal ( & args[ REGISTER_REMOVED_LINT_ID_INDEX ] ) ;
424
+ let removal_reason = extract_string_literal ( & args[ REGISTER_REMOVED_REASON_INDEX ] ) ;
425
+
426
+ lint_id. zip ( removal_reason)
427
+ }
428
+
429
+ fn extract_string_literal ( expr : & hir:: Expr < ' _ > ) -> Option < String > {
430
+ if let ExprKind :: Lit ( spanned) = & expr. kind {
431
+ if let LitKind :: Str ( sym, _) = & spanned. node {
432
+ return Some ( sym. as_str ( ) . to_string ( ) ) ;
433
+ }
434
+ }
435
+
436
+ None
437
+ }
438
+
439
+ fn format_deprecation_reason ( reason : & str ) -> String {
440
+ format ! ( "**Deprecation reason**\n {}" , reason)
441
+ }
442
+
362
443
// ==================================================================
363
444
// Applicability
364
445
// ==================================================================
0 commit comments