diff --git a/crates/oxc_linter/src/context.rs b/crates/oxc_linter/src/context.rs index 4008e1fa3..8a653b53a 100644 --- a/crates/oxc_linter/src/context.rs +++ b/crates/oxc_linter/src/context.rs @@ -12,19 +12,20 @@ use crate::{ ESLintConfig, ESLintEnv, ESLintGlobals, ESLintSettings, }; +#[derive(Clone)] pub struct LintContext<'a> { semantic: Rc>, diagnostics: RefCell>>, - disable_directives: DisableDirectives<'a>, + disable_directives: Rc>, /// Whether or not to apply code fixes during linting. fix: bool, current_rule_name: &'static str, - file_path: Box, + file_path: Rc, eslint_config: Arc, } @@ -36,10 +37,10 @@ impl<'a> LintContext<'a> { Self { semantic: Rc::clone(semantic), diagnostics: RefCell::new(vec![]), - disable_directives, + disable_directives: Rc::new(disable_directives), fix: false, current_rule_name: "", - file_path, + file_path: file_path.into(), eslint_config: Arc::new(ESLintConfig::default()), } } @@ -99,15 +100,16 @@ impl<'a> LintContext<'a> { false } - #[inline] - pub fn with_rule_name(&mut self, name: &'static str) { + #[must_use] + pub fn with_rule_name(mut self, name: &'static str) -> Self { self.current_rule_name = name; + self } /* Diagnostics */ pub fn into_message(self) -> Vec> { - self.diagnostics.into_inner() + self.diagnostics.borrow().iter().cloned().collect::>() } fn add_diagnostic(&self, message: Message<'a>) { diff --git a/crates/oxc_linter/src/fixer.rs b/crates/oxc_linter/src/fixer.rs index a96f2ce4f..2151f8f8e 100644 --- a/crates/oxc_linter/src/fixer.rs +++ b/crates/oxc_linter/src/fixer.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use oxc_diagnostics::OxcDiagnostic; use oxc_span::Span; -#[derive(Debug, Default)] +#[derive(Debug, Clone, Default)] pub struct Fix<'a> { pub content: Cow<'a, str>, pub span: Span, @@ -25,6 +25,7 @@ pub struct FixResult<'a> { pub messages: Vec>, } +#[derive(Clone)] pub struct Message<'a> { pub error: OxcDiagnostic, pub start: u32, diff --git a/crates/oxc_linter/src/lib.rs b/crates/oxc_linter/src/lib.rs index ff5394cb6..3d65f9ef5 100644 --- a/crates/oxc_linter/src/lib.rs +++ b/crates/oxc_linter/src/lib.rs @@ -52,7 +52,7 @@ fn size_asserts() { #[derive(Debug)] pub struct Linter { - rules: Vec<(/* rule name */ &'static str, RuleEnum)>, + rules: Vec, options: LintOptions, eslint_config: Arc, } @@ -69,13 +69,12 @@ impl Linter { /// Returns `Err` if there are any errors parsing the configuration file. pub fn from_options(options: LintOptions) -> Result { let (rules, eslint_config) = options.derive_rules_and_config()?; - let rules = rules.into_iter().map(|rule| (rule.name(), rule)).collect(); Ok(Self { rules, options, eslint_config: Arc::new(eslint_config) }) } #[must_use] pub fn with_rules(mut self, rules: Vec) -> Self { - self.rules = rules.into_iter().map(|rule| (rule.name(), rule)).collect(); + self.rules = rules; self } @@ -101,34 +100,40 @@ impl Linter { pub fn run<'a>(&self, ctx: LintContext<'a>) -> Vec> { let semantic = Rc::clone(ctx.semantic()); - let mut ctx = ctx.with_fix(self.options.fix).with_eslint_config(&self.eslint_config); - for (rule_name, rule) in &self.rules { - ctx.with_rule_name(rule_name); - rule.run_once(&ctx); + let ctx = ctx.with_fix(self.options.fix).with_eslint_config(&self.eslint_config); + let rules = self + .rules + .iter() + .map(|rule| (rule, ctx.clone().with_rule_name(rule.name()))) + .collect::>(); + + for (rule, ctx) in &rules { + rule.run_once(ctx); } for symbol in semantic.symbols().iter() { - for (rule_name, rule) in &self.rules { - ctx.with_rule_name(rule_name); - rule.run_on_symbol(symbol, &ctx); + for (rule, ctx) in &rules { + rule.run_on_symbol(symbol, ctx); } } for node in semantic.nodes().iter() { - for (rule_name, rule) in &self.rules { - ctx.with_rule_name(rule_name); - rule.run(node, &ctx); + for (rule, ctx) in &rules { + rule.run(node, ctx); } } - ctx.into_message() + rules.into_iter().flat_map(|(_, ctx)| ctx.into_message()).collect::>() } /// # Panics pub fn print_rules(writer: &mut W) { - let default_rules = - Linter::default().rules.into_iter().map(|(name, _)| name).collect::>(); + let default_rules = Linter::default() + .rules + .into_iter() + .map(|rule| rule.name()) + .collect::>(); let rules_by_category = RULES.iter().fold( FxHashMap::default(),