diff --git a/crates/oxc_linter/src/service/mod.rs b/crates/oxc_linter/src/service/mod.rs index 15e5fb328d1c2..7ebb9fdca505c 100644 --- a/crates/oxc_linter/src/service/mod.rs +++ b/crates/oxc_linter/src/service/mod.rs @@ -6,6 +6,7 @@ use std::{ use oxc_diagnostics::DiagnosticSender; use runtime::Runtime; +pub use runtime::RuntimeFileSystem; use crate::Linter; @@ -74,10 +75,13 @@ impl LintService { Self { runtime } } - #[cfg(test)] - pub(crate) fn from_linter(linter: Linter, options: LintServiceOptions) -> Self { - let runtime = Runtime::new(linter, options); - Self { runtime } + #[must_use] + pub fn with_file_system( + mut self, + file_system: Box, + ) -> Self { + self.runtime = self.runtime.with_file_system(file_system); + self } pub fn linter(&self) -> &Linter { @@ -105,10 +109,9 @@ impl LintService { pub(crate) fn run_test_source<'a>( &mut self, allocator: &'a oxc_allocator::Allocator, - source_text: &str, check_syntax_errors: bool, tx_error: &DiagnosticSender, ) -> Vec> { - self.runtime.run_test_source(allocator, source_text, check_syntax_errors, tx_error) + self.runtime.run_test_source(allocator, check_syntax_errors, tx_error) } } diff --git a/crates/oxc_linter/src/service/runtime.rs b/crates/oxc_linter/src/service/runtime.rs index 85793f4b45e15..b04cf8b5424ee 100644 --- a/crates/oxc_linter/src/service/runtime.rs +++ b/crates/oxc_linter/src/service/runtime.rs @@ -51,9 +51,6 @@ pub struct Runtime { // This is required to support `run: "onType"` configuration #[cfg(feature = "language_server")] source_text_cache: FxHashMap, String>, - - #[cfg(test)] - pub(super) test_source: std::sync::RwLock>, } /// Output of `Runtime::process_path` @@ -184,12 +181,9 @@ impl Runtime { file_system: Box::new(OsFileSystem), #[cfg(feature = "language_server")] source_text_cache: FxHashMap::default(), - #[cfg(test)] - test_source: std::sync::RwLock::new(None), } } - #[expect(dead_code)] pub fn with_file_system( mut self, file_system: Box, @@ -236,13 +230,6 @@ impl Runtime { } let source_type = source_type.unwrap_or_default(); - #[cfg(test)] - if let (true, Some(test_source)) = - (self.paths.contains(path.as_os_str()), &*self.test_source.read().unwrap()) - { - return Some(Ok((source_type, test_source.clone()))); - } - // The language server uses more up to date source_text provided by `workspace/didChange` request. // This is required to support `run: "onType"` configuration #[cfg(feature = "language_server")] @@ -697,15 +684,12 @@ impl Runtime { pub(super) fn run_test_source<'a>( &mut self, allocator: &'a Allocator, - source_text: &str, check_syntax_errors: bool, tx_error: &DiagnosticSender, ) -> Vec> { use oxc_allocator::CloneIn; use std::sync::Mutex; - *self.test_source.write().unwrap() = Some(source_text.to_owned()); - let messages = Mutex::new(Vec::>::new()); rayon::scope(|scope| { self.resolve_modules(scope, check_syntax_errors, tx_error, |me, mut module| { diff --git a/crates/oxc_linter/src/tester.rs b/crates/oxc_linter/src/tester.rs index 3a9d1fd71d0ea..83275a921e94a 100644 --- a/crates/oxc_linter/src/tester.rs +++ b/crates/oxc_linter/src/tester.rs @@ -17,7 +17,9 @@ use crate::{ Oxlintrc, RuleEnum, RuleWithSeverity, fixer::{FixKind, Fixer}, options::LintOptions, + read_to_string, rules::RULES, + service::RuntimeFileSystem, }; #[derive(Eq, PartialEq)] @@ -165,6 +167,31 @@ where } } +struct TesterFileSystem { + path_to_lint: PathBuf, + source_text: String, +} + +impl TesterFileSystem { + pub fn new(path_to_lint: PathBuf, source_text: String) -> Self { + Self { path_to_lint, source_text } + } +} + +impl RuntimeFileSystem for TesterFileSystem { + fn read_to_string(&self, path: &Path) -> Result { + if path == self.path_to_lint { + return Ok(self.source_text.clone()); + } + + read_to_string(path) + } + + fn write_file(&self, _path: &Path, _content: String) -> Result<(), std::io::Error> { + panic!("writing file should not be allowed in Tester"); + } +} + pub struct Tester { rule_name: &'static str, plugin_name: &'static str, @@ -484,9 +511,12 @@ impl Tester { let paths = vec![Arc::::from(path_to_lint.as_os_str())]; let options = LintServiceOptions::new(cwd, paths).with_cross_module(self.plugins.has_import()); - let mut lint_service = LintService::from_linter(linter, options); + let mut lint_service = LintService::new(linter, options).with_file_system(Box::new( + TesterFileSystem::new(path_to_lint, source_text.to_string()), + )); + let (sender, _receiver) = mpsc::channel(); - let result = lint_service.run_test_source(&allocator, source_text, false, &sender); + let result = lint_service.run_test_source(&allocator, false, &sender); if result.is_empty() { return TestResult::Passed;