ocloc 0.5.1

Fast, reliable lines-of-code counter with JSON/CSV output
Documentation
use indexmap::IndexMap;
use serde::Serialize;

#[derive(Debug, Clone, Copy, Default, Serialize)]
pub struct FileCounts {
    pub files: usize,
    pub total: usize,
    pub code: usize,
    pub comment: usize,
    pub blank: usize,
}

impl FileCounts {
    pub fn one_file() -> Self {
        FileCounts {
            files: 1,
            ..Default::default()
        }
    }

    pub fn merge(&mut self, other: &FileCounts) {
        self.files += other.files;
        self.total += other.total;
        self.code += other.code;
        self.comment += other.comment;
        self.blank += other.blank;
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct AnalyzeResult {
    #[serde(rename = "languages")]
    pub per_lang: IndexMap<String, FileCounts>,
    pub totals: FileCounts,
    pub files_analyzed: usize,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub stats: Option<FileStats>,
    #[serde(skip_serializing)]
    pub analyzed_path: Option<String>,
}

#[derive(Debug, Clone, Default, Serialize)]
pub struct FileStats {
    pub total_files: usize,
    pub unique_files: usize,
    pub ignored_files: usize,
    pub empty_files: usize,
    pub elapsed_seconds: f64,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn json_includes_new_languages() {
        let mut per: IndexMap<String, FileCounts> = IndexMap::new();
        per.insert(
            "Markdown".to_string(),
            FileCounts {
                files: 2,
                total: 10,
                code: 8,
                comment: 1,
                blank: 1,
            },
        );
        per.insert(
            "SVG".to_string(),
            FileCounts {
                files: 1,
                total: 5,
                code: 3,
                comment: 2,
                blank: 0,
            },
        );
        let mut totals = FileCounts::default();
        for v in per.values() {
            totals.merge(v);
        }
        let a = AnalyzeResult {
            per_lang: per,
            totals,
            files_analyzed: totals.files,
            stats: None,
            analyzed_path: None,
        };
        let s = serde_json::to_string_pretty(&a).unwrap();
        assert!(s.contains("\"Markdown\""));
        assert!(s.contains("\"SVG\""));
        assert!(s.contains("\"languages\""));
        assert!(s.contains("\"totals\""));
    }
}