#[cfg(feature = "kotlin-ast")]
impl Default for KotlinComplexityAnalyzer {
fn default() -> Self {
Self::new()
}
}
#[cfg(feature = "kotlin-ast")]
impl KotlinComplexityAnalyzer {
#[must_use]
pub fn new() -> Self {
Self {
cyclomatic_complexity: 0,
cognitive_complexity: 0,
coroutine_complexity: 0,
}
}
pub fn analyze_complexity(&mut self, source: &str) -> Result<(u32, u32), String> {
self.cyclomatic_complexity = 1;
self.cognitive_complexity = 1;
let lines: Vec<&str> = source.lines().collect();
for line in lines {
let trimmed = line.trim();
self.analyze_complexity_for_line(trimmed);
}
Ok((self.cyclomatic_complexity, self.cognitive_complexity))
}
fn analyze_complexity_for_line(&mut self, line: &str) {
if line.contains("if ") || line.contains("while ") || line.contains("for ") {
self.cyclomatic_complexity += 1;
self.cognitive_complexity += 1;
}
if line.contains("&&") || line.contains("||") {
self.cyclomatic_complexity += 1;
}
if line.contains("when ") || line.contains("catch ") {
self.cyclomatic_complexity += 1;
self.cognitive_complexity += 1;
}
}
pub fn analyze_coroutine_complexity(&mut self, source: &str) -> Result<u32, String> {
self.coroutine_complexity = 0;
let lines: Vec<&str> = source.lines().collect();
for line in lines {
let trimmed = line.trim();
if trimmed.contains("suspend ")
|| trimmed.contains("async ")
|| trimmed.contains("launch ")
{
self.coroutine_complexity += 1;
}
}
if self.coroutine_complexity > 0 {
self.coroutine_complexity = self.coroutine_complexity.max(1);
}
Ok(self.coroutine_complexity)
}
}