use codesearch::symbols::{
SymbolIndex, SymbolKind,
extractor::extract_symbols_from_file,
relationships::RelationshipGraph,
};
use std::env;
use std::path::Path;
fn main() {
let args: Vec<String> = env::args().collect();
let target_path = args.get(1).map(|s| s.as_str()).unwrap_or(".");
println!("=== Symbol Analysis Example ===\n");
println!("Analyzing: {}\n", target_path);
let path = Path::new(target_path);
if path.is_file() {
analyze_single_file(path);
} else if path.is_dir() {
analyze_directory(path);
} else {
eprintln!("Path not found: {}", target_path);
std::process::exit(1);
}
}
fn analyze_single_file(file_path: &Path) {
println!("Analyzing file: {}\n", file_path.display());
match extract_symbols_from_file(file_path) {
Ok(symbols) => {
println!("Found {} symbols:\n", symbols.len());
let mut by_kind: std::collections::HashMap<String, Vec<_>> =
std::collections::HashMap::new();
for symbol in &symbols {
by_kind
.entry(format!("{:?}", symbol.kind))
.or_default()
.push(symbol);
}
for (kind, items) in by_kind.iter().enumerate() {
let (kind_name, items) = items;
println!(" [{}] ({})", kind_name, items.len());
for symbol in items {
let visibility = if symbol.is_public() { "pub" } else { "priv" };
let signature = if symbol.signature.is_empty() {
"".to_string()
} else {
format!(" {}", symbol.signature)
};
println!(
" - {} {} at line {}{}",
visibility,
symbol.name,
symbol.line,
signature
);
}
println!();
}
println!("\nDetailed Symbol Information:");
for symbol in &symbols {
println!("\n {} (kind: {:?})", symbol.name, symbol.kind);
println!(" File: {}", symbol.file_path);
println!(" Line: {}", symbol.line);
println!(" Visibility: {:?}", symbol.visibility);
if let Some(ref parent) = symbol.parent {
println!(" Parent: {}", parent);
}
if let Some(ref doc) = symbol.documentation {
println!(" Documentation: {}", doc.trim());
}
if !symbol.signature.is_empty() {
println!(" Signature: {}", symbol.signature);
}
}
}
Err(e) => {
eprintln!("Error extracting symbols: {}", e);
}
}
}
fn analyze_directory(dir_path: &Path) {
println!("Analyzing directory: {}\n", dir_path.display());
let index = SymbolIndex::new();
let graph = RelationshipGraph::new();
let mut total_files = 0;
let mut total_symbols = 0;
for entry in walkdir::WalkDir::new(dir_path)
.into_iter()
.filter_map(|e| e.ok())
{
let path = entry.path();
if path.is_file() {
if let Some(ext) = path.extension() {
let ext = ext.to_string_lossy();
if ext == "rs" || ext == "py" || ext == "js" || ext == "ts" || ext == "go" {
if let Ok(symbols) = extract_symbols_from_file(path) {
total_files += 1;
total_symbols += symbols.len();
for symbol in &symbols {
index.add_symbol(symbol.clone());
graph.add_symbol(symbol.clone());
}
}
}
}
}
}
println!("Indexed {} symbols from {} files\n", total_symbols, total_files);
let stats = index.get_stats();
println!("Index Statistics:");
println!(" Total symbols: {}", stats.total_symbols);
println!(" Total files: {}", stats.total_files);
if !stats.symbols_by_kind.is_empty() {
println!("\n Symbols by kind:");
let mut kinds: Vec<_> = stats.symbols_by_kind.iter().collect();
kinds.sort_by(|a, b| b.1.cmp(a.1));
for (kind, count) in kinds {
println!(" {}: {}", kind, count);
}
}
if !stats.symbols_by_language.is_empty() {
println!("\n Symbols by language:");
let mut langs: Vec<_> = stats.symbols_by_language.iter().collect();
langs.sort_by(|a, b| b.1.cmp(a.1));
for (lang, count) in langs {
println!(" {}: {}", lang, count);
}
}
let functions = index.get_symbols_by_kind(&SymbolKind::Function);
if !functions.is_empty() {
println!("\n Functions found ({}):", functions.len());
for func in functions.iter().take(10) {
println!(" - {} ({}:{})", func.name, func.file_path, func.line);
}
if functions.len() > 10 {
println!(" ... and {} more", functions.len() - 10);
}
}
let classes = index.get_symbols_by_kind(&SymbolKind::Class);
let structs = index.get_symbols_by_kind(&SymbolKind::Struct);
let types: Vec<_> = classes.into_iter().chain(structs.into_iter()).collect();
if !types.is_empty() {
println!("\n Types found ({}):", types.len());
for t in types.iter().take(10) {
println!(" - {} ({}:{})", t.name, t.file_path, t.line);
}
}
println!("\n\nSearch Demo:");
println!(" Searching for 'main'...");
let results = index.find_by_name("main");
if results.is_empty() {
println!(" No exact matches found.");
} else {
for r in &results {
println!(" Found: {} at {}:{}", r.name, r.file_path, r.line);
}
}
}