use super::ast_language::AstLanguage;
use scribe_core::Result;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct DocumentationCoverage {
pub total_functions: usize,
pub documented_functions: usize,
pub total_classes: usize,
pub documented_classes: usize,
pub coverage_percentage: f64,
pub documentation_lines: usize,
pub total_lines: usize,
}
#[derive(Debug)]
pub struct DocumentationAnalyzer {
language: AstLanguage,
}
impl DocumentationAnalyzer {
pub fn new(language: AstLanguage) -> Result<Self> {
Ok(Self { language })
}
pub fn analyze_coverage(&self, content: &str) -> Result<DocumentationCoverage> {
let lines: Vec<&str> = content.lines().collect();
let total_lines = lines.len();
let documentation_lines = self.count_documentation_lines(&lines);
let coverage_percentage = if total_lines > 0 {
(documentation_lines as f64 / total_lines as f64) * 100.0
} else {
0.0
};
Ok(DocumentationCoverage {
total_functions: 0, documented_functions: 0, total_classes: 0, documented_classes: 0, coverage_percentage,
documentation_lines,
total_lines,
})
}
fn count_documentation_lines(&self, lines: &[&str]) -> usize {
lines
.iter()
.filter(|line| self.is_documentation_line(line))
.count()
}
fn is_documentation_line(&self, line: &str) -> bool {
let trimmed = line.trim();
match self.language {
AstLanguage::Python => {
trimmed.starts_with('#')
|| trimmed.starts_with("\"\"\"")
|| trimmed.starts_with("'''")
}
AstLanguage::JavaScript | AstLanguage::TypeScript => {
trimmed.starts_with("//")
|| trimmed.starts_with("/*")
|| trimmed.starts_with("*")
|| trimmed.starts_with("/**")
}
AstLanguage::Rust => {
trimmed.starts_with("//")
|| trimmed.starts_with("///")
|| trimmed.starts_with("//!")
}
AstLanguage::Go => trimmed.starts_with("//"),
_ => {
trimmed.starts_with("//")
|| trimmed.starts_with("#")
|| trimmed.starts_with("/*")
|| trimmed.starts_with("*")
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_python_documentation_analysis() {
let analyzer = DocumentationAnalyzer::new(AstLanguage::Python).unwrap();
let python_code = r#"
# This is a comment
def hello():
"""This is a docstring."""
print("Hello")
def world():
# Another comment
print("World")
"#;
let coverage = analyzer.analyze_coverage(python_code).unwrap();
assert!(coverage.documentation_lines > 0);
assert!(coverage.coverage_percentage > 0.0);
}
}