scribe_analysis/language_support/
documentation_analysis.rs

1//! # Documentation Coverage Analysis
2//!
3//! Analyzes documentation coverage in source code files, including docstrings,
4//! comments, and inline documentation patterns.
5
6use serde::{Deserialize, Serialize};
7use scribe_core::Result;
8use super::ast_language::AstLanguage;
9
10/// Documentation coverage analysis results
11#[derive(Debug, Clone, Default, Serialize, Deserialize)]
12pub struct DocumentationCoverage {
13    /// Total number of functions/methods
14    pub total_functions: usize,
15    /// Number of documented functions
16    pub documented_functions: usize,
17    /// Total number of classes
18    pub total_classes: usize,
19    /// Number of documented classes
20    pub documented_classes: usize,
21    /// Documentation coverage percentage
22    pub coverage_percentage: f64,
23    /// Lines of documentation
24    pub documentation_lines: usize,
25    /// Total lines of code
26    pub total_lines: usize,
27}
28
29/// Documentation analyzer for specific languages
30#[derive(Debug)]
31pub struct DocumentationAnalyzer {
32    language: AstLanguage,
33}
34
35impl DocumentationAnalyzer {
36    /// Create a new documentation analyzer
37    pub fn new(language: AstLanguage) -> Result<Self> {
38        Ok(Self { language })
39    }
40    
41    /// Analyze documentation coverage in source code
42    pub fn analyze_coverage(&self, content: &str) -> Result<DocumentationCoverage> {
43        // Basic implementation - can be enhanced with AST analysis
44        let lines: Vec<&str> = content.lines().collect();
45        let total_lines = lines.len();
46        let documentation_lines = self.count_documentation_lines(&lines);
47        
48        let coverage_percentage = if total_lines > 0 {
49            (documentation_lines as f64 / total_lines as f64) * 100.0
50        } else {
51            0.0
52        };
53        
54        Ok(DocumentationCoverage {
55            total_functions: 0, // TODO: Extract from AST
56            documented_functions: 0, // TODO: Extract from AST
57            total_classes: 0, // TODO: Extract from AST
58            documented_classes: 0, // TODO: Extract from AST
59            coverage_percentage,
60            documentation_lines,
61            total_lines,
62        })
63    }
64    
65    /// Count lines that contain documentation
66    fn count_documentation_lines(&self, lines: &[&str]) -> usize {
67        lines.iter()
68            .filter(|line| self.is_documentation_line(line))
69            .count()
70    }
71    
72    /// Check if a line contains documentation
73    fn is_documentation_line(&self, line: &str) -> bool {
74        let trimmed = line.trim();
75        
76        match self.language {
77            AstLanguage::Python => {
78                trimmed.starts_with('#') ||
79                trimmed.starts_with("\"\"\"") ||
80                trimmed.starts_with("'''")
81            }
82            AstLanguage::JavaScript | AstLanguage::TypeScript => {
83                trimmed.starts_with("//") ||
84                trimmed.starts_with("/*") ||
85                trimmed.starts_with("*") ||
86                trimmed.starts_with("/**")
87            }
88            AstLanguage::Rust => {
89                trimmed.starts_with("//") ||
90                trimmed.starts_with("///") ||
91                trimmed.starts_with("//!")
92            }
93            AstLanguage::Go => {
94                trimmed.starts_with("//")
95            }
96            _ => {
97                // Generic comment detection
98                trimmed.starts_with("//") ||
99                trimmed.starts_with("#") ||
100                trimmed.starts_with("/*") ||
101                trimmed.starts_with("*")
102            }
103        }
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110    
111    #[test]
112    fn test_python_documentation_analysis() {
113        let analyzer = DocumentationAnalyzer::new(AstLanguage::Python).unwrap();
114        let python_code = r#"
115# This is a comment
116def hello():
117    """This is a docstring."""
118    print("Hello")
119
120def world():
121    # Another comment
122    print("World")
123"#;
124        
125        let coverage = analyzer.analyze_coverage(python_code).unwrap();
126        assert!(coverage.documentation_lines > 0);
127        assert!(coverage.coverage_percentage > 0.0);
128    }
129}