Prepare for indentifier in diagnostic provider
This commit is contained in:
parent
8b59087d32
commit
96cf04288d
7 changed files with 109 additions and 27 deletions
|
@ -51,7 +51,7 @@ pub struct Diagnostic {
|
|||
}
|
||||
|
||||
// TODO turn this into a feature flag when lsp becomes optional
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum DiagnosticProvider {
|
||||
PublishDiagnosticProvider(LanguageServerId),
|
||||
PullDiagnosticProvider(LanguageServerId),
|
||||
|
@ -74,6 +74,33 @@ 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)
|
||||
|
@ -86,3 +113,41 @@ impl Diagnostic {
|
|||
self.severity.unwrap_or(Severity::Warning)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use slotmap::KeyData;
|
||||
|
||||
use super::DiagnosticProvider;
|
||||
use crate::diagnostic::LanguageServerId;
|
||||
|
||||
#[test]
|
||||
fn can_compare_equal_diagnostic_provider() {
|
||||
let first_provider =
|
||||
DiagnosticProvider::PublishDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1)));
|
||||
let second_provider =
|
||||
DiagnosticProvider::PublishDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1)));
|
||||
|
||||
assert!(first_provider.equals(&second_provider));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_distinguish_diagnostic_provider() {
|
||||
let first_provider =
|
||||
DiagnosticProvider::PublishDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1)));
|
||||
let second_provider =
|
||||
DiagnosticProvider::PullDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1)));
|
||||
|
||||
assert!(first_provider.equals(&second_provider));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn can_compare_language_server_id() {
|
||||
let provider =
|
||||
DiagnosticProvider::PublishDiagnosticProvider(LanguageServerId(KeyData::from_ffi(1)));
|
||||
|
||||
let language_server_id = LanguageServerId(KeyData::from_ffi(1));
|
||||
|
||||
assert!(provider.has_server_id(&language_server_id));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -757,7 +757,7 @@ impl Application {
|
|||
DiagnosticProvider::PublishDiagnosticProvider(language_server.id());
|
||||
|
||||
self.editor.handle_lsp_diagnostics(
|
||||
diagnostic_provider,
|
||||
&diagnostic_provider,
|
||||
uri,
|
||||
params.version,
|
||||
params.diagnostics,
|
||||
|
@ -871,7 +871,7 @@ impl Application {
|
|||
// an empty diagnostic list for said files
|
||||
for diags in self.editor.diagnostics.values_mut() {
|
||||
diags.retain(|(_, diagnostic_provider)| {
|
||||
Into::<LanguageServerId>::into(*diagnostic_provider) != server_id
|
||||
!diagnostic_provider.has_server_id(&server_id)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ fn handle_pull_diagnostics_response(
|
|||
let (result_id, related_documents) = match response {
|
||||
lsp::DocumentDiagnosticReport::Full(report) => {
|
||||
editor.handle_lsp_diagnostics(
|
||||
provider,
|
||||
&provider,
|
||||
uri,
|
||||
None,
|
||||
report.full_document_diagnostic_report.items,
|
||||
|
@ -181,7 +181,7 @@ fn handle_pull_diagnostics_response(
|
|||
continue;
|
||||
};
|
||||
|
||||
editor.handle_lsp_diagnostics(provider, uri, None, report.items);
|
||||
editor.handle_lsp_diagnostics(&provider, uri, None, report.items);
|
||||
report.result_id
|
||||
}
|
||||
lsp::DocumentDiagnosticReportKind::Unchanged(report) => Some(report.result_id),
|
||||
|
|
|
@ -1407,8 +1407,13 @@ impl Document {
|
|||
true
|
||||
});
|
||||
|
||||
self.diagnostics
|
||||
.sort_by_key(|diagnostic| (diagnostic.range, diagnostic.severity, diagnostic.provider));
|
||||
self.diagnostics.sort_by_key(|diagnostic| {
|
||||
(
|
||||
diagnostic.range,
|
||||
diagnostic.severity,
|
||||
diagnostic.provider.clone(),
|
||||
)
|
||||
});
|
||||
|
||||
// Update the inlay hint annotations' positions, helping ensure they are displayed in the proper place
|
||||
let apply_inlay_hint_changes = |annotations: &mut Vec<InlineAnnotation>| {
|
||||
|
@ -2028,13 +2033,16 @@ impl Document {
|
|||
&mut self,
|
||||
diagnostics: impl IntoIterator<Item = Diagnostic>,
|
||||
unchanged_sources: &[String],
|
||||
diagnostic_provider: Option<DiagnosticProvider>,
|
||||
diagnostic_provider: Option<&DiagnosticProvider>,
|
||||
) {
|
||||
if unchanged_sources.is_empty() {
|
||||
self.clear_diagnostics(diagnostic_provider);
|
||||
} else {
|
||||
self.diagnostics.retain(|d| {
|
||||
if diagnostic_provider.is_some_and(|provider| provider != d.provider) {
|
||||
if diagnostic_provider
|
||||
.as_ref()
|
||||
.is_some_and(|provider| !provider.equals(&d.provider))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2046,14 +2054,19 @@ impl Document {
|
|||
});
|
||||
}
|
||||
self.diagnostics.extend(diagnostics);
|
||||
self.diagnostics
|
||||
.sort_by_key(|diagnostic| (diagnostic.range, diagnostic.severity, diagnostic.provider));
|
||||
self.diagnostics.sort_by_key(|diagnostic| {
|
||||
(
|
||||
diagnostic.range,
|
||||
diagnostic.severity,
|
||||
diagnostic.provider.clone(),
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
/// clears diagnostics for a given diagnostic provider if set, otherwise all diagnostics are cleared
|
||||
pub fn clear_diagnostics(&mut self, provider: Option<DiagnosticProvider>) {
|
||||
pub fn clear_diagnostics(&mut self, provider: Option<&DiagnosticProvider>) {
|
||||
if let Some(provider) = provider {
|
||||
self.diagnostics.retain(|d| d.provider != provider);
|
||||
self.diagnostics.retain(|d| !d.provider.equals(provider));
|
||||
} else {
|
||||
self.diagnostics.clear();
|
||||
}
|
||||
|
@ -2062,7 +2075,8 @@ impl Document {
|
|||
/// clears diagnostics for a given language_server if set, otherwise all diagnostics are cleared
|
||||
pub fn clear_all_language_server_diagnostics(&mut self, server_id: Option<LanguageServerId>) {
|
||||
if let Some(server_id) = server_id {
|
||||
self.diagnostics.retain(|d| server_id != d.provider.into());
|
||||
self.diagnostics
|
||||
.retain(|d| !d.provider.has_server_id(&server_id));
|
||||
} else {
|
||||
self.diagnostics.clear();
|
||||
}
|
||||
|
|
|
@ -2030,8 +2030,7 @@ impl Editor {
|
|||
diags
|
||||
.iter()
|
||||
.filter_map(move |(diagnostic, diagnostic_provider)| {
|
||||
let ls = language_servers
|
||||
.get_by_id(Into::<LanguageServerId>::into(*diagnostic_provider))?;
|
||||
let ls = language_servers.get_by_id(*diagnostic_provider.server_id())?;
|
||||
language_config
|
||||
.as_ref()
|
||||
.and_then(|c| {
|
||||
|
@ -2041,12 +2040,12 @@ impl Editor {
|
|||
})
|
||||
})
|
||||
.and_then(|_| {
|
||||
if filter(diagnostic, *diagnostic_provider) {
|
||||
if filter(diagnostic, diagnostic_provider.clone()) {
|
||||
Document::lsp_diagnostic_to_diagnostic(
|
||||
&text,
|
||||
language_config.as_deref(),
|
||||
diagnostic,
|
||||
*diagnostic_provider,
|
||||
diagnostic_provider.clone(),
|
||||
ls.offset_encoding(),
|
||||
)
|
||||
} else {
|
||||
|
|
|
@ -71,7 +71,7 @@ pub fn diagnostic<'doc>(
|
|||
d.line == line
|
||||
&& doc
|
||||
.language_servers_with_feature(LanguageServerFeature::Diagnostics)
|
||||
.any(|ls| ls.id() == d.provider.into())
|
||||
.any(|ls| d.provider.has_server_id(&ls.id()))
|
||||
});
|
||||
diagnostics_on_line.max_by_key(|d| d.severity).map(|d| {
|
||||
write!(out, "●").ok();
|
||||
|
|
|
@ -281,7 +281,7 @@ impl Editor {
|
|||
|
||||
pub fn handle_lsp_diagnostics(
|
||||
&mut self,
|
||||
diagnostic_provider: DiagnosticProvider,
|
||||
diagnostic_provider: &DiagnosticProvider,
|
||||
uri: Uri,
|
||||
version: Option<i32>,
|
||||
mut diagnostics: Vec<lsp::Diagnostic>,
|
||||
|
@ -314,8 +314,8 @@ impl Editor {
|
|||
.filter(|d| d.source.as_ref() == Some(source));
|
||||
let old_diagnostics = old_diagnostics
|
||||
.iter()
|
||||
.filter(|(d, d_server)| {
|
||||
*d_server == diagnostic_provider && d.source.as_ref() == Some(source)
|
||||
.filter(|(d, d_provider)| {
|
||||
diagnostic_provider.equals(d_provider) && d.source.as_ref() == Some(source)
|
||||
})
|
||||
.map(|(d, _)| d);
|
||||
if new_diagnostics.eq(old_diagnostics) {
|
||||
|
@ -324,7 +324,9 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
|
||||
let diagnostics = diagnostics.into_iter().map(|d| (d, diagnostic_provider));
|
||||
let diagnostics = diagnostics
|
||||
.into_iter()
|
||||
.map(|d| (d, diagnostic_provider.clone()));
|
||||
|
||||
// Insert the original lsp::Diagnostics here because we may have no open document
|
||||
// for diagnostic message and so we can't calculate the exact position.
|
||||
|
@ -333,7 +335,8 @@ impl Editor {
|
|||
Entry::Occupied(o) => {
|
||||
let current_diagnostics = o.into_mut();
|
||||
// there may entries of other language servers, which is why we can't overwrite the whole entry
|
||||
current_diagnostics.retain(|(_, lsp_id)| *lsp_id != diagnostic_provider);
|
||||
current_diagnostics
|
||||
.retain(|(_, ls_provider)| !diagnostic_provider.equals(ls_provider));
|
||||
current_diagnostics.extend(diagnostics);
|
||||
current_diagnostics
|
||||
// Sort diagnostics first by severity and then by line numbers.
|
||||
|
@ -343,12 +346,13 @@ impl Editor {
|
|||
|
||||
// Sort diagnostics first by severity and then by line numbers.
|
||||
// Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
|
||||
diagnostics.sort_by_key(|(d, server_id)| (d.severity, d.range.start, *server_id));
|
||||
diagnostics
|
||||
.sort_by_key(|(d, ls_provider)| (d.severity, d.range.start, ls_provider.clone()));
|
||||
|
||||
if let Some(doc) = doc {
|
||||
let diagnostic_of_language_server_and_not_in_unchanged_sources =
|
||||
|diagnostic: &lsp::Diagnostic, ls_id| {
|
||||
ls_id == diagnostic_provider
|
||||
|diagnostic: &lsp::Diagnostic, ls_provider| {
|
||||
diagnostic_provider.equals(&ls_provider)
|
||||
&& diagnostic
|
||||
.source
|
||||
.as_ref()
|
||||
|
|
Loading…
Add table
Reference in a new issue