mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-06 10:42:08 +00:00
Label the buffer's diff task so it can be deprioritized in tests
This commit is contained in:
parent
b2451d9dd6
commit
89d73f713a
1 changed files with 63 additions and 55 deletions
|
@ -17,7 +17,8 @@ use crate::{
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
pub use clock::ReplicaId;
|
pub use clock::ReplicaId;
|
||||||
use futures::FutureExt as _;
|
use futures::FutureExt as _;
|
||||||
use gpui::{AppContext, EventEmitter, HighlightStyle, ModelContext, Task};
|
use gpui::{AppContext, EventEmitter, HighlightStyle, ModelContext, Task, TaskLabel};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use lsp::LanguageServerId;
|
use lsp::LanguageServerId;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use similar::{ChangeTag, TextDiff};
|
use similar::{ChangeTag, TextDiff};
|
||||||
|
@ -51,6 +52,10 @@ pub use {tree_sitter_rust, tree_sitter_typescript};
|
||||||
|
|
||||||
pub use lsp::DiagnosticSeverity;
|
pub use lsp::DiagnosticSeverity;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref BUFFER_DIFF_TASK: TaskLabel = TaskLabel::new();
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Buffer {
|
pub struct Buffer {
|
||||||
text: TextBuffer,
|
text: TextBuffer,
|
||||||
diff_base: Option<String>,
|
diff_base: Option<String>,
|
||||||
|
@ -1118,69 +1123,72 @@ impl Buffer {
|
||||||
pub fn diff(&self, mut new_text: String, cx: &AppContext) -> Task<Diff> {
|
pub fn diff(&self, mut new_text: String, cx: &AppContext) -> Task<Diff> {
|
||||||
let old_text = self.as_rope().clone();
|
let old_text = self.as_rope().clone();
|
||||||
let base_version = self.version();
|
let base_version = self.version();
|
||||||
cx.background_executor().spawn(async move {
|
cx.background_executor()
|
||||||
let old_text = old_text.to_string();
|
.spawn_labeled(*BUFFER_DIFF_TASK, async move {
|
||||||
let line_ending = LineEnding::detect(&new_text);
|
let old_text = old_text.to_string();
|
||||||
LineEnding::normalize(&mut new_text);
|
let line_ending = LineEnding::detect(&new_text);
|
||||||
|
LineEnding::normalize(&mut new_text);
|
||||||
|
|
||||||
let diff = TextDiff::from_chars(old_text.as_str(), new_text.as_str());
|
let diff = TextDiff::from_chars(old_text.as_str(), new_text.as_str());
|
||||||
let empty: Arc<str> = "".into();
|
let empty: Arc<str> = "".into();
|
||||||
|
|
||||||
let mut edits = Vec::new();
|
let mut edits = Vec::new();
|
||||||
let mut old_offset = 0;
|
let mut old_offset = 0;
|
||||||
let mut new_offset = 0;
|
let mut new_offset = 0;
|
||||||
let mut last_edit: Option<(Range<usize>, Range<usize>)> = None;
|
let mut last_edit: Option<(Range<usize>, Range<usize>)> = None;
|
||||||
for change in diff.iter_all_changes().map(Some).chain([None]) {
|
for change in diff.iter_all_changes().map(Some).chain([None]) {
|
||||||
if let Some(change) = &change {
|
if let Some(change) = &change {
|
||||||
let len = change.value().len();
|
let len = change.value().len();
|
||||||
match change.tag() {
|
match change.tag() {
|
||||||
ChangeTag::Equal => {
|
ChangeTag::Equal => {
|
||||||
old_offset += len;
|
old_offset += len;
|
||||||
new_offset += len;
|
new_offset += len;
|
||||||
}
|
|
||||||
ChangeTag::Delete => {
|
|
||||||
let old_end_offset = old_offset + len;
|
|
||||||
if let Some((last_old_range, _)) = &mut last_edit {
|
|
||||||
last_old_range.end = old_end_offset;
|
|
||||||
} else {
|
|
||||||
last_edit =
|
|
||||||
Some((old_offset..old_end_offset, new_offset..new_offset));
|
|
||||||
}
|
}
|
||||||
old_offset = old_end_offset;
|
ChangeTag::Delete => {
|
||||||
}
|
let old_end_offset = old_offset + len;
|
||||||
ChangeTag::Insert => {
|
if let Some((last_old_range, _)) = &mut last_edit {
|
||||||
let new_end_offset = new_offset + len;
|
last_old_range.end = old_end_offset;
|
||||||
if let Some((_, last_new_range)) = &mut last_edit {
|
} else {
|
||||||
last_new_range.end = new_end_offset;
|
last_edit =
|
||||||
} else {
|
Some((old_offset..old_end_offset, new_offset..new_offset));
|
||||||
last_edit =
|
}
|
||||||
Some((old_offset..old_offset, new_offset..new_end_offset));
|
old_offset = old_end_offset;
|
||||||
}
|
}
|
||||||
new_offset = new_end_offset;
|
ChangeTag::Insert => {
|
||||||
|
let new_end_offset = new_offset + len;
|
||||||
|
if let Some((_, last_new_range)) = &mut last_edit {
|
||||||
|
last_new_range.end = new_end_offset;
|
||||||
|
} else {
|
||||||
|
last_edit =
|
||||||
|
Some((old_offset..old_offset, new_offset..new_end_offset));
|
||||||
|
}
|
||||||
|
new_offset = new_end_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((old_range, new_range)) = &last_edit {
|
||||||
|
if old_offset > old_range.end
|
||||||
|
|| new_offset > new_range.end
|
||||||
|
|| change.is_none()
|
||||||
|
{
|
||||||
|
let text = if new_range.is_empty() {
|
||||||
|
empty.clone()
|
||||||
|
} else {
|
||||||
|
new_text[new_range.clone()].into()
|
||||||
|
};
|
||||||
|
edits.push((old_range.clone(), text));
|
||||||
|
last_edit.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((old_range, new_range)) = &last_edit {
|
Diff {
|
||||||
if old_offset > old_range.end || new_offset > new_range.end || change.is_none()
|
base_version,
|
||||||
{
|
line_ending,
|
||||||
let text = if new_range.is_empty() {
|
edits,
|
||||||
empty.clone()
|
|
||||||
} else {
|
|
||||||
new_text[new_range.clone()].into()
|
|
||||||
};
|
|
||||||
edits.push((old_range.clone(), text));
|
|
||||||
last_edit.take();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
Diff {
|
|
||||||
base_version,
|
|
||||||
line_ending,
|
|
||||||
edits,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn a background task that searches the buffer for any whitespace
|
/// Spawn a background task that searches the buffer for any whitespace
|
||||||
|
|
Loading…
Reference in a new issue