Add identifier to diagnostic provider

This commit is contained in:
Sofus Addington 2025-03-04 06:01:08 +01:00
parent 96cf04288d
commit 14982fb525
No known key found for this signature in database
GPG key ID: 57579341E1199840
3 changed files with 128 additions and 40 deletions

View file

@ -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<String>,
},
// 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<String>,
) -> 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<DiagnosticProvider> 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));

View file

@ -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,

View file

@ -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 {