pub mod assets;
pub mod ast_js;
pub mod audit_report;
pub mod barrels;
pub mod classify;
pub mod coverage;
pub mod coverage_gaps;
pub mod crowd;
mod css;
pub mod cycles;
pub mod dart;
pub mod dead_parrots;
pub mod dist;
pub mod dist_vlq;
pub mod entrypoints;
pub mod findings;
pub mod for_ai;
pub mod frameworks;
pub mod go;
mod graph;
pub mod health_score;
pub mod html;
pub(crate) mod html_analyzer;
pub mod insights;
pub mod js;
pub mod manifests;
pub mod memory_lint;
pub mod open_server;
pub mod output;
pub mod pipelines;
pub mod py;
pub mod react_lint;
pub mod regexes;
pub mod report;
pub mod resolvers;
pub mod root_scan;
pub mod runner;
pub mod rust;
pub mod sarif;
pub mod scan;
pub mod search;
pub mod test_coverage;
pub mod trace;
pub mod ts_lint;
mod tsconfig;
pub mod twins;
pub(super) fn offset_to_line(content: &str, offset: usize) -> usize {
content[..offset].bytes().filter(|b| *b == b'\n').count() + 1
}
pub fn is_test_file(path: &str) -> bool {
let p = path.to_lowercase();
p.contains(".test.")
|| p.contains(".spec.")
|| p.contains("__tests__")
|| p.contains("/test/")
|| p.contains("/tests/")
|| p.contains("test-utils")
|| p.ends_with("setup.ts")
|| p.ends_with("setup.tsx")
}
pub fn build_open_url(file: &str, line: Option<usize>, open_base: Option<&str>) -> String {
let base = open_base.unwrap_or("loctree://");
let path = if base.ends_with('/') {
format!("{}open", base)
} else if base.contains("://") {
format!("{}/open", base)
} else {
format!("{}://open", base)
};
match line {
Some(l) => format!("{}?f={}&l={}", path, urlencoding::encode(file), l),
None => format!("{}?f={}", path, urlencoding::encode(file)),
}
}
#[allow(unused_imports)]
pub use cycles::{ClassifiedCycle, CycleClassification};
pub use report::{
AiInsight, CommandGap, DupLocation, DupSeverity, GraphComponent, GraphData, GraphNode,
RankedDup, ReportSection,
};
pub use runner::run_import_analyzer;