From 14982fb5251cbf5ae61d01e2e1ec7243195e1b2c Mon Sep 17 00:00:00 2001 From: Sofus Addington Date: Tue, 4 Mar 2025 06:01:08 +0100 Subject: [PATCH] Add identifier to diagnostic provider --- helix-core/src/diagnostic.rs | 153 +++++++++++++++++++------ helix-term/src/application.rs | 2 +- helix-term/src/handlers/diagnostics.rs | 13 ++- 3 files changed, 128 insertions(+), 40 deletions(-) diff --git a/helix-core/src/diagnostic.rs b/helix-core/src/diagnostic.rs index a133fae1..3f326037 100644 --- a/helix-core/src/diagnostic.rs +++ b/helix-core/src/diagnostic.rs @@ -53,15 +53,75 @@ pub struct Diagnostic { // TODO turn this into a feature flag when lsp becomes optional #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum DiagnosticProvider { - PublishDiagnosticProvider(LanguageServerId), - PullDiagnosticProvider(LanguageServerId), + Lsp { + server_id: LanguageServerId, + identifier: Option, + }, + // In the future, other non-LSP providers like spell checking go here... +} + +impl DiagnosticProvider { + pub fn from_server_id(server_id: LanguageServerId) -> DiagnosticProvider { + DiagnosticProvider::Lsp { + server_id, + identifier: None, + } + } + + pub fn from_server_and_identifier( + server_id: LanguageServerId, + identifier: Option, + ) -> DiagnosticProvider { + DiagnosticProvider::Lsp { + server_id, + identifier, + } + } + + pub fn server_id(&self) -> &LanguageServerId { + match self { + DiagnosticProvider::Lsp { + server_id, + identifier: _, + } => server_id, + } + } + + pub fn has_server_id(&self, server_id: &LanguageServerId) -> bool { + match self { + DiagnosticProvider::Lsp { + server_id: id, + identifier: _, + } => server_id == id, + } + } + + pub fn equals(&self, diagnostic_provider: &DiagnosticProvider) -> bool { + let (other_identifier, other_server_id) = match diagnostic_provider { + DiagnosticProvider::Lsp { + server_id, + identifier, + } => (identifier, server_id), + }; + + let (identifier, server_id) = match self { + DiagnosticProvider::Lsp { + server_id, + identifier, + } => (identifier, server_id), + }; + + identifier == other_identifier && server_id == other_server_id + } } impl From for LanguageServerId { fn from(value: DiagnosticProvider) -> Self { match value { - DiagnosticProvider::PublishDiagnosticProvider(id) => id, - DiagnosticProvider::PullDiagnosticProvider(id) => id, + DiagnosticProvider::Lsp { + server_id, + identifier: _, + } => server_id, } } } @@ -74,33 +134,6 @@ slotmap::new_key_type! { pub struct LanguageServerId; } -impl DiagnosticProvider { - pub fn server_id(&self) -> &LanguageServerId { - match self { - DiagnosticProvider::PublishDiagnosticProvider(language_server_id) => language_server_id, - DiagnosticProvider::PullDiagnosticProvider(language_server_id) => language_server_id, - } - } - - pub fn has_server_id(&self, server_id: &LanguageServerId) -> bool { - match self { - DiagnosticProvider::PublishDiagnosticProvider(language_server_id) => { - language_server_id == server_id - } - DiagnosticProvider::PullDiagnosticProvider(language_server_id) => { - language_server_id == server_id - } - } - } - - pub fn equals(&self, diagnostic_provider: &DiagnosticProvider) -> bool { - let server_id = self.server_id(); - let other_server_id = diagnostic_provider.server_id(); - - server_id == other_server_id - } -} - impl fmt::Display for LanguageServerId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.0) @@ -124,9 +157,23 @@ mod tests { #[test] fn can_compare_equal_diagnostic_provider() { let first_provider = - DiagnosticProvider::PublishDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1))); + DiagnosticProvider::from_server_id(LanguageServerId(KeyData::from_ffi(1))); let second_provider = - DiagnosticProvider::PublishDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1))); + DiagnosticProvider::from_server_id(LanguageServerId(KeyData::from_ffi(1))); + + assert!(first_provider.equals(&second_provider)); + } + + #[test] + fn can_compare_equal_diagnostic_provider_with_identifier() { + let first_provider = DiagnosticProvider::from_server_and_identifier( + LanguageServerId(KeyData::from_ffi(1)), + Some("provider".to_string()), + ); + let second_provider = DiagnosticProvider::from_server_and_identifier( + LanguageServerId(KeyData::from_ffi(1)), + Some("provider".to_string()), + ); assert!(first_provider.equals(&second_provider)); } @@ -134,17 +181,47 @@ mod tests { #[test] fn can_distinguish_diagnostic_provider() { let first_provider = - DiagnosticProvider::PublishDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1))); + DiagnosticProvider::from_server_id(LanguageServerId(KeyData::from_ffi(1))); let second_provider = - DiagnosticProvider::PullDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1))); + DiagnosticProvider::from_server_id(LanguageServerId(KeyData::from_ffi(2))); - assert!(first_provider.equals(&second_provider)); + assert!(!first_provider.equals(&second_provider)); + } + + #[test] + fn can_distinguish_diagnostic_provider_by_identifier() { + let first_provider = DiagnosticProvider::from_server_and_identifier( + LanguageServerId(KeyData::from_ffi(1)), + Some("provider".to_string()), + ); + let second_provider = DiagnosticProvider::from_server_and_identifier( + LanguageServerId(KeyData::from_ffi(1)), + None, + ); + + assert!(!first_provider.equals(&second_provider)); + } + + #[test] + fn can_distinguish_diagnostic_provider_by_language_server_id() { + let first_provider = DiagnosticProvider::from_server_and_identifier( + LanguageServerId(KeyData::from_ffi(1)), + Some("provider".to_string()), + ); + let second_provider = DiagnosticProvider::from_server_and_identifier( + LanguageServerId(KeyData::from_ffi(2)), + Some("provider".to_string()), + ); + + assert!(!first_provider.equals(&second_provider)); } #[test] fn can_compare_language_server_id() { - let provider = - DiagnosticProvider::PublishDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1))); + let provider = DiagnosticProvider::from_server_and_identifier( + LanguageServerId(KeyData::from_ffi(1)), + Some("provider".to_string()), + ); let language_server_id = LanguageServerId(KeyData::from_ffi(1)); diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 57c82634..6e66041b 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -754,7 +754,7 @@ impl Application { } let diagnostic_provider = - DiagnosticProvider::PublishDiagnosticProvider(language_server.id()); + DiagnosticProvider::from_server_id(language_server.id()); self.editor.handle_lsp_diagnostics( &diagnostic_provider, diff --git a/helix-term/src/handlers/diagnostics.rs b/helix-term/src/handlers/diagnostics.rs index bdd1408c..c04b6e9a 100644 --- a/helix-term/src/handlers/diagnostics.rs +++ b/helix-term/src/handlers/diagnostics.rs @@ -122,7 +122,18 @@ pub fn pull_diagnostics_for_document( return; }; - let provider = DiagnosticProvider::PullDiagnosticProvider(language_server.id()); + let identifier = language_server + .capabilities() + .diagnostic_provider + .as_ref() + .and_then(|diagnostic_provider| match diagnostic_provider { + lsp::DiagnosticServerCapabilities::Options(options) => options.identifier.clone(), + lsp::DiagnosticServerCapabilities::RegistrationOptions(options) => { + options.diagnostic_options.identifier.clone() + } + }); + + let provider = DiagnosticProvider::from_server_and_identifier(language_server.id(), identifier); let document_id = doc.id(); tokio::spawn(async move {