diff --git a/crates/oxc_language_server/src/main.rs b/crates/oxc_language_server/src/main.rs index dd8b5be25d9be..da717572e0b6c 100644 --- a/crates/oxc_language_server/src/main.rs +++ b/crates/oxc_language_server/src/main.rs @@ -17,12 +17,12 @@ use tower_lsp::{ CodeActionProviderCapability, CodeActionResponse, ConfigurationItem, Diagnostic, DiagnosticOptions, DiagnosticServerCapabilities, DidChangeConfigurationParams, DidChangeTextDocumentParams, DidChangeWatchedFilesParams, DidCloseTextDocumentParams, - DidOpenTextDocumentParams, DidSaveTextDocumentParams, DocumentDiagnosticParams, - DocumentDiagnosticReport, DocumentDiagnosticReportResult, FullDocumentDiagnosticReport, - InitializeParams, InitializeResult, InitializedParams, OneOf, - RelatedFullDocumentDiagnosticReport, ServerCapabilities, ServerInfo, - TextDocumentSyncCapability, TextDocumentSyncKind, TextEdit, Url, WorkDoneProgressOptions, - WorkspaceEdit, WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, + DidOpenTextDocumentParams, DocumentDiagnosticParams, DocumentDiagnosticReport, + DocumentDiagnosticReportResult, FullDocumentDiagnosticReport, InitializeParams, + InitializeResult, InitializedParams, OneOf, RelatedFullDocumentDiagnosticReport, + ServerCapabilities, ServerInfo, TextDocumentSyncCapability, TextDocumentSyncKind, TextEdit, + Url, WorkDoneProgressOptions, WorkspaceEdit, WorkspaceFoldersServerCapabilities, + WorkspaceServerCapabilities, }, Client, LanguageServer, LspService, Server, }; @@ -33,7 +33,7 @@ struct Backend { client: Client, root_uri: OnceCell>, server_linter: RwLock, - document_content_cache: DashMap, + document_content_cache: DashMap, diagnostics_report_map: DashMap>, options: Mutex, gitignore_glob: Mutex>, @@ -165,7 +165,7 @@ impl LanguageServer for Backend { debug!("{:?}", &changed_options.get_lint_level()); if changed_options.get_lint_level() == SyntheticRunLevel::Disable { // clear all exists diagnostics when linter is disabled - let opened_files = self.diagnostics_report_map.iter().map(|k| k.key().to_string()); + let opened_files = self.document_content_cache.iter().map(|k| k.key().to_string()); let cleared_diagnostics = opened_files .into_iter() .map(|uri| { @@ -180,6 +180,7 @@ impl LanguageServer for Backend { }) .collect::>(); self.publish_all_diagnostics(&cleared_diagnostics).await; + self.diagnostics_report_map.clear(); } *self.options.lock().await = changed_options; } @@ -199,18 +200,19 @@ impl LanguageServer for Backend { } async fn did_open(&self, params: DidOpenTextDocumentParams) { - self.document_content_cache.insert(params.text_document.uri, params.text_document.text); + self.document_content_cache + .insert(params.text_document.uri.to_string(), params.text_document.text); } async fn did_close(&self, params: DidCloseTextDocumentParams) { - self.document_content_cache.remove(¶ms.text_document.uri); + self.document_content_cache.remove(¶ms.text_document.uri.to_string()); } async fn did_change(&self, params: DidChangeTextDocumentParams) { let content = params.content_changes.first().map(|c| c.text.clone()); if let Some(content) = content { - self.document_content_cache.insert(params.text_document.uri, content); + self.document_content_cache.insert(params.text_document.uri.to_string(), content); } } @@ -218,16 +220,22 @@ impl LanguageServer for Backend { &self, params: DocumentDiagnosticParams, ) -> Result { + // the file is ignored, return empty result + if self.is_ignored(¶ms.text_document.uri).await { + return Ok(DocumentDiagnosticReportResult::Report(DocumentDiagnosticReport::Full( + RelatedFullDocumentDiagnosticReport { + related_documents: None, + full_document_diagnostic_report: FullDocumentDiagnosticReport::default(), + }, + ))); + } + let content = self .document_content_cache - .get(¶ms.text_document.uri) + .get(¶ms.text_document.uri.to_string()) .map(|entry| entry.value().to_owned()); - let Some(entry) = self.document_content_cache.get(¶ms.text_document.uri) else { - return Err(Error::new(ErrorCode::InvalidParams)); - }; - - let Some(result) = self.lint_uri(entry.key(), content).await else { + let Some(result) = self.lint_uri(¶ms.text_document.uri, content).await else { return Ok(DocumentDiagnosticReportResult::Report(DocumentDiagnosticReport::Full( RelatedFullDocumentDiagnosticReport { related_documents: None, @@ -236,8 +244,6 @@ impl LanguageServer for Backend { ))); }; - self.diagnostics_report_map.insert(entry.key().to_string(), result.clone()); - Ok(DocumentDiagnosticReportResult::Report(DocumentDiagnosticReport::Full( RelatedFullDocumentDiagnosticReport { related_documents: None, @@ -357,10 +363,12 @@ impl Backend { } async fn revalidate_open_files(&self) { - join_all(self.diagnostics_report_map.iter().map(|map| { - let url = Url::from_str(map.key()).expect("should convert to path"); - - self.handle_file_update(url, None, None) + join_all(self.document_content_cache.iter().map(|map| { + self.lint_file_and_publish_diagnostic( + Url::from_str(map.key()).unwrap(), + Some(map.value().clone()), + None, + ) })) .await; } @@ -396,9 +404,20 @@ impl Backend { return None; }; - self.server_linter.read().await.run_single(&uri, content) + let result = self.server_linter.read().await.run_single(&uri, content); + + if result.is_some() { + self.diagnostics_report_map.insert(uri.to_string(), result.clone().unwrap()); + } + + result } - async fn handle_file_update(&self, uri: Url, content: Option, version: Option) { + async fn lint_file_and_publish_diagnostic( + &self, + uri: Url, + content: Option, + version: Option, + ) { if let Some(diagnostics) = self.lint_uri(&uri, content).await { self.client .publish_diagnostics( @@ -407,8 +426,6 @@ impl Backend { version, ) .await; - - self.diagnostics_report_map.insert(uri.to_string(), diagnostics); } }