Detailed changes
@@ -332,6 +332,7 @@ pub struct Edit {
pub old_bytes: Range<usize>,
pub new_bytes: Range<usize>,
pub old_lines: Range<Point>,
+ pub new_lines: Range<Point>,
}
impl Edit {
@@ -2014,6 +2015,7 @@ impl<'a, F: FnMut(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
old_bytes: self.old_offset..self.old_offset,
new_bytes: self.new_offset..self.new_offset + fragment.len,
old_lines: self.old_point..self.old_point,
+ new_lines: self.new_point..self.new_point + fragment_lines,
});
}
@@ -2035,6 +2037,7 @@ impl<'a, F: FnMut(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
old_bytes: self.old_offset..self.old_offset + fragment.len,
new_bytes: self.new_offset..self.new_offset,
old_lines: self.old_point..self.old_point + &fragment_lines,
+ new_lines: self.new_point..self.new_point,
});
}
@@ -3,7 +3,7 @@ use anyhow::Result;
use gpui::AppContext;
use parking_lot::Mutex;
use serde::Deserialize;
-use std::{path::Path, str, sync::Arc};
+use std::{collections::HashSet, path::Path, str, sync::Arc};
use theme::SyntaxTheme;
use tree_sitter::{Language as Grammar, Query};
pub use tree_sitter::{Parser, Tree};
@@ -19,7 +19,7 @@ pub struct LanguageConfig {
#[derive(Deserialize)]
pub struct LanguageServerConfig {
pub binary: String,
- pub disk_based_diagnostic_sources: Vec<String>,
+ pub disk_based_diagnostic_sources: HashSet<String>,
}
#[derive(Clone, Debug, Deserialize)]
@@ -130,11 +130,11 @@ impl Language {
}
}
- pub fn disk_based_diagnostic_sources(&self) -> &[String] {
+ pub fn disk_based_diagnostic_sources(&self) -> Option<&HashSet<String>> {
self.config
.language_server
.as_ref()
- .map_or(&[], |config| &config.disk_based_diagnostic_sources)
+ .map(|config| &config.disk_based_diagnostic_sources)
}
pub fn brackets(&self) -> &[BracketPair] {
@@ -661,18 +661,52 @@ impl Buffer {
} else {
self.content()
};
+
+ let empty_set = HashSet::new();
+ let disk_based_sources = self
+ .language
+ .as_ref()
+ .and_then(|language| language.disk_based_diagnostic_sources())
+ .unwrap_or(&empty_set);
+
+ let mut edits_since_save = self.text.edits_since(self.saved_version.clone()).peekable();
+ let mut last_edit_old_end = Point::zero();
+ let mut last_edit_new_end = Point::zero();
+
self.diagnostics = content.anchor_range_multimap(
Bias::Left,
Bias::Right,
- diagnostics.into_iter().map(|diagnostic| {
+ diagnostics.into_iter().filter_map(|diagnostic| {
// TODO: Use UTF-16 positions.
- let start = Point::new(
+ let mut start = Point::new(
diagnostic.range.start.line,
diagnostic.range.start.character,
);
- let end = Point::new(diagnostic.range.end.line, diagnostic.range.end.character);
+ let mut end = Point::new(diagnostic.range.end.line, diagnostic.range.end.character);
let severity = diagnostic.severity.unwrap_or(DiagnosticSeverity::ERROR);
- (start..end, (severity, diagnostic.message))
+
+ if diagnostic
+ .source
+ .as_ref()
+ .map_or(false, |source| disk_based_sources.contains(source))
+ {
+ while let Some(edit) = edits_since_save.peek() {
+ if edit.old_lines.end <= start {
+ last_edit_old_end = edit.old_lines.end;
+ last_edit_new_end = edit.new_lines.end;
+ edits_since_save.next();
+ } else if edit.old_lines.start <= end && edit.old_lines.end >= start {
+ return None;
+ } else {
+ break;
+ }
+ }
+
+ start = last_edit_new_end + (start - last_edit_old_end);
+ end = last_edit_new_end + (end - last_edit_old_end);
+ }
+
+ Some((start..end, (severity, diagnostic.message)))
}),
);