Add thiserror and improve console output formatting

- Added `thiserror` dependency in `Cargo.toml` and `Cargo.lock` for enhanced error handling.
- Improved execution time tracking and output formatting in `main.rs`.
- Refactored console output in `scan.rs` for better readability with grouped warnings.
- Simplified error handling in `scan_filesystem`.
This commit is contained in:
elipeter 2025-06-23 18:25:10 +02:00
parent 952e83453a
commit 487ccbba8b
5 changed files with 46 additions and 26 deletions

1
Cargo.lock generated
View file

@ -514,6 +514,7 @@ dependencies = [
"rayon", "rayon",
"rusqlite", "rusqlite",
"serde", "serde",
"thiserror",
"toml", "toml",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",

View file

@ -30,3 +30,4 @@ console = "0.15.11"
rayon = "1.10.0" rayon = "1.10.0"
r2d2_sqlite = "0.30.0" r2d2_sqlite = "0.30.0"
r2d2 = "0.8.10" r2d2 = "0.8.10"
thiserror = "2.0.12"

View file

@ -10,7 +10,7 @@ use crate::utils::config::Config;
use crate::utils::query_cache; use crate::utils::query_cache;
use crate::walk::spawn_senders; use crate::walk::spawn_senders;
use rayon::prelude::*; use rayon::prelude::*;
use std::collections::BTreeMap;
use tree_sitter::{Language, Parser, QueryCursor, StreamingIterator}; use tree_sitter::{Language, Parser, QueryCursor, StreamingIterator};
type DynError = Box<dyn std::error::Error + Send + Sync>; type DynError = Box<dyn std::error::Error + Send + Sync>;
@ -37,7 +37,7 @@ pub fn handle(
let (project_name, db_path) = get_project_info(&scan_path, database_dir)?; let (project_name, db_path) = get_project_info(&scan_path, database_dir)?;
let diags: Vec<Diag> = if no_index { let diags: Vec<Diag> = if no_index {
scan_filesystem(&scan_path, config).unwrap() scan_filesystem(&scan_path, config)?
} else { } else {
if rebuild_index || !db_path.exists() { if rebuild_index || !db_path.exists() {
tracing::debug!("Scanning filesystem index filesystem"); tracing::debug!("Scanning filesystem index filesystem");
@ -50,23 +50,36 @@ pub fn handle(
tracing::debug!("Found {:?} issues.", diags.len()); tracing::debug!("Found {:?} issues.", diags.len());
if format == "console" || (format.is_empty() && config.output.default_format == "console") { if format == "console"
|| (format.is_empty() && config.output.default_format == "console")
{
tracing::debug!("Printing to console"); tracing::debug!("Printing to console");
let mut grouped: BTreeMap<&str, Vec<&Diag>> = BTreeMap::new();
for d in &diags { for d in &diags {
let sev_str = match d.severity { grouped.entry(&d.path).or_default().push(d);
Severity::High => style("HIGH").red().bold(),
Severity::Medium => style("MEDIUM").yellow().bold(),
Severity::Low => style("LOW").cyan().bold(),
};
println!(
"{}:{}:{} [{}] {}",
style(d.path.clone()).blue().underlined(),
d.line,
d.col,
sev_str,
style(&d.id).bold(),
);
} }
for (path, issues) in grouped {
println!("{}", style(path).blue().underlined());
for d in issues {
let sev_str = match d.severity {
Severity::High => style("HIGH").red().bold(),
Severity::Medium => style("MEDIUM").yellow().bold(),
Severity::Low => style("LOW").cyan().bold(),
};
println!(
" {:>4}:{:<4} [{}] {}",
d.line, d.col, sev_str, style(&d.id).bold()
);
}
println!();
}
println!("{} '{}' generated {} issues.",
style("warning").yellow().bold(),
style(project_name).white().bold(),
style(diags.len()).bold());
println!("\t"); // TODO: Add individual counts for different warning levels
} }
Ok(()) Ok(())
} }
@ -78,7 +91,7 @@ pub fn handle(
fn scan_filesystem( fn scan_filesystem(
root: &Path, root: &Path,
cfg: &Config, cfg: &Config,
) ->Result<Vec<Diag>, Box<dyn std::error::Error + Send + Sync>> { ) ->Result<Vec<Diag>, Box<dyn std::error::Error>> {
let rx = spawn_senders(root, cfg); let rx = spawn_senders(root, cfg);
let acc = Mutex::new(Vec::new()); let acc = Mutex::new(Vec::new());
@ -87,12 +100,11 @@ fn scan_filesystem(
.par_bridge() .par_bridge()
.try_for_each(|path| { .try_for_each(|path| {
let mut local = run_rules_on_file(&path, cfg).unwrap(); let mut local = run_rules_on_file(&path, cfg).unwrap();
let mut guard = acc.lock().unwrap(); acc.lock().unwrap().append(&mut local);
guard.append(&mut local);
Ok::<(), DynError>(()) Ok::<(), DynError>(())
})?; }).unwrap();
Ok(acc.into_inner().unwrap()) Ok(acc.into_inner()?)
} }
fn scan_with_index_parallel( fn scan_with_index_parallel(

View file

@ -10,7 +10,8 @@ use cli::Cli;
use clap::Parser; use clap::Parser;
use directories::ProjectDirs; use directories::ProjectDirs;
use std::fs; use std::fs;
use std::time::Instant;
use console::style;
use tracing_subscriber::{fmt, EnvFilter, Registry}; use tracing_subscriber::{fmt, EnvFilter, Registry};
use tracing_subscriber::prelude::*; use tracing_subscriber::prelude::*;
use tracing_subscriber::fmt::time; use tracing_subscriber::fmt::time;
@ -39,6 +40,7 @@ fn init_tracing() {
} }
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let now = Instant::now();
init_tracing(); init_tracing();
tracing::debug!("CLI starting up"); tracing::debug!("CLI starting up");
@ -57,6 +59,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
commands::handle_command(cli.command, database_dir, &mut config)?; commands::handle_command(cli.command, database_dir, &mut config)?;
let elapsed = now.elapsed().as_millis();
println!("{} in {} ms.",
style("Finished").green().bold(),
style(elapsed).white().bold());
Ok(()) Ok(())
} }