diff --git a/crates/oxc_language_server/src/backend.rs b/crates/oxc_language_server/src/backend.rs index 2459c8a3f046c..0928a186d5685 100644 --- a/crates/oxc_language_server/src/backend.rs +++ b/crates/oxc_language_server/src/backend.rs @@ -492,7 +492,7 @@ impl LanguageServer for Backend { self.file_system.write().await.set(uri, content.clone()); } - if let Some(diagnostics) = worker.run_diagnostic_on_change(uri, content).await { + if let Some(diagnostics) = worker.run_diagnostic_on_change(uri, content.as_deref()).await { self.client .publish_diagnostics(uri.clone(), diagnostics, Some(params.text_document.version)) .await; @@ -516,7 +516,7 @@ impl LanguageServer for Backend { self.file_system.write().await.set(uri, content.clone()); } - if let Some(diagnostics) = worker.run_diagnostic(uri, Some(content)).await { + if let Some(diagnostics) = worker.run_diagnostic(uri, Some(&content)).await { self.client .publish_diagnostics(uri.clone(), diagnostics, Some(params.text_document.version)) .await; @@ -599,7 +599,7 @@ impl LanguageServer for Backend { let Some(worker) = workers.iter().find(|worker| worker.is_responsible_for_uri(uri)) else { return Ok(None); }; - Ok(worker.format_file(uri, self.file_system.read().await.get(uri)).await) + Ok(worker.format_file(uri, self.file_system.read().await.get(uri).as_deref()).await) } } diff --git a/crates/oxc_language_server/src/formatter/server_formatter.rs b/crates/oxc_language_server/src/formatter/server_formatter.rs index 73e843045a534..c8fd247a762ad 100644 --- a/crates/oxc_language_server/src/formatter/server_formatter.rs +++ b/crates/oxc_language_server/src/formatter/server_formatter.rs @@ -199,7 +199,7 @@ impl Tool for ServerFormatter { } } - fn run_format(&self, uri: &Uri, content: Option) -> Option> { + fn run_format(&self, uri: &Uri, content: Option<&str>) -> Option> { // Formatter is disabled if !self.should_run { return None; @@ -207,20 +207,26 @@ impl Tool for ServerFormatter { let path = uri.to_file_path()?; let source_type = get_supported_source_type(&path).map(enable_jsx_source_type)?; + // Declaring Variable to satisfy borrow checker + let file_content; let source_text = if let Some(content) = content { content } else { #[cfg(not(all(test, windows)))] - let source_text = std::fs::read_to_string(&path).ok()?; + { + file_content = std::fs::read_to_string(&path).ok()?; + } #[cfg(all(test, windows))] #[expect(clippy::disallowed_methods)] // no `cow_replace` in tests are fine // On Windows, convert CRLF to LF for consistent formatting results - let source_text = std::fs::read_to_string(&path).ok()?.replace("\r\n", "\n"); - source_text + { + file_content = std::fs::read_to_string(&path).ok()?.replace("\r\n", "\n"); + } + &file_content }; let allocator = Allocator::new(); - let ret = Parser::new(&allocator, &source_text, source_type) + let ret = Parser::new(&allocator, source_text, source_type) .with_options(get_parse_options()) .parse(); @@ -231,14 +237,14 @@ impl Tool for ServerFormatter { let code = Formatter::new(&allocator, self.options.clone()).build(&ret.program); // nothing has changed - if code == source_text { + if code == *source_text { return Some(vec![]); } - let (start, end, replacement) = compute_minimal_text_edit(&source_text, &code); - let rope = Rope::from(source_text.as_str()); - let (start_line, start_character) = get_line_column(&rope, start, &source_text); - let (end_line, end_character) = get_line_column(&rope, end, &source_text); + let (start, end, replacement) = compute_minimal_text_edit(source_text, &code); + let rope = Rope::from(source_text); + let (start_line, start_character) = get_line_column(&rope, start, source_text); + let (end_line, end_character) = get_line_column(&rope, end, source_text); Some(vec![TextEdit::new( Range::new( diff --git a/crates/oxc_language_server/src/linter/isolated_lint_handler.rs b/crates/oxc_language_server/src/linter/isolated_lint_handler.rs index fcdc679c161a9..0a1f91515ef6a 100644 --- a/crates/oxc_language_server/src/linter/isolated_lint_handler.rs +++ b/crates/oxc_language_server/src/linter/isolated_lint_handler.rs @@ -102,16 +102,17 @@ impl IsolatedLintHandler { Self { runner, unused_directives_severity: lint_options.report_unused_directive } } - pub fn run_single(&self, uri: &Uri, content: Option) -> Option> { + pub fn run_single(&self, uri: &Uri, content: Option<&str>) -> Option> { let path = uri.to_file_path()?; if !Self::should_lint_path(&path) { return None; } - let source_text = content.or_else(|| read_to_string(&path).ok())?; + let source_text = + if let Some(content) = content { content } else { &read_to_string(&path).ok()? }; - let mut diagnostics = self.lint_path(&path, uri, &source_text); + let mut diagnostics = self.lint_path(&path, uri, source_text); diagnostics.append(&mut generate_inverted_diagnostics(&diagnostics, uri)); Some(diagnostics) } diff --git a/crates/oxc_language_server/src/linter/server_linter.rs b/crates/oxc_language_server/src/linter/server_linter.rs index a4d0d940ad406..e1c677fa55ee1 100644 --- a/crates/oxc_language_server/src/linter/server_linter.rs +++ b/crates/oxc_language_server/src/linter/server_linter.rs @@ -455,7 +455,7 @@ impl Tool for ServerLinter { /// Lint a file with the current linter /// - If the file is not lintable or ignored, [`None`] is returned /// - If the file is lintable, but no diagnostics are found, an empty vector is returned - fn run_diagnostic(&self, uri: &Uri, content: Option) -> Option> { + fn run_diagnostic(&self, uri: &Uri, content: Option<&str>) -> Option> { self.run_file(uri, content) .map(|reports| reports.into_iter().map(|report| report.diagnostic).collect()) } @@ -467,7 +467,7 @@ impl Tool for ServerLinter { fn run_diagnostic_on_change( &self, uri: &Uri, - content: Option, + content: Option<&str>, ) -> Option> { if self.run != Run::OnType { return None; @@ -479,11 +479,7 @@ impl Tool for ServerLinter { /// - If the file is not lintable or ignored, [`None`] is returned /// - If the linter is not set to `OnSave`, [`None`] is returned /// - If the file is lintable, but no diagnostics are found, an empty vector is returned - fn run_diagnostic_on_save( - &self, - uri: &Uri, - content: Option, - ) -> Option> { + fn run_diagnostic_on_save(&self, uri: &Uri, content: Option<&str>) -> Option> { if self.run != Run::OnSave { return None; } @@ -563,7 +559,7 @@ impl ServerLinter { } /// Lint a single file, return `None` if the file is ignored. - fn run_file(&self, uri: &Uri, content: Option) -> Option> { + fn run_file(&self, uri: &Uri, content: Option<&str>) -> Option> { if self.is_ignored(uri) { return None; } diff --git a/crates/oxc_language_server/src/tool.rs b/crates/oxc_language_server/src/tool.rs index 3ddc9bba87829..368de5799eb7f 100644 --- a/crates/oxc_language_server/src/tool.rs +++ b/crates/oxc_language_server/src/tool.rs @@ -69,7 +69,7 @@ pub trait Tool: Sized { /// Returns a vector of `TextEdit` representing the formatting changes. /// /// Not all tools will implement formatting, so the default implementation returns `None`. - fn run_format(&self, _uri: &Uri, _content: Option) -> Option> { + fn run_format(&self, _uri: &Uri, _content: Option<&str>) -> Option> { None } @@ -77,7 +77,7 @@ pub trait Tool: Sized { /// If `content` is `None`, the tool should read the content from the file system. /// Returns a vector of `Diagnostic` representing the diagnostic results. /// Not all tools will implement diagnostics, so the default implementation returns `None`. - fn run_diagnostic(&self, _uri: &Uri, _content: Option) -> Option> { + fn run_diagnostic(&self, _uri: &Uri, _content: Option<&str>) -> Option> { None } @@ -88,7 +88,7 @@ pub trait Tool: Sized { fn run_diagnostic_on_save( &self, _uri: &Uri, - _content: Option, + _content: Option<&str>, ) -> Option> { None } @@ -100,7 +100,7 @@ pub trait Tool: Sized { fn run_diagnostic_on_change( &self, _uri: &Uri, - _content: Option, + _content: Option<&str>, ) -> Option> { None } diff --git a/crates/oxc_language_server/src/worker.rs b/crates/oxc_language_server/src/worker.rs index ad5a8f2fb0314..16acc52954716 100644 --- a/crates/oxc_language_server/src/worker.rs +++ b/crates/oxc_language_server/src/worker.rs @@ -149,7 +149,7 @@ impl WorkspaceWorker { pub async fn run_diagnostic( &self, uri: &Uri, - content: Option, + content: Option<&str>, ) -> Option> { let Some(server_linter) = &*self.server_linter.read().await else { return None; @@ -162,7 +162,7 @@ impl WorkspaceWorker { pub async fn run_diagnostic_on_change( &self, uri: &Uri, - content: Option, + content: Option<&str>, ) -> Option> { let Some(server_linter) = &*self.server_linter.read().await else { return None; @@ -175,7 +175,7 @@ impl WorkspaceWorker { pub async fn run_diagnostic_on_save( &self, uri: &Uri, - content: Option, + content: Option<&str>, ) -> Option> { let Some(server_linter) = &*self.server_linter.read().await else { return None; @@ -187,7 +187,7 @@ impl WorkspaceWorker { /// Format a file with the current formatter /// - If no file is not formattable or ignored, [`None`] is returned /// - If the file is formattable, but no changes are made, an empty vector is returned - pub async fn format_file(&self, uri: &Uri, content: Option) -> Option> { + pub async fn format_file(&self, uri: &Uri, content: Option<&str>) -> Option> { let Some(server_formatter) = &*self.server_formatter.read().await else { return None; };