Skip to main content

morph_cli/core/diff/
report.rs

1use std::path::PathBuf;
2use std::time::Instant;
3
4use super::preview::{ChangedFile, SkipReason, SkippedFile, TransformationReport};
5
6#[derive(Debug, Clone, Default)]
7#[allow(dead_code)]
8pub struct AggregatedStats {
9    pub total_files: usize,
10    pub changed_files: usize,
11    pub skipped_files: usize,
12    pub lines_added: usize,
13    pub lines_removed: usize,
14    pub execution_time_ms: u64,
15    pub patterns_detected: usize,
16}
17
18impl AggregatedStats {
19    #[allow(dead_code)]
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    #[allow(dead_code)]
25    pub fn add_changed_file(&mut self, file: &ChangedFile) {
26        self.changed_files += 1;
27        self.lines_added += file.lines_added;
28        self.lines_removed += file.lines_removed;
29    }
30
31    #[allow(dead_code)]
32    pub fn add_skipped_file(&mut self) {
33        self.skipped_files += 1;
34    }
35
36    #[allow(dead_code)]
37    pub fn finalize(&mut self, execution_time_ms: u64) {
38        self.execution_time_ms = execution_time_ms;
39        self.total_files = self.changed_files + self.skipped_files;
40    }
41}
42
43impl From<&TransformationReport> for AggregatedStats {
44    fn from(report: &TransformationReport) -> Self {
45        let mut stats = AggregatedStats::new();
46        stats.changed_files = report.total_changed();
47        stats.skipped_files = report.total_files_skipped();
48        stats.lines_added = report.total_lines_added();
49        stats.lines_removed = report.total_lines_removed();
50        stats.execution_time_ms = report.execution_time_ms;
51        stats.total_files = stats.changed_files + stats.skipped_files;
52        stats
53    }
54}
55
56#[derive(Debug, Clone)]
57#[allow(dead_code)]
58pub struct ExecutionTimer {
59    start: Instant,
60}
61
62impl ExecutionTimer {
63    #[allow(dead_code)]
64    pub fn new() -> Self {
65        Self {
66            start: Instant::now(),
67        }
68    }
69
70    #[allow(dead_code)]
71    pub fn elapsed_ms(&self) -> u64 {
72        self.start.elapsed().as_millis() as u64
73    }
74}
75
76impl Default for ExecutionTimer {
77    fn default() -> Self {
78        Self::new()
79    }
80}
81
82pub struct ReportBuilder {
83    #[allow(dead_code)]
84    report: TransformationReport,
85}
86
87impl ReportBuilder {
88    #[allow(dead_code)]
89    pub fn new() -> Self {
90        Self {
91            report: TransformationReport::new(),
92        }
93    }
94
95    #[allow(dead_code)]
96    pub fn add_changed(&mut self, path: PathBuf, lines_added: usize, lines_removed: usize) {
97        self.report.changed_files.push(ChangedFile {
98            path,
99            lines_added,
100            lines_removed,
101            preview: None,
102        });
103    }
104
105    #[allow(dead_code)]
106    pub fn add_skipped(&mut self, path: PathBuf, reason: SkipReason) {
107        self.report.skipped_files.push(SkippedFile { path, reason });
108    }
109
110    #[allow(dead_code)]
111    pub fn build(mut self) -> TransformationReport {
112        self.report.finish();
113        self.report
114    }
115}
116
117impl Default for ReportBuilder {
118    fn default() -> Self {
119        Self::new()
120    }
121}