refactor(linter): move LintPlugins from LintOptions to LintConfig (#6932)

Pure refactor. Moves plugin settings from linter options (which control the linter's behavior on a global level) and linter config ("which may or may not get adjusted on each file).
This commit is contained in:
DonIsaac 2024-10-29 01:28:21 +00:00
parent 1691cab507
commit 8f1460eba3
10 changed files with 58 additions and 34 deletions

View file

@ -7,8 +7,7 @@ use oxc_span::CompactStr;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use crate::{ use crate::{
config::{ESLintRule, OxlintRules}, config::{ESLintRule, LintPlugins, OxlintRules},
options::LintPlugins,
rules::RULES, rules::RULES,
AllowWarnDeny, FixKind, FrameworkFlags, LintConfig, LintFilter, LintFilterKind, LintOptions, AllowWarnDeny, FixKind, FrameworkFlags, LintConfig, LintFilter, LintFilterKind, LintOptions,
Linter, Oxlintrc, RuleCategory, RuleEnum, RuleWithSeverity, Linter, Oxlintrc, RuleCategory, RuleEnum, RuleWithSeverity,
@ -35,8 +34,11 @@ impl LinterBuilder {
/// You can think of this as `oxlint -A all`. /// You can think of this as `oxlint -A all`.
pub fn empty() -> Self { pub fn empty() -> Self {
let options = LintOptions::default(); let options = LintOptions::default();
let cache = RulesCache::new(options.plugins); let config = LintConfig::default();
Self { rules: FxHashSet::default(), options, config: LintConfig::default(), cache } let rules = FxHashSet::default();
let cache = RulesCache::new(config.plugins);
Self { rules, options, config, cache }
} }
/// Warn on all rules in all plugins and categories, including those in `nursery`. /// Warn on all rules in all plugins and categories, including those in `nursery`.
@ -44,15 +46,16 @@ impl LinterBuilder {
/// ///
/// You can think of this as `oxlint -W all -W nursery`. /// You can think of this as `oxlint -W all -W nursery`.
pub fn all() -> Self { pub fn all() -> Self {
let options = LintOptions { plugins: LintPlugins::all(), ..LintOptions::default() }; let options = LintOptions::default();
let cache = RulesCache::new(options.plugins); let config = LintConfig { plugins: LintPlugins::all(), ..LintConfig::default() };
let cache = RulesCache::new(config.plugins);
Self { Self {
rules: RULES rules: RULES
.iter() .iter()
.map(|rule| RuleWithSeverity { rule: rule.clone(), severity: AllowWarnDeny::Warn }) .map(|rule| RuleWithSeverity { rule: rule.clone(), severity: AllowWarnDeny::Warn })
.collect(), .collect(),
options, options,
config: LintConfig::default(), config,
cache, cache,
} }
} }
@ -76,11 +79,11 @@ impl LinterBuilder {
let Oxlintrc { plugins, settings, env, globals, categories, rules: oxlintrc_rules } = let Oxlintrc { plugins, settings, env, globals, categories, rules: oxlintrc_rules } =
oxlintrc; oxlintrc;
let config = LintConfig { settings, env, globals }; let config = LintConfig { plugins, settings, env, globals };
let options = LintOptions { plugins, ..Default::default() }; let options = LintOptions::default();
let rules = let rules =
if start_empty { FxHashSet::default() } else { Self::warn_correctness(plugins) }; if start_empty { FxHashSet::default() } else { Self::warn_correctness(plugins) };
let cache = RulesCache::new(options.plugins); let cache = RulesCache::new(config.plugins);
let mut builder = Self { rules, options, config, cache }; let mut builder = Self { rules, options, config, cache };
if !categories.is_empty() { if !categories.is_empty() {
@ -128,7 +131,7 @@ impl LinterBuilder {
/// [`and_plugins`]: LinterBuilder::and_plugins /// [`and_plugins`]: LinterBuilder::and_plugins
#[inline] #[inline]
pub fn with_plugins(mut self, plugins: LintPlugins) -> Self { pub fn with_plugins(mut self, plugins: LintPlugins) -> Self {
self.options.plugins = plugins; self.config.plugins = plugins;
self.cache.set_plugins(plugins); self.cache.set_plugins(plugins);
self self
} }
@ -139,14 +142,14 @@ impl LinterBuilder {
/// rules. /// rules.
#[inline] #[inline]
pub fn and_plugins(mut self, plugins: LintPlugins, enabled: bool) -> Self { pub fn and_plugins(mut self, plugins: LintPlugins, enabled: bool) -> Self {
self.options.plugins.set(plugins, enabled); self.config.plugins.set(plugins, enabled);
self.cache.set_plugins(self.options.plugins); self.cache.set_plugins(self.config.plugins);
self self
} }
#[inline] #[inline]
pub fn plugins(&self) -> LintPlugins { pub fn plugins(&self) -> LintPlugins {
self.options.plugins self.config.plugins
} }
#[cfg(test)] #[cfg(test)]

View file

@ -2,6 +2,7 @@ mod categories;
mod env; mod env;
mod globals; mod globals;
mod oxlintrc; mod oxlintrc;
mod plugins;
mod rules; mod rules;
mod settings; mod settings;
@ -9,6 +10,7 @@ pub use self::{
env::OxlintEnv, env::OxlintEnv,
globals::OxlintGlobals, globals::OxlintGlobals,
oxlintrc::Oxlintrc, oxlintrc::Oxlintrc,
plugins::LintPlugins,
rules::ESLintRule, rules::ESLintRule,
rules::OxlintRules, rules::OxlintRules,
settings::{jsdoc::JSDocPluginSettings, OxlintSettings}, settings::{jsdoc::JSDocPluginSettings, OxlintSettings},
@ -16,6 +18,7 @@ pub use self::{
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub(crate) struct LintConfig { pub(crate) struct LintConfig {
pub(crate) plugins: LintPlugins,
pub(crate) settings: OxlintSettings, pub(crate) settings: OxlintSettings,
/// Environments enable and disable collections of global variables. /// Environments enable and disable collections of global variables.
pub(crate) env: OxlintEnv, pub(crate) env: OxlintEnv,
@ -25,7 +28,12 @@ pub(crate) struct LintConfig {
impl From<Oxlintrc> for LintConfig { impl From<Oxlintrc> for LintConfig {
fn from(config: Oxlintrc) -> Self { fn from(config: Oxlintrc) -> Self {
Self { settings: config.settings, env: config.env, globals: config.globals } Self {
plugins: config.plugins,
settings: config.settings,
env: config.env,
globals: config.globals,
}
} }
} }

View file

@ -5,11 +5,11 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{ use super::{
categories::OxlintCategories, env::OxlintEnv, globals::OxlintGlobals, rules::OxlintRules, categories::OxlintCategories, env::OxlintEnv, globals::OxlintGlobals, plugins::LintPlugins,
settings::OxlintSettings, rules::OxlintRules, settings::OxlintSettings,
}; };
use crate::{options::LintPlugins, utils::read_to_string}; use crate::utils::read_to_string;
/// Oxlint Configuration File /// Oxlint Configuration File
/// ///

View file

@ -3,11 +3,11 @@ use oxc_span::SourceType;
use std::{cell::RefCell, path::Path, rc::Rc, sync::Arc}; use std::{cell::RefCell, path::Path, rc::Rc, sync::Arc};
use crate::{ use crate::{
config::LintConfig, config::{LintConfig, LintPlugins},
disable_directives::{DisableDirectives, DisableDirectivesBuilder}, disable_directives::{DisableDirectives, DisableDirectivesBuilder},
fixer::{FixKind, Message}, fixer::{FixKind, Message},
frameworks, frameworks,
options::{LintOptions, LintPlugins}, options::LintOptions,
utils, FrameworkFlags, RuleWithSeverity, utils, FrameworkFlags, RuleWithSeverity,
}; };
@ -68,6 +68,7 @@ impl<'a> ContextHost<'a> {
file_path: P, file_path: P,
semantic: Rc<Semantic<'a>>, semantic: Rc<Semantic<'a>>,
options: LintOptions, options: LintOptions,
config: Arc<LintConfig>,
) -> Self { ) -> Self {
const DIAGNOSTICS_INITIAL_CAPACITY: usize = 512; const DIAGNOSTICS_INITIAL_CAPACITY: usize = 512;
@ -82,6 +83,7 @@ impl<'a> ContextHost<'a> {
DisableDirectivesBuilder::new().build(semantic.source_text(), semantic.comments()); DisableDirectivesBuilder::new().build(semantic.source_text(), semantic.comments());
let file_path = file_path.as_ref().to_path_buf().into_boxed_path(); let file_path = file_path.as_ref().to_path_buf().into_boxed_path();
let plugins = config.plugins;
Self { Self {
semantic, semantic,
@ -89,17 +91,25 @@ impl<'a> ContextHost<'a> {
diagnostics: RefCell::new(Vec::with_capacity(DIAGNOSTICS_INITIAL_CAPACITY)), diagnostics: RefCell::new(Vec::with_capacity(DIAGNOSTICS_INITIAL_CAPACITY)),
fix: options.fix, fix: options.fix,
file_path, file_path,
config: Arc::new(LintConfig::default()), config,
frameworks: options.framework_hints, frameworks: options.framework_hints,
plugins: options.plugins, plugins,
} }
.sniff_for_frameworks() .sniff_for_frameworks()
} }
/// Set the linter configuration for this context. /// Set the linter configuration for this context.
#[inline] #[inline]
#[allow(dead_code)] // will be used in up-stack PR
pub fn with_config(mut self, config: &Arc<LintConfig>) -> Self { pub fn with_config(mut self, config: &Arc<LintConfig>) -> Self {
let plugins = config.plugins;
self.config = Arc::clone(config); self.config = Arc::clone(config);
if self.plugins != plugins {
self.plugins = plugins;
return self.sniff_for_frameworks();
}
self self
} }

View file

@ -31,11 +31,11 @@ use utils::iter_possible_jest_call_node;
pub use crate::{ pub use crate::{
builder::LinterBuilder, builder::LinterBuilder,
config::Oxlintrc, config::{LintPlugins, Oxlintrc},
context::LintContext, context::LintContext,
fixer::FixKind, fixer::FixKind,
frameworks::FrameworkFlags, frameworks::FrameworkFlags,
options::{AllowWarnDeny, InvalidFilterKind, LintFilter, LintFilterKind, LintPlugins}, options::{AllowWarnDeny, InvalidFilterKind, LintFilter, LintFilterKind},
rule::{RuleCategory, RuleFixMeta, RuleMeta, RuleWithSeverity}, rule::{RuleCategory, RuleFixMeta, RuleMeta, RuleWithSeverity},
service::{LintService, LintServiceOptions}, service::{LintService, LintServiceOptions},
}; };
@ -115,7 +115,7 @@ impl Linter {
pub fn run<'a>(&self, path: &Path, semantic: Rc<Semantic<'a>>) -> Vec<Message<'a>> { pub fn run<'a>(&self, path: &Path, semantic: Rc<Semantic<'a>>) -> Vec<Message<'a>> {
let ctx_host = let ctx_host =
Rc::new(ContextHost::new(path, semantic, self.options).with_config(&self.config)); Rc::new(ContextHost::new(path, semantic, self.options, Arc::clone(&self.config)));
let rules = self let rules = self
.rules .rules
@ -126,7 +126,7 @@ impl Linter {
let semantic = ctx_host.semantic(); let semantic = ctx_host.semantic();
let should_run_on_jest_node = let should_run_on_jest_node =
self.options.plugins.has_test() && ctx_host.frameworks().is_test(); self.config.plugins.has_test() && ctx_host.frameworks().is_test();
// IMPORTANT: We have two branches here for performance reasons: // IMPORTANT: We have two branches here for performance reasons:
// //

View file

@ -1,6 +1,7 @@
use crate::RuleCategory; use crate::RuleCategory;
use super::{plugins::LintPlugins, AllowWarnDeny}; use super::AllowWarnDeny;
use crate::LintPlugins;
use std::{borrow::Cow, fmt}; use std::{borrow::Cow, fmt};
/// Enables, disables, and sets the severity of lint rules. /// Enables, disables, and sets the severity of lint rules.

View file

@ -1,10 +1,8 @@
mod allow_warn_deny; mod allow_warn_deny;
mod filter; mod filter;
mod plugins;
pub use allow_warn_deny::AllowWarnDeny; pub use allow_warn_deny::AllowWarnDeny;
pub use filter::{InvalidFilterKind, LintFilter, LintFilterKind}; pub use filter::{InvalidFilterKind, LintFilter, LintFilterKind};
pub use plugins::LintPlugins;
use crate::{fixer::FixKind, FrameworkFlags}; use crate::{fixer::FixKind, FrameworkFlags};
@ -14,5 +12,4 @@ use crate::{fixer::FixKind, FrameworkFlags};
pub(crate) struct LintOptions { pub(crate) struct LintOptions {
pub fix: FixKind, pub fix: FixKind,
pub framework_hints: FrameworkFlags, pub framework_hints: FrameworkFlags,
pub plugins: LintPlugins,
} }

View file

@ -10,7 +10,7 @@ use serde::Deserialize;
use serde_json::Value; use serde_json::Value;
use crate::{ use crate::{
fixer::FixKind, options::LintPlugins, rules::RULES, AllowWarnDeny, Fixer, LintService, fixer::FixKind, rules::RULES, AllowWarnDeny, Fixer, LintPlugins, LintService,
LintServiceOptions, LinterBuilder, Oxlintrc, RuleEnum, RuleWithSeverity, LintServiceOptions, LinterBuilder, Oxlintrc, RuleEnum, RuleWithSeverity,
}; };

View file

@ -303,7 +303,7 @@ pub fn is_equality_matcher(matcher: &KnownMemberExpressionProperty) -> bool {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::rc::Rc; use std::{rc::Rc, sync::Arc};
use oxc_allocator::Allocator; use oxc_allocator::Allocator;
use oxc_parser::Parser; use oxc_parser::Parser;
@ -322,8 +322,13 @@ mod test {
let semantic_ret = Rc::new(semantic_ret); let semantic_ret = Rc::new(semantic_ret);
let build_ctx = |path: &'static str| { let build_ctx = |path: &'static str| {
Rc::new(ContextHost::new(path, Rc::clone(&semantic_ret), LintOptions::default())) Rc::new(ContextHost::new(
.spawn_for_test() path,
Rc::clone(&semantic_ret),
LintOptions::default(),
Arc::default(),
))
.spawn_for_test()
}; };
let ctx = build_ctx("foo.js"); let ctx = build_ctx("foo.js");