From a16fda9391f064cf0df9f21b24e99f6323ac0eba Mon Sep 17 00:00:00 2001 From: Viet Dinh <54ckb0y789@gmail.com> Date: Mon, 5 Aug 2024 21:55:03 -0400 Subject: [PATCH] fix: Broken root finder, prevent panics --- src/backend.rs | 4 +++- src/index.rs | 17 ++++++++++++----- src/main.rs | 3 +-- src/utils.rs | 11 ++++++++++- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index f254295..8ac0cc7 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -34,6 +34,7 @@ pub struct Backend { pub record_ranges: DashMap>, pub ast_map: DashMap, pub index: Index, + /// Roots added during initial setup. Not to be confused with [Index::roots]. pub roots: DashSet, pub capabilities: Capabilities, pub root_setup: CondVar, @@ -97,8 +98,9 @@ impl Backend { /// Maximum file line count to process diagnostics each on_change pub const DIAGNOSTICS_LINE_LIMIT: usize = 1200; + #[tracing::instrument(skip_all, ret)] pub fn find_root_of(&self, path: &Path) -> Option { - for root_ in self.roots.iter() { + for root_ in self.index.roots.iter() { if path.starts_with(root_.key()) { return Some(root_.key().to_owned()); } diff --git a/src/index.rs b/src/index.rs index 8fca62b..2614c39 100644 --- a/src/index.rs +++ b/src/index.rs @@ -123,6 +123,7 @@ enum Output { Components(HashMap), } +#[derive(Debug)] pub struct AddRootResults { pub module_count: usize, pub record_count: usize, @@ -138,6 +139,7 @@ impl Index { self.records.retain(|_, record| !record.deleted); info!("(mark_n_sweep) deleted {} records", pre - self.records.len()); } + #[tracing::instrument(skip_all, fields(root=format!("{}", root.display())), ret)] pub async fn add_root( &self, root: &Path, @@ -172,11 +174,16 @@ impl Index { let interner = interner(); let root_key = interner.get_or_intern(root.to_string_lossy()); for manifest in manifests { - let manifest = manifest.into_diagnostic()?; - let module_dir = manifest - .path() - .parent() - .ok_or_else(|| miette::diagnostic!("Unexpected empty path"))?; + let manifest = match manifest { + Ok(manifest) => manifest, + Err(err) => { + warn!(err = %err, "error traversing manifest"); + continue; + } + }; + let Some(module_dir) = manifest.path().parent() else { + continue; + }; fn matched_top_to_bottom(gitignore: &Gitignore, path: &Path) -> bool { let ancestors = path.ancestors().collect::>(); for ancestor in ancestors.into_iter().rev() { diff --git a/src/main.rs b/src/main.rs index 4491c24..96d8506 100644 --- a/src/main.rs +++ b/src/main.rs @@ -181,7 +181,6 @@ impl LanguageServer for Backend { self.capabilities.pull_diagnostics.store(true, Relaxed); } - Ok(InitializeResult { server_info: None, offset_encoding: None, @@ -349,7 +348,7 @@ impl LanguageServer for Backend { .await .unwrap_or(false) { - if let Some(file_path) = path_.parent() { + if let Some(file_path) = path_.parent().and_then(|p| p.parent()) { _ = self .index .add_root(file_path, None, false) diff --git a/src/utils.rs b/src/utils.rs index 6351aaf..fd9c7e5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -346,6 +346,7 @@ impl std::ops::Deref for MaxVec { pub trait TryResultExt { type Result: Sized; + /// Panics if this is [`TryResult::Locked`]. fn expect(self, msg: &str) -> Option; } @@ -370,12 +371,20 @@ pub fn init_for_test() { .init(); } -#[derive(Default)] pub struct CondVar { should_wait: AtomicBool, notifier: tokio::sync::Notify, } +impl Default for CondVar { + fn default() -> Self { + Self { + should_wait: AtomicBool::new(true), + notifier: Default::default(), + } + } +} + pub struct Blocker<'a>(&'a CondVar); impl CondVar {