Skip to main content

ferrous_forge/safety/checks/
doc.rs

1//! Documentation checking - placeholder for now, using standards module
2
3use crate::Result;
4use std::path::Path;
5use std::process::Command;
6use std::time::Instant;
7
8use super::SafetyCheck;
9use crate::safety::{CheckType, report::CheckResult};
10
11/// Doc check implementation
12pub struct DocCheck;
13
14impl SafetyCheck for DocCheck {
15    async fn run(project_path: &Path) -> Result<CheckResult> {
16        run(project_path).await
17    }
18
19    fn name() -> &'static str {
20        "doc"
21    }
22
23    fn description() -> &'static str {
24        "Builds project documentation"
25    }
26}
27
28/// Run documentation build check
29///
30/// # Errors
31///
32/// Returns an error if the check result cannot be constructed.
33pub async fn run(project_path: &Path) -> Result<CheckResult> {
34    let start = Instant::now();
35    let mut result = CheckResult::new(CheckType::Doc);
36
37    match Command::new("cargo")
38        .args(["doc", "--no-deps"])
39        .current_dir(project_path)
40        .output()
41    {
42        Ok(output) => {
43            if !output.status.success() {
44                let stderr = String::from_utf8_lossy(&output.stderr);
45                result.add_error(&format!("cargo doc failed: {stderr}"));
46                result.fail();
47            } else {
48                result.add_context("Documentation built successfully");
49            }
50        }
51        Err(e) => {
52            result.add_error(&format!("Failed to execute cargo doc: {e}"));
53            result.fail();
54        }
55    }
56
57    result.set_duration(start.elapsed());
58    Ok(result)
59}
60
61/// Check documentation coverage
62///
63/// # Errors
64///
65/// Returns an error if the documentation coverage check fails to run.
66pub async fn coverage_check(project_path: &Path) -> Result<CheckResult> {
67    let start = Instant::now();
68    let mut result = CheckResult::new(CheckType::DocCoverage);
69
70    let coverage = crate::doc_coverage::check_documentation_coverage(project_path).await?;
71    let threshold = 50.0;
72
73    if !coverage.meets_threshold(threshold) {
74        result.add_error(&format!(
75            "Documentation coverage {:.1}% is below the {:.0}% threshold",
76            coverage.coverage_percent, threshold
77        ));
78        result.fail();
79    }
80
81    result.add_context(&format!(
82        "Documentation coverage: {:.1}% ({}/{} items documented)",
83        coverage.coverage_percent, coverage.documented_items, coverage.total_items
84    ));
85
86    result.set_duration(start.elapsed());
87    Ok(result)
88}