Skip to content

Commit 90edfd5

Browse files
committed
Metadata collection monster eating removed lints
1 parent f773479 commit 90edfd5

File tree

2 files changed

+86
-3
lines changed

2 files changed

+86
-3
lines changed

clippy_lints/src/utils/internal_lints/metadata_collector.rs

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// - TODO xFrednet 2021-02-13: Collect depreciations and maybe renames
1313

1414
use if_chain::if_chain;
15+
use rustc_ast::LitKind;
1516
use rustc_data_structures::fx::FxHashMap;
1617
use rustc_hir::{
1718
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
4142
const IGNORED_LINT_GROUPS: [&str; 1] = ["clippy::all"];
4243
/// Lints within this group will be excluded from the collection
4344
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";
4447

4548
const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [
4649
&["clippy_utils", "diagnostics", "span_lint"],
@@ -66,8 +69,12 @@ const SUGGESTION_FUNCTIONS: [&[&str]; 2] = [
6669
&["clippy_utils", "diagnostics", "multispan_sugg"],
6770
&["clippy_utils", "diagnostics", "multispan_sugg_with_applicability"],
6871
];
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::";
6976

70-
/// The index of the applicability name of `paths::APPLICABILITY_VALUES`
77+
/// The index of the applicability name in `paths::APPLICABILITY_VALUES`
7178
const APPLICABILITY_NAME_INDEX: usize = 2;
7279

7380
declare_clippy_lint! {
@@ -246,9 +253,10 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
246253
}
247254
}
248255

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.
250258
///
251-
/// Example:
259+
/// Example of the extracted `Applicability` value:
252260
/// ```rust, ignore
253261
/// span_lint_and_sugg(
254262
/// cx,
@@ -261,6 +269,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
261269
/// );
262270
/// ```
263271
fn check_expr(&mut self, cx: &LateContext<'hir>, expr: &'hir hir::Expr<'_>) {
272+
// Applicability value extraction
264273
if let Some(args) = match_lint_emission(cx, expr) {
265274
let mut emission_info = extract_emission_info(cx, args);
266275
if emission_info.is_empty() {
@@ -277,6 +286,29 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
277286
app_info.applicability = applicability;
278287
app_info.is_multi_part_suggestion = is_multi_part;
279288
}
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+
}
280312
}
281313
}
282314
}
@@ -359,6 +391,55 @@ fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &s
359391
);
360392
}
361393

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+
362443
// ==================================================================
363444
// Applicability
364445
// ==================================================================

clippy_utils/src/paths.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet",
147147
pub const RESULT: [&str; 3] = ["core", "result", "Result"];
148148
pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"];
149149
pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"];
150+
#[cfg(feature = "metadata-collector-lint")]
151+
pub const RUSTC_LINT_STORE: [&str; 3] = ["rustc_lint", "context", "LintStore"];
150152
pub const RWLOCK_READ_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGuard"];
151153
pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"];
152154
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];

0 commit comments

Comments
 (0)