impl TdgAnalyzerAst {
fn analyze_ruchy_ast(
&self,
source: &str,
score: &mut TdgScore,
tracker: &mut PenaltyTracker,
) -> Result<()> {
#[cfg(feature = "ruchy-ast")]
{
use crate::services::languages::ruchy::analyze_ruchy_file_with_parser;
use std::io::Write;
use tempfile::NamedTempFile;
let mut temp_file = NamedTempFile::with_suffix(".ruchy")?;
temp_file.write_all(source.as_bytes())?;
let temp_path = temp_file.path();
let rt = tokio::runtime::Handle::try_current()
.or_else(|_| tokio::runtime::Runtime::new().map(|rt| rt.handle().clone()))
.map_err(|e| anyhow::anyhow!("Failed to get async runtime: {e}"))?;
let analysis_result =
rt.block_on(async { analyze_ruchy_file_with_parser(temp_path).await });
match analysis_result {
Ok(metrics) => {
score.structural_complexity = self.score_structural_complexity(
metrics.total_complexity.cyclomatic.into(),
metrics.total_complexity.cognitive.into(),
metrics.total_complexity.nesting_max as usize,
metrics.total_complexity.lines.into(),
tracker,
);
let semantic_score = self.calculate_ruchy_semantic_complexity(source);
score.semantic_complexity = semantic_score;
let import_count = self.count_ruchy_imports(source);
let dependency_count = self.count_ruchy_dependencies(source);
score.coupling_score =
self.score_coupling(import_count, dependency_count, 0, tracker);
let doc_coverage = self.calculate_ruchy_doc_coverage(source);
score.doc_coverage = doc_coverage;
score.duplication_ratio =
self.analyze_duplication_ast(source, score.language, tracker);
score.consistency_score = self.calculate_ruchy_consistency(source);
}
Err(_) => {
self.analyze_heuristic(source, score, tracker)?;
}
}
}
#[cfg(not(feature = "ruchy-ast"))]
{
self.analyze_heuristic(source, score, tracker)?;
}
Ok(())
}
fn analyze_tree_sitter_generic(
&self,
source: &str,
_language: Language,
score: &mut TdgScore,
_tracker: &mut PenaltyTracker,
) -> Result<()> {
score.confidence *= 0.7;
self.analyze_heuristic(source, score, _tracker)
}
fn analyze_heuristic(
&self,
source: &str,
score: &mut TdgScore,
_tracker: &mut PenaltyTracker,
) -> Result<()> {
score.confidence *= 0.3;
let simple_analyzer = crate::tdg::analyzer_simple::TdgAnalyzer::new()?;
let simple_score = simple_analyzer.analyze_source(source, score.language, None)?;
score.structural_complexity = simple_score.structural_complexity;
score.semantic_complexity = simple_score.semantic_complexity;
score.duplication_ratio = simple_score.duplication_ratio;
score.coupling_score = simple_score.coupling_score;
score.doc_coverage = simple_score.doc_coverage;
score.consistency_score = simple_score.consistency_score;
Ok(())
}
}
include!("analyzer_impl2_scoring.rs");
include!("analyzer_impl2_consistency.rs");
include!("analyzer_impl2_metrics.rs");
include!("analyzer_impl2_heuristics.rs");
#[cfg(feature = "rust-ast")]
struct RustComplexityVisitor {
cyclomatic_complexity: u32,
cognitive_complexity: u32,
max_nesting_depth: usize,
max_method_length: usize,
max_params: usize,
generic_count: u32,
abstraction_levels: u32,
import_count: u32,
external_calls: u32,
interface_implementations: u32,
documented_items: u32,
total_public_items: u32,
comment_lines: u32,
total_lines: u32,
current_depth: usize,
}