diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 8882feca3f..300dfc5dd6 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -73,6 +73,7 @@ struct RemoveFile { impl fmt::Debug for AnalysisChange { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("AnalysisChange") + .field("new_roots", &self.new_roots) .field("roots_changed", &self.roots_changed) .field("files_changed", &self.files_changed.len()) .field("libraries_added", &self.libraries_added.len()) diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 7904545d3c..d2f16ea975 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -143,6 +143,7 @@ fn main_loop_inner( } recv(libdata_receiver, data) => Event::Lib(data.unwrap()) }; + log::info!("{:?}", event); let mut state_changed = false; match event { Event::Task(task) => on_task(task, msg_sender, pending_requests), @@ -192,6 +193,9 @@ fn main_loop_inner( sender.send(data); }); } + if state.roots_to_scan == 0 { + feedback(internal_mode, "workspace loaded", msg_sender); + } if state_changed { update_file_notifications_on_threadpool( diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index f2fd09e851..bdb4c513fa 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs @@ -21,6 +21,8 @@ use crate::{ #[derive(Debug)] pub struct ServerWorldState { + pub roots_to_scan: usize, + pub root: PathBuf, pub workspaces: Arc>, pub analysis_host: AnalysisHost, pub vfs: Arc>, @@ -37,12 +39,13 @@ impl ServerWorldState { let mut change = AnalysisChange::new(); let mut roots = Vec::new(); - roots.push(root); + roots.push(root.clone()); for ws in workspaces.iter() { for pkg in ws.packages() { roots.push(pkg.root(&ws).to_path_buf()); } } + let roots_to_scan = roots.len(); let (mut vfs, roots) = Vfs::new(roots); for r in roots { change.add_root(SourceRootId(r.0)); @@ -83,6 +86,8 @@ impl ServerWorldState { let mut analysis_host = AnalysisHost::default(); analysis_host.apply_change(change); ServerWorldState { + roots_to_scan, + root, workspaces: Arc::new(workspaces), analysis_host, vfs: Arc::new(RwLock::new(vfs)), @@ -94,16 +99,29 @@ impl ServerWorldState { pub fn process_changes( &mut self, ) -> Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc)>)> { + let changes = self.vfs.write().commit_changes(); + if changes.is_empty() { + return Vec::new(); + } let mut libs = Vec::new(); let mut change = AnalysisChange::new(); - for c in self.vfs.write().commit_changes() { + for c in changes { + log::info!("vfs change {:?}", c); match c { VfsChange::AddRoot { root, files } => { - let files = files - .into_iter() - .map(|(vfsfile, path, text)| (FileId(vfsfile.0), path, text)) - .collect(); - libs.push((SourceRootId(root.0), files)); + let root_path = self.vfs.read().root2path(root); + if root_path.starts_with(&self.root) { + self.roots_to_scan -= 1; + for (file, path, text) in files { + change.add_file(SourceRootId(root.0), FileId(file.0), path, text); + } + } else { + let files = files + .into_iter() + .map(|(vfsfile, path, text)| (FileId(vfsfile.0), path, text)) + .collect(); + libs.push((SourceRootId(root.0), files)); + } } VfsChange::AddFile { root, @@ -126,6 +144,7 @@ impl ServerWorldState { } pub fn add_lib(&mut self, data: LibraryData) { + self.roots_to_scan -= 1; let mut change = AnalysisChange::new(); change.add_library(data); self.analysis_host.apply_change(change); diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index 26f5e3f200..029a55d402 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -1,9 +1,7 @@ mod support; use serde_json::json; - use ra_lsp_server::req::{Runnables, RunnablesParams, CodeActionRequest, CodeActionParams}; - use languageserver_types::{Position, Range, CodeActionContext}; use crate::support::project; @@ -20,6 +18,7 @@ fn foo() { } ", ); + server.wait_for_feedback("workspace loaded"); server.request::( RunnablesParams { text_document: server.doc_id("lib.rs"), diff --git a/crates/ra_vfs/src/lib.rs b/crates/ra_vfs/src/lib.rs index dc980c3d2a..3a68039f01 100644 --- a/crates/ra_vfs/src/lib.rs +++ b/crates/ra_vfs/src/lib.rs @@ -132,6 +132,7 @@ impl Vfs { roots.sort_by_key(|it| Reverse(it.as_os_str().len())); for (i, path) in roots.iter().enumerate() { let root = res.roots.alloc(RootFilter::new(path.clone())); + res.root2files.insert(root, Default::default()); let nested = roots[..i] .iter() .filter(|it| it.starts_with(path)) @@ -155,6 +156,10 @@ impl Vfs { (res, roots) } + pub fn root2path(&self, root: VfsRoot) -> PathBuf { + self.roots[root].root.clone() + } + pub fn path2file(&self, path: &Path) -> Option { if let Some((_root, _path, Some(file))) = self.find_root(path) { return Some(file); @@ -176,6 +181,23 @@ impl Vfs { } pub fn load(&mut self, path: &Path) -> Option { + if let Some((root, rel_path, file)) = self.find_root(path) { + return if let Some(file) = file { + Some(file) + } else { + let text = fs::read_to_string(path).unwrap_or_default(); + let text = Arc::new(text); + let file = self.add_file(root, rel_path.clone(), Arc::clone(&text)); + let change = VfsChange::AddFile { + file, + text, + root, + path: rel_path, + }; + self.pending_changes.push(change); + Some(file) + }; + } None } @@ -262,10 +284,7 @@ impl Vfs { fn add_file(&mut self, root: VfsRoot, path: RelativePathBuf, text: Arc) -> VfsFile { let data = VfsFileData { root, path, text }; let file = self.files.alloc(data); - self.root2files - .entry(root) - .or_insert_with(FxHashSet::default) - .insert(file); + self.root2files.get_mut(&root).unwrap().insert(file); file }