Add error handling with NyxError and refactor console output formatting

- Introduced `NyxError` and `NyxResult` for unified error handling across modules.
- Refactored `scan.rs`, `index.rs`, and `walk.rs` with improved error management and consistent formatting.
- Replaced existing error handling in `database.rs` with `NyxResult`.
- Improved database maintenance by integrating `vacuum` and `clear` methods into workflows.
- Added `dashmap` for efficient parallel diagnostics result aggregation in `scan_with_index_parallel`.
- Enhanced readability and formatting of console outputs in multiple modules.
This commit is contained in:
elipeter 2025-06-23 20:27:16 +02:00
parent 75a20eaa2a
commit 0a66a0ae2d
14 changed files with 360 additions and 240 deletions

15
src/utils/ext.rs Normal file
View file

@ -0,0 +1,15 @@
pub fn lowercase_ext(path: &std::path::Path) -> Option<&'static str> {
path.extension()
.and_then(|s| match s.to_str()? {
"rs" | "RS" => Some("rs"),
"c" => Some("c"),
"cpp" | "c++" => Some("cpp"),
"java" => Some("java"),
"go" => Some("go"),
"php" => Some("php"),
"py" | "PY" => Some("py"),
"ts" | "TSX" | "tsx" => Some("ts"),
"js" => Some("js"),
_ => None,
})
}

View file

@ -1,6 +1,7 @@
pub mod project;
pub mod config;
pub(crate) mod query_cache;
pub(crate) mod ext;
// Re-export commonly used functions for convenience
pub use project::{get_project_info};

View file

@ -1,27 +1,30 @@
use std::path::{Path, PathBuf};
use crate::errors::{NyxError, NyxResult};
/// Determine `<project-name, path/to/<project>.sqlite>`.
pub fn get_project_info(
project_path: &Path,
config_dir: &Path,
) -> Result<(String, PathBuf), Box<dyn std::error::Error>> {
project_path: &Path,
config_dir: &Path,
) -> NyxResult<(String, PathBuf)> {
let project_name = project_path
.file_name()
.and_then(|name| name.to_str())
.ok_or("Unable to determine project name")?;
.and_then(|n| n.to_str())
.ok_or_else(|| NyxError::Other("Unable to determine project name".into()))?;
let db_name = sanitize_project_name(project_name);
let db_path = config_dir.join(format!("{}.sqlite", db_name));
Ok((project_name.to_string(), db_path))
Ok((project_name.to_owned(), db_path))
}
pub fn sanitize_project_name(name: &str) -> String {
pub fn sanitize_project_name(name: &str) -> String {
name.to_lowercase()
.chars()
.map(|c| match c {
' ' | '\t' | '\n' | '\r' => '_',
c if c.is_alphanumeric() || c == '_' || c == '-' => c,
_ => '_'
.map(|c| match c {
' ' | '\t' | '\n' | '\r' => '_',
c if c.is_alphanumeric() || c == '_' || c == '-' => c,
_ => '_',
})
.collect::<String>()
.split('_')

View file

@ -1,5 +1,5 @@
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::sync::RwLock;
use once_cell::sync::Lazy;
use tree_sitter::{Language, Query};
@ -8,30 +8,36 @@ use crate::patterns::{self, Pattern};
#[derive(Clone)]
pub struct CompiledQuery {
pub meta: Pattern,
pub query: Arc<Query>,
pub meta: Pattern,
pub query: std::sync::Arc<Query>,
}
static CACHE: Lazy<RwLock<HashMap<&'static str, Vec<CompiledQuery>>>> =
static CACHE: Lazy<RwLock<HashMap<&'static str, std::sync::Arc<Vec<CompiledQuery>>>>> =
Lazy::new(|| RwLock::new(HashMap::new()));
pub fn for_lang(lang: &'static str, ts_lang: Language) -> Vec<CompiledQuery> {
// fast-path read
/// Return **one shared Arc** to the per-language query set.
/// Cloning the `Arc` is O(1) and the underlying Vec lives for the
/// lifetime of the process.
pub fn for_lang(lang: &'static str, ts_lang: Language) -> std::sync::Arc<Vec<CompiledQuery>> {
// fast path
if let Some(v) = CACHE.read().unwrap().get(lang) {
return v.clone();
}
// compile under write-lock exactly once
let patterns = patterns::load(lang);
let mut vec = Vec::with_capacity(patterns.len());
for p in patterns {
// slow path — compile
let patterns = patterns::load(lang);
let compiled: Vec<_> = patterns.into_iter().filter_map(|p| {
match Query::new(&ts_lang, p.query) {
Ok(q) => vec.push(CompiledQuery { meta: p, query: Arc::new(q) }),
Err(e) => tracing::warn!(lang, id = p.id, "query compile error: {e}"),
Ok(q) => Some(CompiledQuery { meta: p, query: std::sync::Arc::new(q) }),
Err(e)=> {
tracing::warn!(lang, id = p.id, "query compile error: {e}");
None
}
}
}
}).collect();
CACHE.write().unwrap().insert(lang, vec.clone());
vec
let compiled = std::sync::Arc::new(compiled);
let mut w = CACHE.write().unwrap();
w.entry(lang).or_insert_with(|| compiled.clone()).clone()
}