impl TdgAnalyzerAst {
pub async fn analyze_file(&self, path: &Path) -> Result<TdgScore> {
self.analyze_file_with_priority(path, OperationPriority::Medium)
.await
}
pub async fn analyze_file_with_priority(
&self,
path: &Path,
priority: OperationPriority,
) -> Result<TdgScore> {
let start_time = SystemTime::now();
let language = Language::from_extension(path);
let _resource_allocation = self.request_analysis_resources(path, priority).await?;
let source = fs::read_to_string(path)?;
let content_hash = blake3::hash(source.as_bytes());
if let Some(cached_score) = self
.check_cache_and_return(&content_hash, language, path, start_time)
.await?
{
return Ok(cached_score);
}
let score = self
.perform_analysis_and_store(path, &source, language, content_hash, start_time)
.await?;
Ok(score)
}
async fn request_analysis_resources(
&self,
path: &Path,
priority: OperationPriority,
) -> Result<Option<crate::tdg::resource_control::ResourceAllocation>> {
if let Some(controller) = &self.resource_controller {
let estimated_memory = self.estimate_analysis_memory(path)?;
Ok(Some(
controller
.request_resources(
format!("analyze_{}", path.display()),
crate::tdg::resource_control::OperationType::Analysis,
priority,
estimated_memory,
)
.await?,
))
} else {
Ok(None)
}
}
async fn check_cache_and_return(
&self,
content_hash: &blake3::Hash,
language: Language,
path: &Path,
start_time: SystemTime,
) -> Result<Option<TdgScore>> {
if let Some(storage) = &self.storage {
if let Some(hot_entry) = storage.get_hot(content_hash) {
if let Some(adaptive) = &self.adaptive_manager {
let duration = start_time.elapsed().unwrap_or_default();
let sample = adaptive.create_sample(duration, true, 0).await;
adaptive.record_sample(sample).await?;
}
let mut cached_score = TdgScore {
total: hot_entry.total_score,
grade: Grade::from_score(hot_entry.total_score),
language,
confidence: language.confidence(),
file_path: Some(path.to_path_buf()),
..Default::default()
};
cached_score.calculate_total();
return Ok(Some(cached_score));
}
}
Ok(None)
}
async fn perform_analysis_and_store(
&self,
path: &Path,
source: &str,
language: Language,
content_hash: blake3::Hash,
start_time: SystemTime,
) -> Result<TdgScore> {
let analysis_start = SystemTime::now();
let score = self.analyze_source(source, language, Some(path.to_path_buf()))?;
let analysis_duration = analysis_start.elapsed().unwrap_or_default();
self.store_analysis_record(path, &score, content_hash, analysis_duration, language)
.await?;
if let Some(adaptive) = &self.adaptive_manager {
let total_duration = start_time.elapsed().unwrap_or_default();
let sample = adaptive.create_sample(total_duration, false, 0).await;
adaptive.record_sample(sample).await?;
}
Ok(score)
}
async fn store_analysis_record(
&self,
path: &Path,
score: &TdgScore,
content_hash: blake3::Hash,
analysis_duration: Duration,
language: Language,
) -> Result<()> {
if let Some(storage) = &self.storage {
let file_metadata = fs::metadata(path)?;
let record = FullTdgRecord {
identity: FileIdentity {
path: path.to_path_buf(),
content_hash,
size_bytes: file_metadata.len(),
modified_time: file_metadata.modified().unwrap_or(SystemTime::now()),
},
score: score.clone(),
components: ComponentScores {
complexity_breakdown: std::collections::HashMap::new(),
duplication_sources: Vec::new(),
coupling_dependencies: Vec::new(),
doc_missing_items: Vec::new(),
consistency_violations: Vec::new(),
},
semantic_sig: SemanticSignature {
ast_structure_hash: u64::from_le_bytes(
content_hash.as_bytes()[0..8]
.try_into()
.expect("slice with incorrect length"),
),
identifier_pattern: String::new(),
control_flow_pattern: String::new(),
import_dependencies: Vec::new(),
},
metadata: AnalysisMetadata {
analyzer_version: env!("CARGO_PKG_VERSION").to_string(),
analysis_duration_ms: analysis_duration.as_millis() as u64,
language_confidence: language.confidence(),
analysis_timestamp: SystemTime::now(),
cache_hit: false,
},
git_context: self.git_context.clone(), };
storage.store(record).await?;
}
Ok(())
}
pub async fn analyze_file_commit(&self, path: &Path) -> Result<TdgScore> {
let _guard = if let Some(scheduler) = &self.scheduler {
Some(
scheduler
.schedule_commit(path.to_path_buf())
.await
.map_err(|e| anyhow::anyhow!("Scheduling failed: {e}"))?,
)
} else {
None
};
self.analyze_file_with_priority(path, OperationPriority::Critical)
.await
}
pub async fn analyze_file_background(&self, path: &Path) -> Result<TdgScore> {
let _guard = if let Some(scheduler) = &self.scheduler {
Some(
scheduler
.schedule_background(path.to_path_buf())
.await
.map_err(|e| anyhow::anyhow!("Scheduling failed: {e}"))?,
)
} else {
None
};
self.analyze_file_with_priority(path, OperationPriority::Low)
.await
}
}