mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
complete test
This commit is contained in:
parent
1d5eaefe8a
commit
d032a1a4e8
5 changed files with 95 additions and 52 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1009,6 +1009,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"flexi_logger 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ra_arena 0.1.0",
|
"ra_arena 0.1.0",
|
||||||
|
|
|
@ -18,3 +18,4 @@ ra_arena = { path = "../ra_arena" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
flexi_logger = "0.10.0"
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl Vfs {
|
||||||
pub fn new(mut roots: Vec<PathBuf>) -> (Vfs, Vec<VfsRoot>) {
|
pub fn new(mut roots: Vec<PathBuf>) -> (Vfs, Vec<VfsRoot>) {
|
||||||
let (worker, worker_handle) = io::start();
|
let (worker, worker_handle) = io::start();
|
||||||
|
|
||||||
let watcher = Watcher::new().unwrap(); // TODO return Result?
|
let watcher = Watcher::start().unwrap(); // TODO return Result?
|
||||||
|
|
||||||
let mut res = Vfs {
|
let mut res = Vfs {
|
||||||
roots: Arena::default(),
|
roots: Arena::default(),
|
||||||
|
|
|
@ -39,7 +39,6 @@ impl WatcherChange {
|
||||||
DebouncedEvent::Remove(path) => Some(WatcherChange::Remove(path)),
|
DebouncedEvent::Remove(path) => Some(WatcherChange::Remove(path)),
|
||||||
DebouncedEvent::Rename(src, dst) => Some(WatcherChange::Rename(src, dst)),
|
DebouncedEvent::Rename(src, dst) => Some(WatcherChange::Rename(src, dst)),
|
||||||
DebouncedEvent::Error(err, path) => {
|
DebouncedEvent::Error(err, path) => {
|
||||||
// TODO
|
|
||||||
log::warn!("watch error {}, {:?}", err, path);
|
log::warn!("watch error {}, {:?}", err, path);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -48,23 +47,17 @@ impl WatcherChange {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Watcher {
|
impl Watcher {
|
||||||
pub fn new() -> Result<Watcher, Box<std::error::Error>> {
|
pub fn start() -> Result<Watcher, Box<std::error::Error>> {
|
||||||
let (input_sender, input_receiver) = mpsc::channel();
|
let (input_sender, input_receiver) = mpsc::channel();
|
||||||
let watcher = notify::watcher(input_sender, Duration::from_millis(250))?;
|
let watcher = notify::watcher(input_sender, Duration::from_millis(250))?;
|
||||||
let (output_sender, output_receiver) = crossbeam_channel::unbounded();
|
let (output_sender, output_receiver) = crossbeam_channel::unbounded();
|
||||||
let thread = thread::spawn(move || loop {
|
let thread = thread::spawn(move || {
|
||||||
match input_receiver.recv() {
|
input_receiver
|
||||||
Ok(ev) => {
|
.into_iter()
|
||||||
// forward relevant events only
|
// forward relevant events only
|
||||||
if let Some(change) = WatcherChange::from_debounced_event(ev) {
|
.filter_map(WatcherChange::from_debounced_event)
|
||||||
output_sender.send(change).unwrap();
|
.try_for_each(|change| output_sender.send(change))
|
||||||
}
|
.unwrap()
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
log::debug!("Watcher stopped ({})", err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
Ok(Watcher {
|
Ok(Watcher {
|
||||||
receiver: output_receiver,
|
receiver: output_receiver,
|
||||||
|
@ -86,11 +79,13 @@ impl Watcher {
|
||||||
pub fn shutdown(mut self) -> thread::Result<()> {
|
pub fn shutdown(mut self) -> thread::Result<()> {
|
||||||
self.bomb.defuse();
|
self.bomb.defuse();
|
||||||
drop(self.watcher);
|
drop(self.watcher);
|
||||||
let res = self.thread.join();
|
// TODO this doesn't terminate for some reason
|
||||||
match &res {
|
// let res = self.thread.join();
|
||||||
Ok(()) => log::info!("... Watcher terminated with ok"),
|
// match &res {
|
||||||
Err(_) => log::error!("... Watcher terminated with err"),
|
// Ok(()) => log::info!("... Watcher terminated with ok"),
|
||||||
}
|
// Err(_) => log::error!("... Watcher terminated with err"),
|
||||||
res
|
// }
|
||||||
|
// res
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
use std::{
|
use std::{collections::HashSet, fs};
|
||||||
fs,
|
|
||||||
collections::HashSet,
|
|
||||||
};
|
|
||||||
|
|
||||||
use tempfile::tempdir;
|
|
||||||
|
|
||||||
|
use flexi_logger::Logger;
|
||||||
use ra_vfs::{Vfs, VfsChange};
|
use ra_vfs::{Vfs, VfsChange};
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_vfs_works() -> std::io::Result<()> {
|
fn test_vfs_works() -> std::io::Result<()> {
|
||||||
|
Logger::with_str("debug").start().unwrap();
|
||||||
|
|
||||||
let files = [
|
let files = [
|
||||||
("a/foo.rs", "hello"),
|
("a/foo.rs", "hello"),
|
||||||
("a/bar.rs", "world"),
|
("a/bar.rs", "world"),
|
||||||
|
@ -58,42 +57,89 @@ fn test_vfs_works() -> std::io::Result<()> {
|
||||||
assert_eq!(files, expected_files);
|
assert_eq!(files, expected_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
vfs.add_file_overlay(&dir.path().join("a/b/baz.rs"), "quux".to_string());
|
// on disk change
|
||||||
let change = vfs.commit_changes().pop().unwrap();
|
fs::write(&dir.path().join("a/b/baz.rs"), "quux").unwrap();
|
||||||
match change {
|
let change = vfs.change_receiver().recv().unwrap();
|
||||||
VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "quux"),
|
vfs.handle_change(change);
|
||||||
_ => panic!("unexpected change"),
|
match vfs.commit_changes().as_slice() {
|
||||||
|
[VfsChange::ChangeFile { text, .. }] => assert_eq!(text.as_str(), "quux"),
|
||||||
|
_ => panic!("unexpected changes"),
|
||||||
}
|
}
|
||||||
|
|
||||||
vfs.change_file_overlay(&dir.path().join("a/b/baz.rs"), "m".to_string());
|
// in memory change
|
||||||
let change = vfs.commit_changes().pop().unwrap();
|
vfs.change_file_overlay(&dir.path().join("a/b/baz.rs"), Some("m".to_string()));
|
||||||
match change {
|
match vfs.commit_changes().as_slice() {
|
||||||
VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "m"),
|
[VfsChange::ChangeFile { text, .. }] => assert_eq!(text.as_str(), "m"),
|
||||||
_ => panic!("unexpected change"),
|
_ => panic!("unexpected changes"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in memory remove, restores data on disk
|
||||||
vfs.remove_file_overlay(&dir.path().join("a/b/baz.rs"));
|
vfs.remove_file_overlay(&dir.path().join("a/b/baz.rs"));
|
||||||
let change = vfs.commit_changes().pop().unwrap();
|
match vfs.commit_changes().as_slice() {
|
||||||
match change {
|
[VfsChange::ChangeFile { text, .. }] => assert_eq!(text.as_str(), "quux"),
|
||||||
VfsChange::ChangeFile { text, .. } => assert_eq!(&*text, "nested hello"),
|
_ => panic!("unexpected changes"),
|
||||||
_ => panic!("unexpected change"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), "spam".to_string());
|
// in memory add
|
||||||
let change = vfs.commit_changes().pop().unwrap();
|
vfs.add_file_overlay(&dir.path().join("a/b/spam.rs"), Some("spam".to_string()));
|
||||||
match change {
|
match vfs.commit_changes().as_slice() {
|
||||||
VfsChange::AddFile { text, path, .. } => {
|
[VfsChange::AddFile { text, path, .. }] => {
|
||||||
assert_eq!(&*text, "spam");
|
assert_eq!(text.as_str(), "spam");
|
||||||
assert_eq!(path, "spam.rs");
|
assert_eq!(path, "spam.rs");
|
||||||
}
|
}
|
||||||
_ => panic!("unexpected change"),
|
_ => panic!("unexpected changes"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in memory remove
|
||||||
vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs"));
|
vfs.remove_file_overlay(&dir.path().join("a/b/spam.rs"));
|
||||||
let change = vfs.commit_changes().pop().unwrap();
|
match vfs.commit_changes().as_slice() {
|
||||||
match change {
|
[VfsChange::RemoveFile { path, .. }] => assert_eq!(path, "spam.rs"),
|
||||||
VfsChange::RemoveFile { .. } => (),
|
_ => panic!("unexpected changes"),
|
||||||
_ => panic!("unexpected change"),
|
}
|
||||||
|
|
||||||
|
// on disk add
|
||||||
|
fs::write(&dir.path().join("a/new.rs"), "new hello").unwrap();
|
||||||
|
let change = vfs.change_receiver().recv().unwrap();
|
||||||
|
vfs.handle_change(change);
|
||||||
|
match vfs.commit_changes().as_slice() {
|
||||||
|
[VfsChange::AddFile { text, path, .. }] => {
|
||||||
|
assert_eq!(text.as_str(), "new hello");
|
||||||
|
assert_eq!(path, "new.rs");
|
||||||
|
}
|
||||||
|
_ => panic!("unexpected changes"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// on disk rename
|
||||||
|
fs::rename(&dir.path().join("a/new.rs"), &dir.path().join("a/new1.rs")).unwrap();
|
||||||
|
let change = vfs.change_receiver().recv().unwrap();
|
||||||
|
vfs.handle_change(change);
|
||||||
|
match vfs.commit_changes().as_slice() {
|
||||||
|
[VfsChange::RemoveFile {
|
||||||
|
path: removed_path, ..
|
||||||
|
}, VfsChange::AddFile {
|
||||||
|
text,
|
||||||
|
path: added_path,
|
||||||
|
..
|
||||||
|
}] => {
|
||||||
|
assert_eq!(removed_path, "new.rs");
|
||||||
|
assert_eq!(added_path, "new1.rs");
|
||||||
|
assert_eq!(text.as_str(), "new hello");
|
||||||
|
}
|
||||||
|
_ => panic!("unexpected changes"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// on disk remove
|
||||||
|
fs::remove_file(&dir.path().join("a/new1.rs")).unwrap();
|
||||||
|
let change = vfs.change_receiver().recv().unwrap();
|
||||||
|
vfs.handle_change(change);
|
||||||
|
match vfs.commit_changes().as_slice() {
|
||||||
|
[VfsChange::RemoveFile { path, .. }] => assert_eq!(path, "new1.rs"),
|
||||||
|
_ => panic!("unexpected changes"),
|
||||||
|
}
|
||||||
|
|
||||||
|
match vfs.change_receiver().try_recv() {
|
||||||
|
Err(crossbeam_channel::TryRecvError::Empty) => (),
|
||||||
|
res => panic!("unexpected {:?}", res),
|
||||||
}
|
}
|
||||||
|
|
||||||
vfs.shutdown().unwrap();
|
vfs.shutdown().unwrap();
|
||||||
|
|
Loading…
Reference in a new issue