morph-cli 0.1.0

AST-based codebase migration and codemod tool for JavaScript and TypeScript projects.
Documentation
use std::path::PathBuf;
use std::time::Instant;

use super::preview::{ChangedFile, SkipReason, SkippedFile, TransformationReport};

#[derive(Debug, Clone, Default)]
#[allow(dead_code)]
pub struct AggregatedStats {
    pub total_files: usize,
    pub changed_files: usize,
    pub skipped_files: usize,
    pub lines_added: usize,
    pub lines_removed: usize,
    pub execution_time_ms: u64,
    pub patterns_detected: usize,
}

impl AggregatedStats {
    #[allow(dead_code)]
    pub fn new() -> Self {
        Self::default()
    }

    #[allow(dead_code)]
    pub fn add_changed_file(&mut self, file: &ChangedFile) {
        self.changed_files += 1;
        self.lines_added += file.lines_added;
        self.lines_removed += file.lines_removed;
    }

    #[allow(dead_code)]
    pub fn add_skipped_file(&mut self) {
        self.skipped_files += 1;
    }

    #[allow(dead_code)]
    pub fn finalize(&mut self, execution_time_ms: u64) {
        self.execution_time_ms = execution_time_ms;
        self.total_files = self.changed_files + self.skipped_files;
    }
}

impl From<&TransformationReport> for AggregatedStats {
    fn from(report: &TransformationReport) -> Self {
        let mut stats = AggregatedStats::new();
        stats.changed_files = report.total_changed();
        stats.skipped_files = report.total_files_skipped();
        stats.lines_added = report.total_lines_added();
        stats.lines_removed = report.total_lines_removed();
        stats.execution_time_ms = report.execution_time_ms;
        stats.total_files = stats.changed_files + stats.skipped_files;
        stats
    }
}

#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct ExecutionTimer {
    start: Instant,
}

impl ExecutionTimer {
    #[allow(dead_code)]
    pub fn new() -> Self {
        Self {
            start: Instant::now(),
        }
    }

    #[allow(dead_code)]
    pub fn elapsed_ms(&self) -> u64 {
        self.start.elapsed().as_millis() as u64
    }
}

impl Default for ExecutionTimer {
    fn default() -> Self {
        Self::new()
    }
}

pub struct ReportBuilder {
    #[allow(dead_code)]
    report: TransformationReport,
}

impl ReportBuilder {
    #[allow(dead_code)]
    pub fn new() -> Self {
        Self {
            report: TransformationReport::new(),
        }
    }

    #[allow(dead_code)]
    pub fn add_changed(&mut self, path: PathBuf, lines_added: usize, lines_removed: usize) {
        self.report.changed_files.push(ChangedFile {
            path,
            lines_added,
            lines_removed,
            preview: None,
        });
    }

    #[allow(dead_code)]
    pub fn add_skipped(&mut self, path: PathBuf, reason: SkipReason) {
        self.report.skipped_files.push(SkippedFile { path, reason });
    }

    #[allow(dead_code)]
    pub fn build(mut self) -> TransformationReport {
        self.report.finish();
        self.report
    }
}

impl Default for ReportBuilder {
    fn default() -> Self {
        Self::new()
    }
}