Remove duplication when assigning diagnostics and hardcode provider names

This commit is contained in:
Antonio Scandurra 2021-12-24 12:07:26 +01:00
parent 4f774e2bde
commit 11e3874b4a
8 changed files with 198 additions and 178 deletions

View file

@ -23,7 +23,7 @@ use std::{
ffi::OsString,
future::Future,
iter::{Iterator, Peekable},
ops::{Deref, DerefMut, Range},
ops::{Add, Deref, DerefMut, Range, Sub},
path::{Path, PathBuf},
str,
sync::Arc,
@ -31,7 +31,7 @@ use std::{
vec,
};
use sum_tree::TreeMap;
use text::operation_queue::OperationQueue;
use text::{operation_queue::OperationQueue, rope::TextDimension};
pub use text::{Buffer as TextBuffer, Operation as _, *};
use theme::SyntaxTheme;
use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
@ -85,6 +85,12 @@ pub struct BufferSnapshot {
parse_count: usize,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GroupId {
source: Arc<str>,
id: usize,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Diagnostic {
pub code: Option<String>,
@ -740,13 +746,16 @@ impl Buffer {
self.diagnostic_sets.iter().flat_map(|set| set.iter())
}
pub fn update_diagnostics(
pub fn update_diagnostics<T>(
&mut self,
provider_name: Arc<str>,
version: Option<i32>,
mut diagnostics: Vec<DiagnosticEntry<PointUtf16>>,
mut diagnostics: Vec<DiagnosticEntry<T>>,
cx: &mut ModelContext<Self>,
) -> Result<Operation> {
) -> Result<Operation>
where
T: ToPoint + Ord + Clip + TextDimension + Add<Output = T> + Sub<Output = T> + Copy,
{
fn compare_diagnostics(a: &Diagnostic, b: &Diagnostic) -> Ordering {
Ordering::Equal
.then_with(|| b.is_primary.cmp(&a.is_primary))
@ -755,13 +764,6 @@ impl Buffer {
.then_with(|| a.message.cmp(&b.message))
}
diagnostics.sort_unstable_by(|a, b| {
Ordering::Equal
.then_with(|| a.range.start.cmp(&b.range.start))
.then_with(|| b.range.end.cmp(&a.range.end))
.then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
});
let version = version.map(|version| version as usize);
let content = if let Some(version) = version {
let language_server = self.language_server.as_mut().unwrap();
@ -777,14 +779,18 @@ impl Buffer {
self.deref()
};
let mut edits_since_save = content
.edits_since::<PointUtf16>(&self.saved_version)
.peekable();
let mut last_edit_old_end = PointUtf16::zero();
let mut last_edit_new_end = PointUtf16::zero();
let mut ix = 0;
'outer: while ix < diagnostics.len() {
let entry = &mut diagnostics[ix];
diagnostics.sort_unstable_by(|a, b| {
Ordering::Equal
.then_with(|| a.range.start.cmp(&b.range.start))
.then_with(|| b.range.end.cmp(&a.range.end))
.then_with(|| compare_diagnostics(&a.diagnostic, &b.diagnostic))
});
let mut sanitized_diagnostics = Vec::new();
let mut edits_since_save = content.edits_since::<T>(&self.saved_version).peekable();
let mut last_edit_old_end = T::default();
let mut last_edit_new_end = T::default();
'outer: for entry in diagnostics {
let mut start = entry.range.start;
let mut end = entry.range.end;
@ -798,7 +804,6 @@ impl Buffer {
last_edit_new_end = edit.new.end;
edits_since_save.next();
} else if edit.old.start <= end && edit.old.end >= start {
diagnostics.remove(ix);
continue 'outer;
} else {
break;
@ -809,23 +814,26 @@ impl Buffer {
end = last_edit_new_end + (end - last_edit_old_end);
}
entry.range = content.clip_point_utf16(start, Bias::Left)
..content.clip_point_utf16(end, Bias::Right);
let range = start.clip(Bias::Left, content)..end.clip(Bias::Right, content);
let mut range = range.start.to_point(content)..range.end.to_point(content);
// Expand empty ranges by one character
if entry.range.start == entry.range.end {
entry.range.end.column += 1;
entry.range.end = content.clip_point_utf16(entry.range.end, Bias::Right);
if entry.range.start == entry.range.end && entry.range.end.column > 0 {
entry.range.start.column -= 1;
entry.range.start = content.clip_point_utf16(entry.range.start, Bias::Left);
if range.start == range.end {
range.end.column += 1;
range.end = content.clip_point(range.end, Bias::Right);
if range.start == range.end && range.end.column > 0 {
range.start.column -= 1;
range.start = content.clip_point(range.start, Bias::Left);
}
}
ix += 1;
sanitized_diagnostics.push(DiagnosticEntry {
range,
diagnostic: entry.diagnostic,
});
}
drop(edits_since_save);
let set = DiagnosticSet::new(provider_name, diagnostics, content);
let set = DiagnosticSet::new(provider_name, sanitized_diagnostics, content);
self.apply_diagnostic_update(set.clone(), cx);
Ok(Operation::UpdateDiagnostics {
provider_name: set.provider_name().to_string(),

View file

@ -7,7 +7,7 @@ use std::{
sync::Arc,
};
use sum_tree::{self, Bias, SumTree};
use text::{Anchor, FromAnchor, PointUtf16, ToOffset};
use text::{Anchor, FromAnchor, Point, ToOffset};
#[derive(Clone, Debug)]
pub struct DiagnosticSet {
@ -56,7 +56,7 @@ impl DiagnosticSet {
pub fn new<I>(provider_name: Arc<str>, iter: I, buffer: &text::BufferSnapshot) -> Self
where
I: IntoIterator<Item = DiagnosticEntry<PointUtf16>>,
I: IntoIterator<Item = DiagnosticEntry<Point>>,
{
let mut entries = iter.into_iter().collect::<Vec<_>>();
entries.sort_unstable_by_key(|entry| (entry.range.start, Reverse(entry.range.end)));

View file

@ -65,9 +65,7 @@ pub struct BracketPair {
}
#[async_trait]
pub trait DiagnosticSource: 'static + Send + Sync {
fn name(&self) -> Arc<str>;
pub trait DiagnosticProvider: 'static + Send + Sync {
async fn diagnose(
&self,
path: Arc<Path>,
@ -77,7 +75,7 @@ pub trait DiagnosticSource: 'static + Send + Sync {
pub struct Language {
pub(crate) config: LanguageConfig,
pub(crate) grammar: Option<Arc<Grammar>>,
pub(crate) diagnostic_source: Option<Arc<dyn DiagnosticSource>>,
pub(crate) diagnostic_provider: Option<Arc<dyn DiagnosticProvider>>,
}
pub struct Grammar {
@ -142,7 +140,7 @@ impl Language {
highlight_map: Default::default(),
})
}),
diagnostic_source: None,
diagnostic_provider: None,
}
}
@ -176,8 +174,8 @@ impl Language {
Ok(self)
}
pub fn with_diagnostic_source(mut self, source: impl DiagnosticSource) -> Self {
self.diagnostic_source = Some(Arc::new(source));
pub fn with_diagnostic_provider(mut self, source: impl DiagnosticProvider) -> Self {
self.diagnostic_provider = Some(Arc::new(source));
self
}
@ -214,8 +212,8 @@ impl Language {
}
}
pub fn diagnostic_source(&self) -> Option<&Arc<dyn DiagnosticSource>> {
self.diagnostic_source.as_ref()
pub fn diagnostic_provider(&self) -> Option<&Arc<dyn DiagnosticProvider>> {
self.diagnostic_provider.as_ref()
}
pub fn disk_based_diagnostic_sources(&self) -> Option<&HashSet<String>> {