Refactor codebase for consistent indentation and formatting

- Standardized spacing and indentation across multiple modules for improved readability.
- Reorganized `patterns` and `utils` imports for consistency.
- Updated `NyxError` and `NyxResult` related implementations to maintain consistent formatting.
- Enhanced readability in AST patterns for better clarity and maintainability.
This commit is contained in:
elipeter 2025-06-24 20:27:06 +02:00
parent b3870997d7
commit 14a549ac39
26 changed files with 1314 additions and 1221 deletions

View file

@ -1,13 +1,9 @@
use std::{env, fs};
use console::style;
use crate::errors::NyxResult;
use crate::utils::get_project_info;
use console::style;
use std::{env, fs};
pub fn handle(
project: Option<String>,
all: bool,
config_dir: &std::path::Path,
) -> NyxResult<()> {
pub fn handle(project: Option<String>, all: bool, config_dir: &std::path::Path) -> NyxResult<()> {
if all {
println!("{}", style("Cleaning all indexes...").cyan().bold());
if config_dir.exists() {
@ -19,9 +15,17 @@ pub fn handle(
let db_path = config_dir.join(format!("{}.sqlite", proj_name));
if db_path.exists() {
fs::remove_file(&db_path)?;
println!("{} {}", style("✔ Cleaned index for").green(), style(&proj_name).white().bold());
println!(
"{} {}",
style("✔ Cleaned index for").green(),
style(&proj_name).white().bold()
);
} else {
println!("{} {}", style("✖ No index found for").red(), style(&proj_name).white().bold());
println!(
"{} {}",
style("✖ No index found for").red(),
style(&proj_name).white().bold()
);
}
} else {
let current_dir = env::current_dir()?;
@ -29,11 +33,19 @@ pub fn handle(
if db_path.exists() {
fs::remove_file(&db_path)?;
println!("{} {}", style("✔ Cleaned index for").green(), style(&project_name).white().bold());
println!(
"{} {}",
style("✔ Cleaned index for").green(),
style(&project_name).white().bold()
);
} else {
println!("{} {}", style("✖ No index found for current project").red(), style(&project_name).white().bold());
println!(
"{} {}",
style("✖ No index found for current project").red(),
style(&project_name).white().bold()
);
}
}
std::process::exit(0);
}
}

View file

@ -1,16 +1,16 @@
use std::fs;
use std::process::exit;
use bytesize::ByteSize;
use chrono::{DateTime, Local};
use console::style;
use crate::cli::IndexAction;
use crate::database::index::{Indexer, IssueRow};
use crate::errors::NyxResult;
use crate::patterns::Severity;
use crate::utils::Config;
use crate::utils::project::get_project_info;
use crate::walk::spawn_senders;
use bytesize::ByteSize;
use chrono::{DateTime, Local};
use console::style;
use rayon::prelude::*;
use crate::errors::NyxResult;
use std::fs;
use std::process::exit;
pub fn handle(
action: IndexAction,
@ -24,10 +24,18 @@ pub fn handle(
if force || !db_path.exists() {
build_index(&project_name, &build_path, &db_path, config)?;
println!("{} {}", style("Index built:" ).green(), style(db_path.display()).white().bold());
println!(
"✔ {} {}",
style("Index built:").green(),
style(db_path.display()).white().bold()
);
exit(0);
} else {
println!("{} {}", style("↩ Index already exists").yellow(), style("(use --force to rebuild)").dim());
println!(
"{} {}",
style("↩ Index already exists").yellow(),
style("(use --force to rebuild)").dim()
);
exit(0);
}
}
@ -36,18 +44,34 @@ pub fn handle(
let (project_name, db_path) = get_project_info(&status_path, database_dir)?;
println!("{}", style("Project status").blue().bold().underlined());
println!(" {:14} {}", style("Project"), style(&project_name).white().bold());
println!(" {:14} {}", style("Index path"), style(db_path.display()).underlined());
println!(" {:14} {}", style("Exists"), style(db_path.exists()).bold());
println!(
" {:14} {}",
style("Project"),
style(&project_name).white().bold()
);
println!(
" {:14} {}",
style("Index path"),
style(db_path.display()).underlined()
);
println!(
" {:14} {}",
style("Exists"),
style(db_path.exists()).bold()
);
if db_path.exists() {
let meta = fs::metadata(&db_path)?;
let size = ByteSize::b(meta.len());
let mtime: DateTime<Local> = meta.modified()?.into();
println!(" {:14} {}", style("Size"), size);
println!(" {:14} {}", style("Modified"), mtime.format("%Y-%m-%d %H:%M:%S"));
println!(" {:14} {}", style("Size"), size);
println!(
" {:14} {}",
style("Modified"),
mtime.format("%Y-%m-%d %H:%M:%S")
);
}
exit(0);
}
}
@ -61,7 +85,7 @@ pub fn build_index(
) -> NyxResult<()> {
tracing::debug!("Building index for: {}", project_name);
fs::File::create(db_path)?;
let pool = Indexer::init(db_path)?;
{
let idx = Indexer::from_pool(project_name, &pool)?;
@ -69,34 +93,39 @@ pub fn build_index(
}
tracing::debug!("Cleaned index for: {}", project_name);
let rx = spawn_senders(project_path, config);
let paths: Vec<_> = rx.into_iter().flatten().collect();
paths.into_par_iter().try_for_each(|path| -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let issues = crate::commands::scan::run_rules_on_file(&path, config)?;
let mut idx = Indexer::from_pool(project_name, &pool)?;
let file_id = idx.upsert_file(&path)?;
let rows: Vec<IssueRow> = issues.iter().map(|d| IssueRow {
rule_id: d.id.as_ref(),
severity: match d.severity {
Severity::High => "HIGH",
Severity::Medium => "MEDIUM",
Severity::Low => "LOW",
},
line: d.line as i64,
col: d.col as i64,
}).collect();
idx.replace_issues(file_id, rows)?;
Ok(())
})?;
paths.into_par_iter().try_for_each(
|path| -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let issues = crate::commands::scan::run_rules_on_file(&path, config)?;
let mut idx = Indexer::from_pool(project_name, &pool)?;
let file_id = idx.upsert_file(&path)?;
let rows: Vec<IssueRow> = issues
.iter()
.map(|d| IssueRow {
rule_id: d.id.as_ref(),
severity: match d.severity {
Severity::High => "HIGH",
Severity::Medium => "MEDIUM",
Severity::Low => "LOW",
},
line: d.line as i64,
col: d.col as i64,
})
.collect();
idx.replace_issues(file_id, rows)?;
Ok(())
},
)?;
{
let idx = Indexer::from_pool(project_name, &pool)?;
idx.vacuum()?;
}
Ok(())
}
}

View file

@ -1,13 +1,10 @@
use std::fs;
use crate::errors::NyxResult;
use bytesize::ByteSize;
use chrono::{DateTime, Local};
use console::style;
use crate::errors::NyxResult;
use std::fs;
pub fn handle(
verbose: bool,
database_dir: &std::path::Path,
) -> NyxResult<()> {
pub fn handle(verbose: bool, database_dir: &std::path::Path) -> NyxResult<()> {
println!("{}", style("Indexed projects").blue().bold().underlined());
if !database_dir.exists() {
@ -21,18 +18,29 @@ pub fn handle(
continue;
}
let name = path.file_stem().and_then(|s| s.to_str()).unwrap_or("unknown");
let name = path
.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("unknown");
println!(" {}", style(name).white().bold());
if verbose {
let meta = fs::metadata(&path)?;
let size = ByteSize::b(meta.len());
let mtime: DateTime<Local> = meta.modified()?.into();
println!(" {:10} {}", style("Path"), style(path.display()).underlined());
println!(" {:10} {}", style("Size"), size);
println!(" {:10} {}", style("Modified"), mtime.format("%Y-%m-%d %H:%M:%S"));
println!(
" {:10} {}",
style("Path"),
style(path.display()).underlined()
);
println!(" {:10} {}", style("Size"), size);
println!(
" {:10} {}",
style("Modified"),
mtime.format("%Y-%m-%d %H:%M:%S")
);
}
}
std::process::exit(0);
}
}

View file

@ -1,33 +1,35 @@
pub mod scan;
pub mod clean;
pub mod index;
pub mod list;
pub mod clean;
pub mod scan;
use crate::cli::Commands;
use std::path::Path;
use crate::errors::NyxResult;
use crate::patterns::Severity;
use crate::utils::config::Config;
use std::path::Path;
pub fn handle_command(
command: Commands,
database_dir: &Path,
config: &mut Config
config: &mut Config,
) -> NyxResult<()> {
match command {
Commands::Scan { path, no_index, rebuild_index, format, high_only } => {
if high_only { config.scanner.min_severity = Severity::High };
Commands::Scan {
path,
no_index,
rebuild_index,
format,
high_only,
} => {
if high_only {
config.scanner.min_severity = Severity::High
};
scan::handle(&path, no_index, rebuild_index, format, database_dir, config)
}
Commands::Index { action } => {
index::handle(action, database_dir, config)
}
Commands::List { verbose } => {
list::handle(verbose, database_dir)
}
Commands::Clean { project, all } => {
clean::handle(project, all, database_dir)
}
Commands::Index { action } => index::handle(action, database_dir, config),
Commands::List { verbose } => list::handle(verbose, database_dir),
Commands::Clean { project, all } => clean::handle(project, all, database_dir),
}
}
}

View file

@ -1,18 +1,18 @@
use crate::utils::project::get_project_info;
use console::style;
use std::path::Path;
use std::sync::{Arc, Mutex};
use r2d2::Pool;
use r2d2_sqlite::SqliteConnectionManager;
use crate::database::index::{IssueRow, Indexer};
pub(crate) use crate::ast::run_rules_on_file;
use crate::database::index::{Indexer, IssueRow};
use crate::errors::NyxResult;
use crate::patterns::Severity;
use crate::utils::config::Config;
use crate::utils::project::get_project_info;
use crate::walk::spawn_senders;
use console::style;
use dashmap::DashMap;
use r2d2::Pool;
use r2d2_sqlite::SqliteConnectionManager;
use rayon::prelude::*;
use std::collections::BTreeMap;
use dashmap::DashMap;
use crate::errors::NyxResult;
pub(crate) use crate::ast::run_rules_on_file;
use std::path::Path;
use std::sync::{Arc, Mutex};
type DynError = Box<dyn std::error::Error + Send + Sync>;
@ -37,14 +37,18 @@ pub fn handle(
let scan_path = Path::new(path).canonicalize()?;
let (project_name, db_path) = get_project_info(&scan_path, database_dir)?;
println!("{} {}...\n", style("Checking").green().bold(), &project_name);
println!(
"{} {}...\n",
style("Checking").green().bold(),
&project_name
);
let diags: Vec<Diag> = if no_index {
scan_filesystem(&scan_path, config)?
} else {
if rebuild_index || !db_path.exists() {
tracing::debug!("Scanning filesystem index filesystem");
crate::commands::index::build_index(&project_name,&scan_path, &db_path, config)?;
crate::commands::index::build_index(&project_name, &scan_path, &db_path, config)?;
}
let pool = Indexer::init(&db_path)?;
@ -53,9 +57,7 @@ pub fn handle(
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");
let mut grouped: BTreeMap<&str, Vec<&Diag>> = BTreeMap::new();
for d in &diags {
@ -65,16 +67,23 @@ pub fn handle(
for (path, issues) in &grouped {
println!("{}", style(path).blue().underlined());
for d in issues {
println!(" {:>4}:{:<4} [{}] {}",
d.line, d.col, d.severity, style(&d.id).bold());
println!(
" {:>4}:{:<4} [{}] {}",
d.line,
d.col,
d.severity,
style(&d.id).bold()
);
}
println!();
}
println!("{} '{}' generated {} issues.",
style("warning").yellow().bold(),
style(project_name).white().bold(),
style(diags.len()).bold());
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(())
@ -84,22 +93,16 @@ pub fn handle(
// Scanning helpers
// --------------------------------------------------------------------------------------------
fn scan_filesystem(
root: &Path,
cfg: &Config,
) -> NyxResult<Vec<Diag>> {
fn scan_filesystem(root: &Path, cfg: &Config) -> NyxResult<Vec<Diag>> {
let rx = spawn_senders(root, cfg);
let acc = Mutex::new(Vec::new());
rx.into_iter()
.flatten()
.par_bridge()
.try_for_each(|path| {
let mut local = run_rules_on_file(&path, cfg)?;
acc.lock().unwrap().append(&mut local);
Ok::<(), DynError>(())
})?;
rx.into_iter().flatten().par_bridge().try_for_each(|path| {
let mut local = run_rules_on_file(&path, cfg)?;
acc.lock().unwrap().append(&mut local);
Ok::<(), DynError>(())
})?;
Ok(acc.into_inner()?)
}
@ -108,7 +111,6 @@ pub fn scan_with_index_parallel(
pool: Arc<Pool<SqliteConnectionManager>>,
cfg: &Config,
) -> NyxResult<Vec<Diag>> {
let files = {
let idx = Indexer::from_pool(project, &pool)?;
idx.get_files(project)?
@ -117,40 +119,48 @@ pub fn scan_with_index_parallel(
// ① Collect per-path Vec<Diag> without a global mutex
let diag_map: DashMap<String, Vec<Diag>> = DashMap::new();
files.into_par_iter()
.for_each_init(
// ② A single Indexer per Rayon worker thread
|| Indexer::from_pool(project, &pool).expect("db pool"),
|idx, path| {
let needs_scan = idx.should_scan(&path).unwrap_or(true);
files.into_par_iter().for_each_init(
// ② A single Indexer per Rayon worker thread
|| Indexer::from_pool(project, &pool).expect("db pool"),
|idx, path| {
let needs_scan = idx.should_scan(&path).unwrap_or(true);
let mut diags = if needs_scan {
let d = run_rules_on_file(&path, cfg).unwrap_or_default();
let file_id = idx.upsert_file(&path).unwrap_or_default();
idx.replace_issues(
file_id,
d.iter().map(|d| IssueRow {
rule_id: &d.id,
severity: d.severity.as_db_str(),
line: d.line as i64,
col: d.col as i64,
}),
).ok();
d
} else {
idx.get_issues_from_file(&path).unwrap_or_default()
};
if !diags.is_empty() {
diag_map.entry(path.to_string_lossy().to_string())
let mut diags = if needs_scan {
let d = run_rules_on_file(&path, cfg).unwrap_or_default();
let file_id = idx.upsert_file(&path).unwrap_or_default();
idx.replace_issues(
file_id,
d.iter().map(|d| IssueRow {
rule_id: &d.id,
severity: d.severity.as_db_str(),
line: d.line as i64,
col: d.col as i64,
}),
)
.ok();
d
} else {
idx.get_issues_from_file(&path).unwrap_or_default()
};
if !diags.is_empty() {
diag_map
.entry(path.to_string_lossy().to_string())
.or_default()
.append(&mut diags);
}
}
);
}
},
);
// Optional, heavy: only vacuum on --rebuild-index
// if rebuild { idx.vacuum()?; }
// flatten
let mut diags: Vec<Diag> = diag_map.into_iter().flat_map(|(_, v)| v).collect();
if let Some(max) = cfg.output.max_results {
diags.truncate(max as usize);
}
// Flatten
Ok(diag_map.into_iter().flat_map(|(_, v)| v).collect())
Ok(diags)
}