diff options
| author | xFrednet <xFrednet@gmail.com> | 2021-05-11 20:23:52 +0200 |
|---|---|---|
| committer | xFrednet <xFrednet@gmail.com> | 2021-05-12 17:31:00 +0200 |
| commit | 210ec728e5d7f428b22b78ee721ed6507cc6f925 (patch) | |
| tree | 4e47ff7f5ecd6182f8d6b1c56f502c84a5a089b2 | |
| parent | aa15a5442a975180a367373e563b7f8c626b5344 (diff) | |
| download | rust-210ec728e5d7f428b22b78ee721ed6507cc6f925.tar.gz rust-210ec728e5d7f428b22b78ee721ed6507cc6f925.zip | |
Metadata collection monster searching for configurations
| -rw-r--r-- | clippy_lints/src/lib.rs | 2 | ||||
| -rw-r--r-- | clippy_lints/src/utils/conf.rs | 24 | ||||
| -rw-r--r-- | clippy_lints/src/utils/internal_lints/metadata_collector.rs | 88 |
3 files changed, 109 insertions, 5 deletions
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0c86441cf3f..f0fae6ee1c7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1009,7 +1009,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: #[cfg(feature = "metadata-collector-lint")] { if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) { - store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::default()); + store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::new()); } } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 52c1dc3bdd2..98b86f73a1f 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -26,13 +26,13 @@ impl TryConf { macro_rules! define_Conf { ($( - #[$doc:meta] + #[doc = $doc:literal] $(#[conf_deprecated($dep:literal)])? ($name:ident: $ty:ty = $default:expr), )*) => { /// Clippy lint configuration pub struct Conf { - $(#[$doc] pub $name: $ty,)* + $(#[doc = $doc] pub $name: $ty,)* } mod defaults { @@ -89,6 +89,24 @@ macro_rules! define_Conf { Ok(TryConf { conf, errors }) } } + + #[cfg(feature = "metadata-collector-lint")] + pub mod metadata { + use crate::utils::internal_lints::metadata_collector::ClippyConfigurationBasicInfo; + + pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfigurationBasicInfo> { + vec![ + $( + ClippyConfigurationBasicInfo { + name: stringify!($name), + config_type: stringify!($ty), + default: stringify!($default), + doc_comment: $doc, + }, + )+ + ] + } + } }; } @@ -100,7 +118,7 @@ define_Conf! { (blacklisted_names: Vec<String> = ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()), /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have (cognitive_complexity_threshold: u64 = 25), - /// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead. + /// Lint: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead. #[conf_deprecated("Please use `cognitive-complexity-threshold` instead")] (cyclomatic_complexity_threshold: Option<u64> = None), /// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks diff --git a/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/clippy_lints/src/utils/internal_lints/metadata_collector.rs index fc4912ba52f..308f61beec3 100644 --- a/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -102,13 +102,24 @@ declare_clippy_lint! { impl_lint_pass!(MetadataCollector => [INTERNAL_METADATA_COLLECTOR]); #[allow(clippy::module_name_repetitions)] -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub struct MetadataCollector { /// All collected lints /// /// We use a Heap here to have the lints added in alphabetic order in the export lints: BinaryHeap<LintMetadata>, applicability_info: FxHashMap<String, ApplicabilityInfo>, + config: Vec<ClippyConfiguration>, +} + +impl MetadataCollector { + pub fn new() -> Self { + Self { + lints: BinaryHeap::<LintMetadata>::default(), + applicability_info: FxHashMap::<String, ApplicabilityInfo>::default(), + config: collect_configs(), + } + } } impl Drop for MetadataCollector { @@ -214,6 +225,81 @@ impl Serialize for ApplicabilityInfo { } } +#[derive(Debug)] +pub(crate) struct ClippyConfigurationBasicInfo { + pub name: &'static str, + pub config_type: &'static str, + pub default: &'static str, + pub doc_comment: &'static str, +} + +#[derive(Debug, Clone, Default)] +struct ClippyConfiguration { + name: String, + lints: Vec<String>, + doc: String, + config_type: &'static str, + default: String, +} + +// ================================================================== +// Configuration +// ================================================================== +fn collect_configs() -> Vec<ClippyConfiguration> { + let cons = crate::utils::conf::metadata::get_configuration_metadata(); + cons.iter() + .map(move |x| { + let (lints, doc) = parse_config_field_doc(x.doc_comment) + .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string())); + + ClippyConfiguration { + name: to_kebab(x.name), + lints, + doc, + config_type: x.config_type, + default: x.default.to_string(), + } + }) + .collect() +} + +/// This parses the field documentation of the config struct. +/// +/// ```rust, ignore +/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin") +/// ``` +/// +/// Would yield: +/// ```rust, ignore +/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin") +/// ``` +fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> { + const DOC_START: &str = " Lint: "; + if_chain! { + if doc_comment.starts_with(DOC_START); + if let Some(split_pos) = doc_comment.find('.'); + then { + let mut doc_comment = doc_comment.to_string(); + let documentation = doc_comment.split_off(split_pos); + + doc_comment.make_ascii_lowercase(); + let lints: Vec<String> = doc_comment.split_off(DOC_START.len()).split(", ").map(str::to_string).collect(); + + Some((lints, documentation)) + } else { + None + } + } +} + +/// Transforms a given `snake_case_string` to a tasty `kebab-case-string` +fn to_kebab(config_name: &str) -> String { + config_name.replace('_', "-") +} + +// ================================================================== +// Lint pass +// ================================================================== impl<'hir> LateLintPass<'hir> for MetadataCollector { /// Collecting lint declarations like: /// ```rust, ignore |
