1use crate::context::ProjectMetadata;
2use crate::file_analyzers;
3use crate::log_debug;
4use anyhow::Result;
5use futures::future::join_all;
6use std::path::Path;
7use tokio::task;
8
9pub async fn analyze_file(file_path: &str) -> Option<ProjectMetadata> {
11 let file_name = Path::new(file_path)
12 .file_name()
13 .and_then(|name| name.to_str())
14 .unwrap_or_default();
15
16 let analyzer: Box<dyn file_analyzers::FileAnalyzer + Send + Sync> =
17 file_analyzers::get_analyzer(file_name);
18
19 log_debug!("Analyzing file: {}", file_path);
20
21 if file_analyzers::should_exclude_file(file_path) {
22 log_debug!("File excluded: {}", file_path);
23 None
24 } else if let Ok(content) = tokio::fs::read_to_string(file_path).await {
25 let metadata = analyzer.extract_metadata(file_name, &content);
26 log_debug!("Extracted metadata for {}: {:?}", file_name, metadata);
27 Some(metadata)
28 } else {
29 log_debug!("Failed to read file: {}", file_path);
30 None
31 }
32}
33
34pub async fn extract_project_metadata(
38 changed_files: &[String],
39 batch_size: usize,
40) -> Result<ProjectMetadata> {
41 log_debug!(
42 "Getting project metadata for {} changed files",
43 changed_files.len()
44 );
45
46 let mut combined_metadata = ProjectMetadata::default();
47 let mut any_file_analyzed = false;
48
49 for chunk in changed_files.chunks(batch_size) {
51 let metadata_futures = chunk.iter().map(|file_path| {
52 let file_path = file_path.clone();
53 task::spawn(async move { analyze_file(&file_path).await })
54 });
55
56 let batch_results = join_all(metadata_futures).await;
57
58 for metadata in batch_results.into_iter().flatten().flatten() {
59 log_debug!("Merging metadata: {:?}", metadata);
60 combined_metadata.merge(metadata);
61 any_file_analyzed = true;
62 }
63 }
64
65 log_debug!("Final combined metadata: {:?}", combined_metadata);
66
67 if !any_file_analyzed {
68 log_debug!("No files were analyzed!");
69 combined_metadata.language = Some("Unknown".to_string());
70 } else if combined_metadata.language.is_none() {
71 combined_metadata.language = Some("Unknown".to_string());
72 }
73
74 Ok(combined_metadata)
75}