From ee4d904cfb1b604bc8627491e05980ac43cd59e3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 25 Oct 2018 10:57:55 +0300 Subject: Store all the data in the Salsa Database --- crates/ra_lsp_server/src/path_map.rs | 13 +++--- crates/ra_lsp_server/src/server_world.rs | 70 ++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 27 deletions(-) (limited to 'crates/ra_lsp_server/src') diff --git a/crates/ra_lsp_server/src/path_map.rs b/crates/ra_lsp_server/src/path_map.rs index d32829382..b3d1dc3db 100644 --- a/crates/ra_lsp_server/src/path_map.rs +++ b/crates/ra_lsp_server/src/path_map.rs @@ -22,15 +22,18 @@ impl PathMap { pub fn new() -> PathMap { Default::default() } - pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> FileId { - self.path2id + pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> (bool, FileId) { + let mut inserted = false; + let file_id = self.path2id .get(path.as_path()) .map(|&id| id) .unwrap_or_else(|| { + inserted = true; let id = self.new_file_id(); self.insert(path, id, root); id - }) + }); + (inserted, file_id) } pub fn get_id(&self, path: &Path) -> Option { self.path2id.get(path).map(|&id| id) @@ -105,8 +108,8 @@ mod test { #[test] fn test_resolve() { let mut m = PathMap::new(); - let id1 = m.get_or_insert(PathBuf::from("/foo"), Root::Workspace); - let id2 = m.get_or_insert(PathBuf::from("/foo/bar.rs"), Root::Workspace); + let (_, id1) = m.get_or_insert(PathBuf::from("/foo"), Root::Workspace); + let (_, id2) = m.get_or_insert(PathBuf::from("/foo/bar.rs"), Root::Workspace); assert_eq!(m.resolve(id1, &RelativePath::new("bar.rs")), Some(id2),) } } diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 69b2a1cd1..555de66ff 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs @@ -2,10 +2,11 @@ use std::{ fs, path::{Path, PathBuf}, sync::Arc, + collections::BTreeMap, }; use languageserver_types::Url; -use ra_analysis::{Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, LibraryData}; +use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, CrateId, FileId, FileResolver, LibraryData}; use rustc_hash::FxHashMap; use crate::{ @@ -39,30 +40,40 @@ impl ServerWorldState { } } pub fn apply_fs_changes(&mut self, events: Vec) { + let mut change = AnalysisChange::new(); + let mut inserted = false; { let pm = &mut self.path_map; let mm = &mut self.mem_map; - let changes = events + events .into_iter() .map(|event| { let text = match event.kind { - FileEventKind::Add(text) => Some(text), + FileEventKind::Add(text) => text, }; (event.path, text) }) - .map(|(path, text)| (pm.get_or_insert(path, Root::Workspace), text)) - .filter_map(|(id, text)| { - if mm.contains_key(&id) { - mm.insert(id, text); + .map(|(path, text)| { + let (ins, file_id) = pm.get_or_insert(path, Root::Workspace); + inserted |= ins; + (file_id, text) + }) + .filter_map(|(file_id, text)| { + if mm.contains_key(&file_id) { + mm.insert(file_id, Some(text)); None } else { - Some((id, text)) + Some((file_id, text)) } + }) + .for_each(|(file_id, text)| { + change.add_file(file_id, text) }); - self.analysis_host.change_files(changes); } - self.analysis_host - .set_file_resolver(Arc::new(self.path_map.clone())); + if inserted { + change.set_file_resolver(Arc::new(self.path_map.clone())) + } + self.analysis_host.apply_change(change); } pub fn events_to_files( &mut self, @@ -76,24 +87,31 @@ impl ServerWorldState { let FileEventKind::Add(text) = event.kind; (event.path, text) }) - .map(|(path, text)| (pm.get_or_insert(path, Root::Lib), text)) + .map(|(path, text)| (pm.get_or_insert(path, Root::Lib).1, text)) .collect() }; let resolver = Arc::new(self.path_map.clone()); (files, resolver) } pub fn add_lib(&mut self, data: LibraryData) { - self.analysis_host.add_library(data); + let mut change = AnalysisChange::new(); + change.add_library(data); + self.analysis_host.apply_change(change); } pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId { - let file_id = self.path_map.get_or_insert(path, Root::Workspace); - self.analysis_host - .set_file_resolver(Arc::new(self.path_map.clone())); - self.mem_map.insert(file_id, None); + let (inserted, file_id) = self.path_map.get_or_insert(path, Root::Workspace); if self.path_map.get_root(file_id) != Root::Lib { - self.analysis_host.change_file(file_id, Some(text)); + let mut change = AnalysisChange::new(); + if inserted { + change.add_file(file_id, text); + change.set_file_resolver(Arc::new(self.path_map.clone())); + } else { + change.change_file(file_id, text); + } + self.analysis_host.apply_change(change); } + self.mem_map.insert(file_id, None); file_id } @@ -103,7 +121,9 @@ impl ServerWorldState { .get_id(path) .ok_or_else(|| format_err!("change to unknown file: {}", path.display()))?; if self.path_map.get_root(file_id) != Root::Lib { - self.analysis_host.change_file(file_id, Some(text)); + let mut change = AnalysisChange::new(); + change.change_file(file_id, text); + self.analysis_host.apply_change(change); } Ok(()) } @@ -120,12 +140,16 @@ impl ServerWorldState { // Do this via file watcher ideally. let text = fs::read_to_string(path).ok(); if self.path_map.get_root(file_id) != Root::Lib { - self.analysis_host.change_file(file_id, text); + let mut change = AnalysisChange::new(); + if let Some(text) = text { + change.change_file(file_id, text); + } + self.analysis_host.apply_change(change); } Ok(file_id) } pub fn set_workspaces(&mut self, ws: Vec) { - let mut crate_roots = FxHashMap::default(); + let mut crate_roots = BTreeMap::default(); ws.iter() .flat_map(|ws| { ws.packages() @@ -140,7 +164,9 @@ impl ServerWorldState { }); let crate_graph = CrateGraph { crate_roots }; self.workspaces = Arc::new(ws); - self.analysis_host.set_crate_graph(crate_graph); + let mut change = AnalysisChange::new(); + change.set_crate_graph(crate_graph); + self.analysis_host.apply_change(change); } pub fn snapshot(&self) -> ServerWorld { ServerWorld { -- cgit v1.2.3 From 56df0fc83c753b7fb8829438c8d3017ef1bf450c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 25 Oct 2018 16:03:49 +0300 Subject: Improve logging --- crates/ra_lsp_server/src/main_loop/mod.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'crates/ra_lsp_server/src') diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index e681062ca..9ddc3fd0b 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs @@ -8,7 +8,7 @@ use gen_lsp_server::{ handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, }; use languageserver_types::NumberOrString; -use ra_analysis::{FileId, LibraryData}; +use ra_analysis::{Canceled, FileId, LibraryData}; use rayon::{self, ThreadPool}; use rustc_hash::FxHashSet; use serde::{de::DeserializeOwned, Serialize}; @@ -376,7 +376,7 @@ impl<'a> PoolDispatcher<'a> { Err(e) => { match e.downcast::() { Ok(lsp_error) => RawResponse::err(id, lsp_error.code, lsp_error.message), - Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string()) + Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, format!("{}\n{}", e, e.backtrace())) } } }; @@ -408,14 +408,22 @@ fn update_file_notifications_on_threadpool( pool.spawn(move || { for file_id in subscriptions { match handlers::publish_diagnostics(&world, file_id) { - Err(e) => error!("failed to compute diagnostics: {:?}", e), + Err(e) => { + if !is_canceled(&e) { + error!("failed to compute diagnostics: {:?}", e); + } + }, Ok(params) => { let not = RawNotification::new::(¶ms); sender.send(Task::Notify(not)); } } match handlers::publish_decorations(&world, file_id) { - Err(e) => error!("failed to compute decorations: {:?}", e), + Err(e) => { + if !is_canceled(&e) { + error!("failed to compute decorations: {:?}", e); + } + }, Ok(params) => { let not = RawNotification::new::(¶ms); sender.send(Task::Notify(not)) @@ -432,3 +440,7 @@ fn feedback(intrnal_mode: bool, msg: &str, sender: &Sender) { let not = RawNotification::new::(&msg.to_string()); sender.send(RawMessage::Notification(not)); } + +fn is_canceled(e: &failure::Error) -> bool { + e.downcast_ref::().is_some() +} -- cgit v1.2.3 From 772acb53f2d7568ff1cc2ba4ca84a47110f13b3a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 25 Oct 2018 16:25:24 +0300 Subject: use correct file when resolving callables --- crates/ra_lsp_server/src/path_map.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'crates/ra_lsp_server/src') diff --git a/crates/ra_lsp_server/src/path_map.rs b/crates/ra_lsp_server/src/path_map.rs index b3d1dc3db..d5957d673 100644 --- a/crates/ra_lsp_server/src/path_map.rs +++ b/crates/ra_lsp_server/src/path_map.rs @@ -1,4 +1,7 @@ -use std::path::{Component, Path, PathBuf}; +use std::{ + fmt, + path::{Component, Path, PathBuf}, +}; use im; use ra_analysis::{FileId, FileResolver}; @@ -10,7 +13,7 @@ pub enum Root { Lib, } -#[derive(Debug, Default, Clone)] +#[derive(Default, Clone)] pub struct PathMap { next_id: u32, path2id: im::HashMap, @@ -18,6 +21,12 @@ pub struct PathMap { id2root: im::HashMap, } +impl fmt::Debug for PathMap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("PathMap { ... }") + } +} + impl PathMap { pub fn new() -> PathMap { Default::default() -- cgit v1.2.3 From e0eb33605a917d2e7289debe0c915e75286b834f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 25 Oct 2018 17:40:24 +0300 Subject: Encapsulate CrateGraph a bit --- crates/ra_lsp_server/src/server_world.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'crates/ra_lsp_server/src') diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 555de66ff..25986e230 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs @@ -2,11 +2,10 @@ use std::{ fs, path::{Path, PathBuf}, sync::Arc, - collections::BTreeMap, }; use languageserver_types::Url; -use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, CrateId, FileId, FileResolver, LibraryData}; +use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, FileId, FileResolver, LibraryData}; use rustc_hash::FxHashMap; use crate::{ @@ -149,7 +148,7 @@ impl ServerWorldState { Ok(file_id) } pub fn set_workspaces(&mut self, ws: Vec) { - let mut crate_roots = BTreeMap::default(); + let mut crate_graph = CrateGraph::new(); ws.iter() .flat_map(|ws| { ws.packages() @@ -158,11 +157,9 @@ impl ServerWorldState { }) .for_each(|root| { if let Some(file_id) = self.path_map.get_id(root) { - let crate_id = CrateId(crate_roots.len() as u32); - crate_roots.insert(crate_id, file_id); + crate_graph.add_crate_root(file_id); } }); - let crate_graph = CrateGraph { crate_roots }; self.workspaces = Arc::new(ws); let mut change = AnalysisChange::new(); change.set_crate_graph(crate_graph); -- cgit v1.2.3