diff --git a/apps/oxlint/src/lint/mod.rs b/apps/oxlint/src/lint/mod.rs index efa90a242d16eb..3668e0a24da7ae 100644 --- a/apps/oxlint/src/lint/mod.rs +++ b/apps/oxlint/src/lint/mod.rs @@ -3,7 +3,7 @@ use std::{env, io::BufWriter, time::Instant}; use ignore::gitignore::Gitignore; use oxc_diagnostics::{DiagnosticService, GraphicalReportHandler}; use oxc_linter::{ - partial_loader::LINT_PARTIAL_LOADER_EXT, LintOptions, LintService, LintServiceOptions, Linter, + partial_loader::LINT_PARTIAL_LOADER_EXT, LintService, LintServiceOptions, Linter, OxlintOptions, }; use oxc_span::VALID_EXTENSIONS; @@ -92,7 +92,7 @@ impl Runner for LintRunner { let number_of_files = paths.len(); let cwd = std::env::current_dir().unwrap().into_boxed_path(); - let lint_options = LintOptions::default() + let lint_options = OxlintOptions::default() .with_filter(filter) .with_config_path(basic_options.config) .with_fix(fix_options.fix_kind()) diff --git a/crates/oxc_language_server/src/main.rs b/crates/oxc_language_server/src/main.rs index 4a830be3a9806b..28bf03829494bc 100644 --- a/crates/oxc_language_server/src/main.rs +++ b/crates/oxc_language_server/src/main.rs @@ -7,7 +7,7 @@ use futures::future::join_all; use globset::Glob; use ignore::gitignore::Gitignore; use log::{debug, error, info}; -use oxc_linter::{FixKind, LintOptions, Linter}; +use oxc_linter::{FixKind, Linter, OxlintOptions}; use serde::{Deserialize, Serialize}; use tokio::sync::{Mutex, OnceCell, RwLock, SetError}; use tower_lsp::{ @@ -345,7 +345,7 @@ impl Backend { let mut linter = self.server_linter.write().await; *linter = ServerLinter::new_with_linter( Linter::from_options( - LintOptions::default() + OxlintOptions::default() .with_fix(FixKind::SafeFix) .with_config_path(Some(config_path)), ) diff --git a/crates/oxc_linter/src/config/mod.rs b/crates/oxc_linter/src/config/mod.rs index 3f594aab5f487a..d717bf8006bc53 100644 --- a/crates/oxc_linter/src/config/mod.rs +++ b/crates/oxc_linter/src/config/mod.rs @@ -65,6 +65,11 @@ pub struct OxlintConfig { pub globals: OxlintGlobals, } +/// Configuration used by the linter, fixer, and rules. +/// +/// This is a mapping from the public [`OxlintConfig`] API to a trimmed down +/// version that is also better suited for internal use. Do not expose this +/// struct outside this crate. #[derive(Debug, Default)] pub(crate) struct LintConfig { pub(crate) settings: OxlintSettings, diff --git a/crates/oxc_linter/src/lib.rs b/crates/oxc_linter/src/lib.rs index c6b8c0556dd248..520fc2c70e3fba 100644 --- a/crates/oxc_linter/src/lib.rs +++ b/crates/oxc_linter/src/lib.rs @@ -23,6 +23,7 @@ pub mod table; use std::{io::Write, path::Path, rc::Rc, sync::Arc}; use config::LintConfig; +use options::LintOptions; use oxc_diagnostics::Error; use oxc_semantic::{AstNode, Semantic}; @@ -31,7 +32,7 @@ pub use crate::{ context::LintContext, fixer::FixKind, frameworks::FrameworkFlags, - options::{AllowWarnDeny, LintOptions}, + options::{AllowWarnDeny, OxlintOptions}, rule::{RuleCategory, RuleFixMeta, RuleMeta, RuleWithSeverity}, service::{LintService, LintServiceOptions}, }; @@ -60,7 +61,7 @@ pub struct Linter { impl Default for Linter { fn default() -> Self { - Self::from_options(LintOptions::default()).unwrap() + Self::from_options(OxlintOptions::default()).unwrap() } } @@ -68,9 +69,9 @@ impl Linter { /// # Errors /// /// Returns `Err` if there are any errors parsing the configuration file. - pub fn from_options(options: LintOptions) -> Result { + pub fn from_options(options: OxlintOptions) -> Result { let (rules, config) = options.derive_rules_and_config()?; - Ok(Self { rules, options, config: Arc::new(config) }) + Ok(Self { rules, options: options.into(), config: Arc::new(config) }) } #[cfg(test)] @@ -104,7 +105,7 @@ impl Linter { self } - pub fn options(&self) -> &LintOptions { + pub(crate) fn options(&self) -> &LintOptions { &self.options } diff --git a/crates/oxc_linter/src/options/mod.rs b/crates/oxc_linter/src/options/mod.rs index 598e00db1f9677..aa2ce91222c41e 100644 --- a/crates/oxc_linter/src/options/mod.rs +++ b/crates/oxc_linter/src/options/mod.rs @@ -18,7 +18,7 @@ pub use allow_warn_deny::AllowWarnDeny; pub use plugins::LintPluginOptions; #[derive(Debug)] -pub struct LintOptions { +pub struct OxlintOptions { /// Allow / Deny rules in order. [("allow" / "deny", rule name)] /// Defaults to [("deny", "correctness")] pub filter: Vec<(AllowWarnDeny, String)>, @@ -33,7 +33,15 @@ pub struct LintOptions { pub framework_hints: FrameworkFlags, } -impl Default for LintOptions { +#[derive(Debug, Default)] +#[cfg_attr(test, derive(PartialEq))] +pub(crate) struct LintOptions { + pub fix: FixKind, + pub framework_hints: FrameworkFlags, + pub plugins: LintPluginOptions, +} + +impl Default for OxlintOptions { fn default() -> Self { Self { filter: vec![(AllowWarnDeny::Warn, String::from("correctness"))], @@ -44,8 +52,22 @@ impl Default for LintOptions { } } } +/// Subset of options used directly by the [`Linter`]. Derived from +/// [`OxlintOptions`], which is the public-facing API. Do not expose this +/// outside of this crate. +/// +/// [`Linter`]: crate::Linter +impl From for LintOptions { + fn from(options: OxlintOptions) -> Self { + Self { + fix: options.fix, + framework_hints: options.framework_hints, + plugins: options.plugins, + } + } +} -impl LintOptions { +impl OxlintOptions { #[must_use] pub fn with_filter(mut self, filter: Vec<(AllowWarnDeny, String)>) -> Self { if !filter.is_empty() { @@ -149,7 +171,7 @@ impl LintOptions { } } -impl LintOptions { +impl OxlintOptions { /// # Errors /// /// * Returns `Err` if there are any errors parsing the configuration file. @@ -251,3 +273,15 @@ impl LintOptions { .collect::>() } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_default_conversion() { + let lint_options = LintOptions::default(); + let oxlint_options = OxlintOptions::default(); + assert_eq!(lint_options, oxlint_options.into()); + } +} diff --git a/crates/oxc_linter/src/options/plugins.rs b/crates/oxc_linter/src/options/plugins.rs index 3c4cab9ab855bd..d0821fcb7b3f93 100644 --- a/crates/oxc_linter/src/options/plugins.rs +++ b/crates/oxc_linter/src/options/plugins.rs @@ -1,4 +1,5 @@ #[derive(Debug)] +#[cfg_attr(test, derive(PartialEq))] #[non_exhaustive] pub struct LintPluginOptions { /// On by default. @@ -115,22 +116,6 @@ impl<'s> FromIterator<&'s str> for LintPluginOptions { #[cfg(test)] mod test { use super::*; - impl PartialEq for LintPluginOptions { - fn eq(&self, other: &Self) -> bool { - self.react == other.react - && self.unicorn == other.unicorn - && self.typescript == other.typescript - && self.oxc == other.oxc - && self.import == other.import - && self.jsdoc == other.jsdoc - && self.jest == other.jest - && self.vitest == other.vitest - && self.jsx_a11y == other.jsx_a11y - && self.nextjs == other.nextjs - && self.react_perf == other.react_perf - && self.promise == other.promise - } - } #[test] fn test_collect_empty() { diff --git a/crates/oxc_linter/src/tester.rs b/crates/oxc_linter/src/tester.rs index ec6ecf8ba80782..5381ace2eacba3 100644 --- a/crates/oxc_linter/src/tester.rs +++ b/crates/oxc_linter/src/tester.rs @@ -9,8 +9,8 @@ use serde::Deserialize; use serde_json::Value; use crate::{ - fixer::FixKind, options::LintPluginOptions, rules::RULES, AllowWarnDeny, Fixer, LintOptions, - LintService, LintServiceOptions, Linter, OxlintConfig, RuleEnum, RuleWithSeverity, + fixer::FixKind, options::LintPluginOptions, rules::RULES, AllowWarnDeny, Fixer, LintService, + LintServiceOptions, Linter, OxlintConfig, OxlintOptions, RuleEnum, RuleWithSeverity, }; #[derive(Eq, PartialEq)] @@ -344,7 +344,7 @@ impl Tester { ) -> TestResult { let allocator = Allocator::default(); let rule = self.find_rule().read_json(rule_config.unwrap_or_default()); - let options = LintOptions::default() + let options = OxlintOptions::default() .with_fix(fix.into()) .with_import_plugin(self.plugins.import) .with_jest_plugin(self.plugins.jest) diff --git a/tasks/benchmark/benches/linter.rs b/tasks/benchmark/benches/linter.rs index 3848dabeb686df..5cccf206ad9e51 100644 --- a/tasks/benchmark/benches/linter.rs +++ b/tasks/benchmark/benches/linter.rs @@ -6,7 +6,7 @@ use std::{ use oxc_allocator::Allocator; use oxc_benchmark::{criterion_group, criterion_main, BenchmarkId, Criterion}; -use oxc_linter::{AllowWarnDeny, FixKind, LintOptions, Linter}; +use oxc_linter::{AllowWarnDeny, FixKind, Linter, OxlintOptions}; use oxc_parser::Parser; use oxc_semantic::SemanticBuilder; use oxc_span::SourceType; @@ -41,7 +41,7 @@ fn bench_linter(criterion: &mut Criterion) { (AllowWarnDeny::Deny, "all".into()), (AllowWarnDeny::Deny, "nursery".into()), ]; - let lint_options = LintOptions::default() + let lint_options = OxlintOptions::default() .with_filter(filter) .with_fix(FixKind::All) .with_import_plugin(true)