Auto merge of #7197 - xFrednet:4310-depreciated-lints-collection, r=flip1995

Metadata collection monster eating deprecated lints

This adds the collection of deprecated lints to the metadata collection monster. The JSON output has the same structure with the *new* lint group "DEPRECATED". Here is one of fourteen examples it was able to dig up in Clippy's code:

```JSON
  {
    "id": "assign_op_pattern",
    "id_span": {
      "path": "src/assign_ops.rs",
      "line": 34
    },
    "group": "clippy::style",
    "docs": " **What it does:** Checks for `a = a op b` or `a = b commutative_op a` patterns.\n\n **Why is this bad?** These can be written as the shorter `a op= b`.\n\n **Known problems:** While forbidden by the spec, `OpAssign` traits may have\n implementations that differ from the regular `Op` impl.\n\n **Example:**\n ```rust\n let mut a = 5;\n let b = 0;\n // ...\n // Bad\n a = a + b;\n\n // Good\n a += b;\n ```\n",
    "applicability": {
      "is_multi_part_suggestion": false,
      "applicability": "MachineApplicable"
    }
  }
```

And you! Yes you! Sir or Madam can get all of this **for free** in Clippy if this PR gets merged. (Sorry for the silliness ^^)

---

See: #7172 for the full metadata collection to-do list or to suggest a new feature in connection to it 🙃

---

changelog: none

r? `@flip1995`
This commit is contained in:
bors 2021-05-12 08:01:10 +00:00
commit aa15a5442a
3 changed files with 62 additions and 24 deletions

View file

@ -1,6 +1,13 @@
/// This struct fakes the `Lint` declaration that is usually created by `declare_lint!`. This
/// enables the simple extraction of the metadata without changing the current deprecation
/// declaration.
pub struct ClippyDeprecatedLint;
macro_rules! declare_deprecated_lint { macro_rules! declare_deprecated_lint {
(pub $name: ident, $_reason: expr) => { { $(#[$attr:meta])* pub $name: ident, $_reason: expr} => {
declare_lint!(pub $name, Allow, "deprecated lint") $(#[$attr])*
#[allow(dead_code)]
pub static $name: ClippyDeprecatedLint = ClippyDeprecatedLint {};
} }
} }

View file

@ -162,6 +162,8 @@ macro_rules! extract_msrv_attr {
mod consts; mod consts;
#[macro_use] #[macro_use]
mod utils; mod utils;
#[cfg(feature = "metadata-collector-lint")]
mod deprecated_lints;
// begin lints modules, do not remove this comment, its used in `update_lints` // begin lints modules, do not remove this comment, its used in `update_lints`
mod absurd_extreme_comparisons; mod absurd_extreme_comparisons;

View file

@ -8,9 +8,6 @@
//! during any comparison or mapping. (Please take care of this, it's not fun to spend time on such //! during any comparison or mapping. (Please take care of this, it's not fun to spend time on such
//! a simple mistake) //! a simple mistake)
// # NITs
// - TODO xFrednet 2021-02-13: Collect depreciations and maybe renames
use if_chain::if_chain; use if_chain::if_chain;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_hir::{ use rustc_hir::{
@ -28,7 +25,7 @@ use std::path::Path;
use crate::utils::internal_lints::is_lint_ref_type; use crate::utils::internal_lints::is_lint_ref_type;
use clippy_utils::{ use clippy_utils::{
diagnostics::span_lint, last_path_segment, match_function_call, match_path, paths, ty::match_type, diagnostics::span_lint, last_path_segment, match_def_path, match_function_call, match_path, paths, ty::match_type,
ty::walk_ptrs_ty_depth, ty::walk_ptrs_ty_depth,
}; };
@ -41,6 +38,8 @@ const BLACK_LISTED_LINTS: [&str; 3] = ["lint_author", "deep_code_inspection", "i
const IGNORED_LINT_GROUPS: [&str; 1] = ["clippy::all"]; const IGNORED_LINT_GROUPS: [&str; 1] = ["clippy::all"];
/// Lints within this group will be excluded from the collection /// Lints within this group will be excluded from the collection
const EXCLUDED_LINT_GROUPS: [&str; 1] = ["clippy::internal"]; const EXCLUDED_LINT_GROUPS: [&str; 1] = ["clippy::internal"];
/// Collected deprecated lint will be assigned to this group in the JSON output
const DEPRECATED_LINT_GROUP_STR: &str = "DEPRECATED";
const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [ const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [
&["clippy_utils", "diagnostics", "span_lint"], &["clippy_utils", "diagnostics", "span_lint"],
@ -66,6 +65,7 @@ const SUGGESTION_FUNCTIONS: [&[&str]; 2] = [
&["clippy_utils", "diagnostics", "multispan_sugg"], &["clippy_utils", "diagnostics", "multispan_sugg"],
&["clippy_utils", "diagnostics", "multispan_sugg_with_applicability"], &["clippy_utils", "diagnostics", "multispan_sugg_with_applicability"],
]; ];
const DEPRECATED_LINT_TYPE: [&str; 3] = ["clippy_lints", "deprecated_lints", "ClippyDeprecatedLint"];
/// The index of the applicability name of `paths::APPLICABILITY_VALUES` /// The index of the applicability name of `paths::APPLICABILITY_VALUES`
const APPLICABILITY_NAME_INDEX: usize = 2; const APPLICABILITY_NAME_INDEX: usize = 2;
@ -225,23 +225,42 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
/// } /// }
/// ``` /// ```
fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) { fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) {
if_chain! { if let ItemKind::Static(ref ty, Mutability::Not, _) = item.kind {
// item validation // Normal lint
if let ItemKind::Static(ref ty, Mutability::Not, _) = item.kind; if_chain! {
if is_lint_ref_type(cx, ty); // item validation
// blacklist check if is_lint_ref_type(cx, ty);
let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase(); // blacklist check
if !BLACK_LISTED_LINTS.contains(&lint_name.as_str()); let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase();
// metadata extraction if !BLACK_LISTED_LINTS.contains(&lint_name.as_str());
if let Some(group) = get_lint_group_or_lint(cx, &lint_name, item); // metadata extraction
if let Some(docs) = extract_attr_docs_or_lint(cx, item); if let Some(group) = get_lint_group_or_lint(cx, &lint_name, item);
then { if let Some(docs) = extract_attr_docs_or_lint(cx, item);
self.lints.push(LintMetadata::new( then {
lint_name, self.lints.push(LintMetadata::new(
SerializableSpan::from_item(cx, item), lint_name,
group, SerializableSpan::from_item(cx, item),
docs, group,
)); docs,
));
}
}
if_chain! {
if is_deprecated_lint(cx, ty);
// blacklist check
let lint_name = sym_to_string(item.ident.name).to_ascii_lowercase();
if !BLACK_LISTED_LINTS.contains(&lint_name.as_str());
// Metadata the little we can get from a deprecated lint
if let Some(docs) = extract_attr_docs_or_lint(cx, item);
then {
self.lints.push(LintMetadata::new(
lint_name,
SerializableSpan::from_item(cx, item),
DEPRECATED_LINT_GROUP_STR.to_string(),
docs,
));
}
} }
} }
} }
@ -268,7 +287,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
// - src/misc.rs:734:9 // - src/misc.rs:734:9
// - src/methods/mod.rs:3545:13 // - src/methods/mod.rs:3545:13
// - src/methods/mod.rs:3496:13 // - src/methods/mod.rs:3496:13
// We are basically unable to resolve the lint name it self. // We are basically unable to resolve the lint name itself.
return; return;
} }
@ -347,6 +366,16 @@ fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option<String> {
None None
} }
fn is_deprecated_lint(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
if let hir::TyKind::Path(ref path) = ty.kind {
if let hir::def::Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, ty.hir_id) {
return match_def_path(cx, def_id, &DEPRECATED_LINT_TYPE);
}
}
false
}
// ================================================================== // ==================================================================
// Lint emission // Lint emission
// ================================================================== // ==================================================================