Start work on preserving continuity of disk-based diagnostics
This commit is contained in:
parent
e31205c95e
commit
1544da887e
4 changed files with 72 additions and 8 deletions
|
@ -18,11 +18,11 @@ use smol::future::yield_now;
|
||||||
use std::{
|
use std::{
|
||||||
any::Any,
|
any::Any,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
cmp,
|
cmp::{self, Reverse},
|
||||||
collections::{BTreeMap, HashMap, HashSet},
|
collections::{BTreeMap, HashMap, HashSet},
|
||||||
ffi::OsString,
|
ffi::OsString,
|
||||||
future::Future,
|
future::Future,
|
||||||
iter::{Iterator, Peekable},
|
iter::{self, Iterator, Peekable},
|
||||||
ops::{Deref, DerefMut, Range},
|
ops::{Deref, DerefMut, Range},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
str,
|
str,
|
||||||
|
@ -92,6 +92,7 @@ pub struct Diagnostic {
|
||||||
pub severity: DiagnosticSeverity,
|
pub severity: DiagnosticSeverity,
|
||||||
pub message: String,
|
pub message: String,
|
||||||
pub group_id: usize,
|
pub group_id: usize,
|
||||||
|
pub is_valid: bool,
|
||||||
pub is_primary: bool,
|
pub is_primary: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +726,7 @@ impl Buffer {
|
||||||
mut diagnostics: Vec<DiagnosticEntry<PointUtf16>>,
|
mut diagnostics: Vec<DiagnosticEntry<PointUtf16>>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Result<Operation> {
|
) -> Result<Operation> {
|
||||||
diagnostics.sort_unstable_by_key(|d| (d.range.start, d.range.end));
|
diagnostics.sort_unstable_by_key(|d| (d.range.start, Reverse(d.range.end)));
|
||||||
|
|
||||||
let version = version.map(|version| version as usize);
|
let version = version.map(|version| version as usize);
|
||||||
let content = if let Some(version) = version {
|
let content = if let Some(version) = version {
|
||||||
|
@ -754,6 +755,7 @@ impl Buffer {
|
||||||
.peekable();
|
.peekable();
|
||||||
let mut last_edit_old_end = PointUtf16::zero();
|
let mut last_edit_old_end = PointUtf16::zero();
|
||||||
let mut last_edit_new_end = PointUtf16::zero();
|
let mut last_edit_new_end = PointUtf16::zero();
|
||||||
|
let mut has_disk_based_diagnostics = false;
|
||||||
let mut ix = 0;
|
let mut ix = 0;
|
||||||
'outer: while ix < diagnostics.len() {
|
'outer: while ix < diagnostics.len() {
|
||||||
let entry = &mut diagnostics[ix];
|
let entry = &mut diagnostics[ix];
|
||||||
|
@ -769,6 +771,7 @@ impl Buffer {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |source| disk_based_sources.contains(source))
|
.map_or(false, |source| disk_based_sources.contains(source))
|
||||||
{
|
{
|
||||||
|
has_disk_based_diagnostics = true;
|
||||||
while let Some(edit) = edits_since_save.peek() {
|
while let Some(edit) = edits_since_save.peek() {
|
||||||
if edit.old.end <= start {
|
if edit.old.end <= start {
|
||||||
last_edit_old_end = edit.old.end;
|
last_edit_old_end = edit.old.end;
|
||||||
|
@ -802,7 +805,62 @@ impl Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(edits_since_save);
|
drop(edits_since_save);
|
||||||
self.diagnostics = DiagnosticSet::new(diagnostics, content);
|
|
||||||
|
let diagnostics = diagnostics.into_iter().map(|entry| DiagnosticEntry {
|
||||||
|
range: content.anchor_before(entry.range.start)..content.anchor_after(entry.range.end),
|
||||||
|
diagnostic: entry.diagnostic,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Some diagnostic sources are reported on a less frequent basis than others.
|
||||||
|
// If those sources are absent from this message, then preserve the previous
|
||||||
|
// diagnostics for those sources, but mark them as stale, and set a time to
|
||||||
|
// clear them out.
|
||||||
|
let mut merged_old_disk_based_diagnostics = false;
|
||||||
|
self.diagnostics = if has_disk_based_diagnostics {
|
||||||
|
DiagnosticSet::from_sorted_entries(diagnostics, content)
|
||||||
|
} else {
|
||||||
|
let mut new_diagnostics = diagnostics.peekable();
|
||||||
|
let mut old_diagnostics = self
|
||||||
|
.diagnostics
|
||||||
|
.iter()
|
||||||
|
.filter_map(|entry| {
|
||||||
|
let is_disk_based = entry
|
||||||
|
.diagnostic
|
||||||
|
.source
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |source| disk_based_sources.contains(source));
|
||||||
|
if is_disk_based {
|
||||||
|
merged_old_disk_based_diagnostics = true;
|
||||||
|
let mut entry = entry.clone();
|
||||||
|
entry.diagnostic.is_valid = false;
|
||||||
|
Some(entry)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.peekable();
|
||||||
|
let merged_diagnostics =
|
||||||
|
iter::from_fn(|| match (old_diagnostics.peek(), new_diagnostics.peek()) {
|
||||||
|
(None, None) => None,
|
||||||
|
(Some(_), None) => old_diagnostics.next(),
|
||||||
|
(None, Some(_)) => new_diagnostics.next(),
|
||||||
|
(Some(old), Some(new)) => {
|
||||||
|
let ordering = old
|
||||||
|
.range
|
||||||
|
.start
|
||||||
|
.cmp(&new.range.start, content)
|
||||||
|
.unwrap()
|
||||||
|
.then_with(|| new.range.end.cmp(&old.range.end, content).unwrap());
|
||||||
|
if ordering.is_lt() {
|
||||||
|
old_diagnostics.next()
|
||||||
|
} else {
|
||||||
|
new_diagnostics.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
DiagnosticSet::from_sorted_entries(merged_diagnostics, content)
|
||||||
|
};
|
||||||
|
|
||||||
self.diagnostics_update_count += 1;
|
self.diagnostics_update_count += 1;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
cx.emit(Event::DiagnosticsUpdated);
|
cx.emit(Event::DiagnosticsUpdated);
|
||||||
|
@ -2009,6 +2067,7 @@ impl Default for Diagnostic {
|
||||||
message: Default::default(),
|
message: Default::default(),
|
||||||
group_id: Default::default(),
|
group_id: Default::default(),
|
||||||
is_primary: Default::default(),
|
is_primary: Default::default(),
|
||||||
|
is_valid: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,7 @@ pub fn serialize_diagnostics<'a>(
|
||||||
} as i32,
|
} as i32,
|
||||||
group_id: entry.diagnostic.group_id as u64,
|
group_id: entry.diagnostic.group_id as u64,
|
||||||
is_primary: entry.diagnostic.is_primary,
|
is_primary: entry.diagnostic.is_primary,
|
||||||
|
is_valid: entry.diagnostic.is_valid,
|
||||||
code: entry.diagnostic.code.clone(),
|
code: entry.diagnostic.code.clone(),
|
||||||
source: entry.diagnostic.source.clone(),
|
source: entry.diagnostic.source.clone(),
|
||||||
})
|
})
|
||||||
|
@ -273,6 +274,7 @@ pub fn deserialize_diagnostics(
|
||||||
is_primary: diagnostic.is_primary,
|
is_primary: diagnostic.is_primary,
|
||||||
code: diagnostic.code,
|
code: diagnostic.code,
|
||||||
source: diagnostic.source,
|
source: diagnostic.source,
|
||||||
|
is_valid: diagnostic.is_valid,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -721,6 +721,7 @@ impl Worktree {
|
||||||
message: mem::take(&mut diagnostic.message),
|
message: mem::take(&mut diagnostic.message),
|
||||||
group_id,
|
group_id,
|
||||||
is_primary: false,
|
is_primary: false,
|
||||||
|
is_valid: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,10 +303,12 @@ message Diagnostic {
|
||||||
Anchor end = 2;
|
Anchor end = 2;
|
||||||
Severity severity = 3;
|
Severity severity = 3;
|
||||||
string message = 4;
|
string message = 4;
|
||||||
uint64 group_id = 5;
|
optional string code = 5;
|
||||||
bool is_primary = 6;
|
optional string source = 6;
|
||||||
optional string code = 7;
|
uint64 group_id = 7;
|
||||||
optional string source = 8;
|
bool is_primary = 8;
|
||||||
|
bool is_valid = 9;
|
||||||
|
|
||||||
enum Severity {
|
enum Severity {
|
||||||
None = 0;
|
None = 0;
|
||||||
Error = 1;
|
Error = 1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue