Detailed changes
@@ -102,15 +102,19 @@ dependencies = [
"anyhow",
"chrono",
"collections",
+ "ctor",
"editor",
+ "env_logger 0.9.3",
"fs",
"futures 0.3.28",
"gpui",
"indoc",
"isahc",
"language",
+ "log",
"menu",
"project",
+ "rand 0.8.5",
"regex",
"schemars",
"search",
@@ -37,3 +37,8 @@ tiktoken-rs = "0.4"
[dev-dependencies]
editor = { path = "../editor", features = ["test-support"] }
project = { path = "../project", features = ["test-support"] }
+
+ctor.workspace = true
+env_logger.workspace = true
+log.workspace = true
+rand.workspace = true
@@ -283,3 +283,11 @@ pub async fn stream_completion(
}
}
}
+
+#[cfg(test)]
+#[ctor::ctor]
+fn init_logger() {
+ if std::env::var("RUST_LOG").is_ok() {
+ env_logger::init();
+ }
+}
@@ -204,14 +204,67 @@ impl Diff {
#[cfg(test)]
mod tests {
+ use std::env;
+
use super::*;
+ use rand::prelude::*;
+
+ #[gpui::test(iterations = 100)]
+ fn test_random_diffs(mut rng: StdRng) {
+ let old_text_len = env::var("OLD_TEXT_LEN")
+ .map(|i| i.parse().expect("invalid `OLD_TEXT_LEN` variable"))
+ .unwrap_or(10);
+ let new_text_len = env::var("NEW_TEXT_LEN")
+ .map(|i| i.parse().expect("invalid `NEW_TEXT_LEN` variable"))
+ .unwrap_or(10);
+
+ let old = util::RandomCharIter::new(&mut rng)
+ .take(old_text_len)
+ .collect::<String>();
+ log::info!("old text: {:?}", old);
+
+ let mut diff = Diff::new(old.clone());
+ let mut hunks = Vec::new();
+ let mut new_len = 0;
+ let mut new = String::new();
+ while new_len < new_text_len {
+ let new_chunk_len = rng.gen_range(1..=new_text_len - new_len);
+ let new_chunk = util::RandomCharIter::new(&mut rng)
+ .take(new_len)
+ .collect::<String>();
+ log::info!("new chunk: {:?}", new_chunk);
+ new_len += new_chunk_len;
+ new.push_str(&new_chunk);
+ let new_hunks = diff.push_new(&new_chunk);
+ log::info!("hunks: {:?}", new_hunks);
+ hunks.extend(new_hunks);
+ }
+ let final_hunks = diff.finish();
+ log::info!("final hunks: {:?}", final_hunks);
+ hunks.extend(final_hunks);
- #[test]
- fn test_diff() {
- let mut diff = Diff::new("hello world".to_string());
- dbg!(diff.push_new("hello"));
- dbg!(diff.push_new(" ciaone"));
- // dbg!(diff.push_new(" world"));
- dbg!(diff.finish());
+ log::info!("new text: {:?}", new);
+ let mut old_ix = 0;
+ let mut new_ix = 0;
+ let mut patched = String::new();
+ for hunk in hunks {
+ match hunk {
+ Hunk::Keep { len } => {
+ assert_eq!(&old[old_ix..old_ix + len], &new[new_ix..new_ix + len]);
+ patched.push_str(&old[old_ix..old_ix + len]);
+ old_ix += len;
+ new_ix += len;
+ }
+ Hunk::Remove { len } => {
+ old_ix += len;
+ }
+ Hunk::Insert { text } => {
+ assert_eq!(text, &new[new_ix..new_ix + text.len()]);
+ patched.push_str(&text);
+ new_ix += text.len();
+ }
+ }
+ }
+ assert_eq!(patched, new);
}
}
@@ -78,15 +78,14 @@ impl RefactoringAssistant {
}
let hunks = diff.push_new(&new_text);
- hunks_tx.send((hunks, new_text)).await?;
+ hunks_tx.send(hunks).await?;
}
-
- hunks_tx.send((diff.finish(), String::new())).await?;
+ hunks_tx.send(diff.finish()).await?;
anyhow::Ok(())
});
- while let Some((hunks, new_text)) = hunks_rx.next().await {
+ while let Some(hunks) = hunks_rx.next().await {
editor.update(&mut cx, |editor, cx| {
editor.buffer().update(cx, |buffer, cx| {
buffer.start_transaction(cx);