refactor(linter): remove with_rule_name from the tight loop (#3335)

This commit is contained in:
Boshen 2024-05-18 01:43:08 +00:00
parent e4b3a3c06a
commit 8383b6e046
3 changed files with 32 additions and 24 deletions

View file

@ -12,19 +12,20 @@ use crate::{
ESLintConfig, ESLintEnv, ESLintGlobals, ESLintSettings,
};
#[derive(Clone)]
pub struct LintContext<'a> {
semantic: Rc<Semantic<'a>>,
diagnostics: RefCell<Vec<Message<'a>>>,
disable_directives: DisableDirectives<'a>,
disable_directives: Rc<DisableDirectives<'a>>,
/// Whether or not to apply code fixes during linting.
fix: bool,
current_rule_name: &'static str,
file_path: Box<Path>,
file_path: Rc<Path>,
eslint_config: Arc<ESLintConfig>,
}
@ -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<Message<'a>> {
self.diagnostics.into_inner()
self.diagnostics.borrow().iter().cloned().collect::<Vec<_>>()
}
fn add_diagnostic(&self, message: Message<'a>) {

View file

@ -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<Message<'a>>,
}
#[derive(Clone)]
pub struct Message<'a> {
pub error: OxcDiagnostic,
pub start: u32,

View file

@ -52,7 +52,7 @@ fn size_asserts() {
#[derive(Debug)]
pub struct Linter {
rules: Vec<(/* rule name */ &'static str, RuleEnum)>,
rules: Vec<RuleEnum>,
options: LintOptions,
eslint_config: Arc<ESLintConfig>,
}
@ -69,13 +69,12 @@ impl Linter {
/// Returns `Err` if there are any errors parsing the configuration file.
pub fn from_options(options: LintOptions) -> Result<Self, Error> {
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<RuleEnum>) -> 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<Message<'a>> {
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::<Vec<_>>();
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::<Vec<_>>()
}
/// # Panics
pub fn print_rules<W: Write>(writer: &mut W) {
let default_rules =
Linter::default().rules.into_iter().map(|(name, _)| name).collect::<FxHashSet<&str>>();
let default_rules = Linter::default()
.rules
.into_iter()
.map(|rule| rule.name())
.collect::<FxHashSet<&str>>();
let rules_by_category = RULES.iter().fold(
FxHashMap::default(),