Skip to content

Commit 210ec72

Browse files
committed
Metadata collection monster searching for configurations
1 parent aa15a54 commit 210ec72

File tree

3 files changed

+109
-5
lines changed

3 files changed

+109
-5
lines changed

clippy_lints/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10091009
#[cfg(feature = "metadata-collector-lint")]
10101010
{
10111011
if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
1012-
store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::default());
1012+
store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::new());
10131013
}
10141014
}
10151015

clippy_lints/src/utils/conf.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ impl TryConf {
2626

2727
macro_rules! define_Conf {
2828
($(
29-
#[$doc:meta]
29+
#[doc = $doc:literal]
3030
$(#[conf_deprecated($dep:literal)])?
3131
($name:ident: $ty:ty = $default:expr),
3232
)*) => {
3333
/// Clippy lint configuration
3434
pub struct Conf {
35-
$(#[$doc] pub $name: $ty,)*
35+
$(#[doc = $doc] pub $name: $ty,)*
3636
}
3737

3838
mod defaults {
@@ -89,6 +89,24 @@ macro_rules! define_Conf {
8989
Ok(TryConf { conf, errors })
9090
}
9191
}
92+
93+
#[cfg(feature = "metadata-collector-lint")]
94+
pub mod metadata {
95+
use crate::utils::internal_lints::metadata_collector::ClippyConfigurationBasicInfo;
96+
97+
pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfigurationBasicInfo> {
98+
vec![
99+
$(
100+
ClippyConfigurationBasicInfo {
101+
name: stringify!($name),
102+
config_type: stringify!($ty),
103+
default: stringify!($default),
104+
doc_comment: $doc,
105+
},
106+
)+
107+
]
108+
}
109+
}
92110
};
93111
}
94112

@@ -100,7 +118,7 @@ define_Conf! {
100118
(blacklisted_names: Vec<String> = ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
101119
/// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
102120
(cognitive_complexity_threshold: u64 = 25),
103-
/// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead.
121+
/// Lint: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead.
104122
#[conf_deprecated("Please use `cognitive-complexity-threshold` instead")]
105123
(cyclomatic_complexity_threshold: Option<u64> = None),
106124
/// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks

clippy_lints/src/utils/internal_lints/metadata_collector.rs

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,24 @@ declare_clippy_lint! {
102102
impl_lint_pass!(MetadataCollector => [INTERNAL_METADATA_COLLECTOR]);
103103

104104
#[allow(clippy::module_name_repetitions)]
105-
#[derive(Debug, Clone, Default)]
105+
#[derive(Debug, Clone)]
106106
pub struct MetadataCollector {
107107
/// All collected lints
108108
///
109109
/// We use a Heap here to have the lints added in alphabetic order in the export
110110
lints: BinaryHeap<LintMetadata>,
111111
applicability_info: FxHashMap<String, ApplicabilityInfo>,
112+
config: Vec<ClippyConfiguration>,
113+
}
114+
115+
impl MetadataCollector {
116+
pub fn new() -> Self {
117+
Self {
118+
lints: BinaryHeap::<LintMetadata>::default(),
119+
applicability_info: FxHashMap::<String, ApplicabilityInfo>::default(),
120+
config: collect_configs(),
121+
}
122+
}
112123
}
113124

114125
impl Drop for MetadataCollector {
@@ -214,6 +225,81 @@ impl Serialize for ApplicabilityInfo {
214225
}
215226
}
216227

228+
#[derive(Debug)]
229+
pub(crate) struct ClippyConfigurationBasicInfo {
230+
pub name: &'static str,
231+
pub config_type: &'static str,
232+
pub default: &'static str,
233+
pub doc_comment: &'static str,
234+
}
235+
236+
#[derive(Debug, Clone, Default)]
237+
struct ClippyConfiguration {
238+
name: String,
239+
lints: Vec<String>,
240+
doc: String,
241+
config_type: &'static str,
242+
default: String,
243+
}
244+
245+
// ==================================================================
246+
// Configuration
247+
// ==================================================================
248+
fn collect_configs() -> Vec<ClippyConfiguration> {
249+
let cons = crate::utils::conf::metadata::get_configuration_metadata();
250+
cons.iter()
251+
.map(move |x| {
252+
let (lints, doc) = parse_config_field_doc(x.doc_comment)
253+
.unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
254+
255+
ClippyConfiguration {
256+
name: to_kebab(x.name),
257+
lints,
258+
doc,
259+
config_type: x.config_type,
260+
default: x.default.to_string(),
261+
}
262+
})
263+
.collect()
264+
}
265+
266+
/// This parses the field documentation of the config struct.
267+
///
268+
/// ```rust, ignore
269+
/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
270+
/// ```
271+
///
272+
/// Would yield:
273+
/// ```rust, ignore
274+
/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
275+
/// ```
276+
fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
277+
const DOC_START: &str = " Lint: ";
278+
if_chain! {
279+
if doc_comment.starts_with(DOC_START);
280+
if let Some(split_pos) = doc_comment.find('.');
281+
then {
282+
let mut doc_comment = doc_comment.to_string();
283+
let documentation = doc_comment.split_off(split_pos);
284+
285+
doc_comment.make_ascii_lowercase();
286+
let lints: Vec<String> = doc_comment.split_off(DOC_START.len()).split(", ").map(str::to_string).collect();
287+
288+
Some((lints, documentation))
289+
} else {
290+
None
291+
}
292+
}
293+
}
294+
295+
/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
296+
fn to_kebab(config_name: &str) -> String {
297+
config_name.replace('_', "-")
298+
}
299+
300+
// ==================================================================
301+
// Lint pass
302+
// ==================================================================
217303
impl<'hir> LateLintPass<'hir> for MetadataCollector {
218304
/// Collecting lint declarations like:
219305
/// ```rust, ignore

0 commit comments

Comments
 (0)