From 8b9ebcd6e5881f36dd3266c6859b548051fd7276 Mon Sep 17 00:00:00 2001 From: Boshen Date: Sun, 26 Feb 2023 16:30:43 +0800 Subject: [PATCH] feat(linter): read rule configuration from json --- crates/oxc_linter/src/lib.rs | 25 +++++++++++++++++++++++-- crates/oxc_linter/src/rules.rs | 6 +++--- crates/oxc_linter/src/rules/no_empty.rs | 2 +- crates/oxc_linter/src/tester.rs | 2 +- 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/crates/oxc_linter/src/lib.rs b/crates/oxc_linter/src/lib.rs index 5a9da9cbc..852d2e586 100644 --- a/crates/oxc_linter/src/lib.rs +++ b/crates/oxc_linter/src/lib.rs @@ -7,7 +7,7 @@ mod context; mod rule; mod rules; -use std::rc::Rc; +use std::{fs, rc::Rc}; use oxc_diagnostics::Error; pub(crate) use oxc_semantic::AstNode; @@ -27,7 +27,20 @@ impl Linter { #[must_use] #[allow(clippy::new_without_default)] pub fn new() -> Self { - Self { rules: RULES.to_vec() } + let rules_config = Self::read_rules_configuration(); + let rules = rules_config.map_or_else( + || RULES.to_vec(), + |rules_config| { + RULES + .iter() + .map(|rule| { + let value = rules_config.get(rule.name()); + rule.read_json(value.cloned()) + }) + .collect() + }, + ); + Self { rules } } #[must_use] @@ -47,4 +60,12 @@ impl Linter { ctx.into_diagnostics() } + + fn read_rules_configuration() -> Option> { + fs::read_to_string(".eslintrc.json") + .ok() + .and_then(|s| serde_json::from_str(&s).ok()) + .and_then(|v: serde_json::Value| v.get("rules").cloned()) + .and_then(|v| v.as_object().cloned()) + } } diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 94bfc0a6e..9f8707127 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -27,13 +27,13 @@ impl RuleEnum { } } - pub fn from_json(&self, maybe_value: Option) -> Self { + pub fn read_json(&self, maybe_value: Option) -> Self { match self { Self::NoDebugger(_) => { - RuleEnum::NoDebugger(maybe_value.map(NoDebugger::from_json).unwrap_or_default()) + Self::NoDebugger(maybe_value.map(NoDebugger::from_json).unwrap_or_default()) } Self::NoEmpty(_) => { - RuleEnum::NoEmpty(maybe_value.map(NoEmpty::from_json).unwrap_or_default()) + Self::NoEmpty(maybe_value.map(NoEmpty::from_json).unwrap_or_default()) } } } diff --git a/crates/oxc_linter/src/rules/no_empty.rs b/crates/oxc_linter/src/rules/no_empty.rs index 4c87a42f0..ffcea0c7d 100644 --- a/crates/oxc_linter/src/rules/no_empty.rs +++ b/crates/oxc_linter/src/rules/no_empty.rs @@ -26,7 +26,7 @@ impl Rule for NoEmpty { Self { allow_empty_catch: obj .and_then(|v| v.get("allowEmptyCatch")) - .and_then(|v| v.as_bool()) + .and_then(serde_json::Value::as_bool) .unwrap_or_default(), } } diff --git a/crates/oxc_linter/src/tester.rs b/crates/oxc_linter/src/tester.rs index e64a0c5b4..af3cf1314 100644 --- a/crates/oxc_linter/src/tester.rs +++ b/crates/oxc_linter/src/tester.rs @@ -65,7 +65,7 @@ impl Tester { let semantic = SemanticBuilder::new().build(program, ret.trivias); let semantic = std::rc::Rc::new(semantic); let rule = RULES.iter().find(|rule| rule.name() == self.rule_name).unwrap(); - let rule = rule.from_json(config); + let rule = rule.read_json(config); let diagnostics = Linter::from_rules(vec![rule]).run(&semantic); if diagnostics.is_empty() { return true;