#![cfg_attr(coverage_nightly, coverage(off))]
use super::analyzer_ast::TdgAnalyzerAst;
impl TdgAnalyzerAst {
#[cfg(feature = "ruchy-ast")]
#[allow(clippy::cast_possible_truncation)]
pub(crate) fn calculate_ruchy_semantic_complexity(&self, source: &str) -> f32 {
let mut complexity_score = self.config.weights.semantic_complexity;
let actor_count = source.matches("actor ").count();
let receive_count = source.matches("receive ").count();
let pipeline_count = source.matches("|>").count();
let match_count = source.matches(" match ").count();
let pattern_match_count = source.matches(" => ").count();
complexity_score += (actor_count * 2) as f32;
complexity_score += receive_count as f32 * 1.5;
complexity_score += pipeline_count as f32 * 0.5;
complexity_score += match_count as f32 * 1.2;
complexity_score += pattern_match_count as f32 * 0.3;
complexity_score.min(self.config.weights.semantic_complexity)
}
#[cfg(feature = "ruchy-ast")]
#[allow(clippy::cast_possible_truncation)]
pub(crate) fn count_ruchy_imports(&self, source: &str) -> u32 {
source.matches("import ").count() as u32
+ source.matches("use ").count() as u32
+ source.matches("extern ").count() as u32
}
#[cfg(feature = "ruchy-ast")]
#[allow(clippy::cast_possible_truncation)]
pub(crate) fn count_ruchy_dependencies(&self, source: &str) -> u32 {
source.matches(" <- ").count() as u32 + source.matches(" <? ").count() as u32 + source.matches("spawn ").count() as u32 }
#[cfg(feature = "ruchy-ast")]
#[allow(clippy::cast_possible_truncation)]
pub(crate) fn calculate_ruchy_doc_coverage(&self, source: &str) -> f32 {
let line_count = source.lines().count() as f32;
if line_count == 0.0 {
return self.config.weights.documentation;
}
let doc_comments = source.matches("///").count() as f32
+ source.matches("/**").count() as f32
+ source.matches("#[doc").count() as f32;
let coverage_ratio = (doc_comments / line_count * 20.0).min(1.0);
coverage_ratio * self.config.weights.documentation
}
#[cfg(feature = "ruchy-ast")]
#[allow(clippy::cast_possible_truncation)]
pub(crate) fn calculate_ruchy_consistency(&self, source: &str) -> f32 {
let mut consistency_score = self.config.weights.consistency;
let snake_case_functions = regex::Regex::new(r"fun [a-z][a-z0-9_]*\(")
.expect("Invalid regex")
.find_iter(source)
.count();
let pascal_case_types = regex::Regex::new(r"(struct|enum|actor) [A-Z][A-Za-z0-9]*")
.expect("Invalid regex")
.find_iter(source)
.count();
let snake_case_vars = regex::Regex::new(r"let [a-z][a-z0-9_]* =")
.expect("Invalid regex")
.find_iter(source)
.count();
let total_identifiers = snake_case_functions + pascal_case_types + snake_case_vars;
if total_identifiers > 0 {
let fun_upper_regex = regex::Regex::new(r"fun [A-Z]").expect("Invalid regex");
let struct_lower_regex = regex::Regex::new(r"struct [a-z]").expect("Invalid regex");
let let_upper_regex = regex::Regex::new(r"let [A-Z]").expect("Invalid regex");
let inconsistent_count = fun_upper_regex.find_iter(source).count()
+ struct_lower_regex.find_iter(source).count()
+ let_upper_regex.find_iter(source).count();
if inconsistent_count > 0 {
let consistency_ratio =
1.0 - (inconsistent_count as f32 / total_identifiers as f32);
consistency_score *= consistency_ratio;
}
}
consistency_score
}
}