diff --git a/crates/oxc_language_server/src/worker.rs b/crates/oxc_language_server/src/worker.rs index f3552c108d139..86ff10f35e405 100644 --- a/crates/oxc_language_server/src/worker.rs +++ b/crates/oxc_language_server/src/worker.rs @@ -100,30 +100,33 @@ impl WorkspaceWorker { uri: &Uri, content: Option, ) -> Option> { - if self.is_ignored(uri).await { - return None; + let diagnostics = self.lint_file_internal(uri, content).await; + + if let Some(diagnostics) = &diagnostics { + self.update_diagnostics(uri, diagnostics).await; } - Some(self.update_diagnostics(uri, content).await) + diagnostics } - async fn update_diagnostics( + async fn lint_file_internal( &self, uri: &Uri, content: Option, - ) -> Vec { - let diagnostics = self.server_linter.read().await.run_single(uri, content); - if let Some(diagnostics) = diagnostics { - self.diagnostics_report_map - .read() - .await - .pin() - .insert(uri.to_string(), diagnostics.clone()); - - return diagnostics; + ) -> Option> { + if self.is_ignored(uri).await { + return None; } - vec![] + self.server_linter.read().await.run_single(uri, content) + } + + async fn update_diagnostics(&self, uri: &Uri, diagnostics: &[DiagnosticReport]) { + self.diagnostics_report_map + .read() + .await + .pin() + .insert(uri.to_string(), diagnostics.to_owned()); } async fn revalidate_diagnostics(&self) -> ConcurrentHashMap> { @@ -160,11 +163,18 @@ impl WorkspaceWorker { is_source_fix_all_oxc: bool, ) -> Vec { let report_map = self.diagnostics_report_map.read().await; - let report_map_ref = report_map.pin(); - let Some(value) = report_map_ref.get(&uri.to_string()) else { - return vec![]; + let report_map_ref = report_map.pin_owned(); + let value = match report_map_ref.get(&uri.to_string()) { + Some(value) => value, + // code actions / commands can be requested without opening the file + // we just internally lint and provide the code actions / commands without refreshing the diagnostic map. + None => &self.lint_file_internal(uri, None).await.unwrap_or_default(), }; + if value.is_empty() { + return vec![]; + } + let reports = value .iter() .filter(|r| r.diagnostic.range == *range || range_overlaps(*range, r.diagnostic.range)); @@ -194,11 +204,18 @@ impl WorkspaceWorker { pub async fn get_diagnostic_text_edits(&self, uri: &Uri) -> Vec { let report_map = self.diagnostics_report_map.read().await; - let report_map_ref = report_map.pin(); - let Some(value) = report_map_ref.get(&uri.to_string()) else { - return vec![]; + let report_map_ref = report_map.pin_owned(); + let value = match report_map_ref.get(&uri.to_string()) { + Some(value) => value, + // code actions / commands can be requested without opening the file + // we just internally lint and provide the code actions / commands without refreshing the diagnostic map. + None => &self.lint_file_internal(uri, None).await.unwrap_or_default(), }; + if value.is_empty() { + return vec![]; + } + let mut text_edits = vec![]; for report in value { diff --git a/editors/vscode/client/extension.spec.ts b/editors/vscode/client/extension.spec.ts index d871b3b51a451..8f8aa3e0e4b24 100644 --- a/editors/vscode/client/extension.spec.ts +++ b/editors/vscode/client/extension.spec.ts @@ -99,7 +99,7 @@ suite('code actions', () => { }); await workspace.applyEdit(edit); - await window.showTextDocument(fileUri); + // await window.showTextDocument(fileUri); -- should also work without opening the file const codeActions: ProviderResult> = await commands.executeCommand( 'vscode.executeCodeActionProvider',