Skip to main content

harper_stats/
lib.rs

1mod record;
2mod summary;
3
4use std::io::{self, Read, Write};
5use std::io::{BufRead, BufReader};
6
7use harper_core::TokenKind;
8pub use record::Record;
9pub use record::RecordKind;
10use serde::Serialize;
11use serde_json::Serializer;
12pub use summary::Summary;
13
14/// A collection of logged statistics for the various Harper frontends.
15#[derive(Debug, Clone, Eq, PartialEq)]
16pub struct Stats {
17    pub records: Vec<Record>,
18}
19
20impl Stats {
21    pub fn new() -> Self {
22        Self {
23            records: Vec::new(),
24        }
25    }
26
27    /// Count the number of each kind of lint applied.
28    pub fn summarize(&self) -> Summary {
29        let mut summary = Summary::new();
30
31        for record in &self.records {
32            match &record.kind {
33                RecordKind::Lint { kind, context } => {
34                    summary.inc_lint_count(*kind);
35
36                    for tok in context {
37                        if let TokenKind::Word(None) = tok.kind {
38                            summary.inc_misspelled_count(&tok.content);
39                        }
40                    }
41                }
42                RecordKind::LintConfigUpdate(lint_group_config) => {
43                    summary.final_config = lint_group_config.clone();
44                }
45            }
46        }
47
48        summary
49    }
50
51    /// Write the records from `self`.
52    /// Expects the target buffer to either be empty or already be terminated by a newline.
53    pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
54        for record in &self.records {
55            let mut serializer = Serializer::new(&mut *w);
56            record.serialize(&mut serializer)?;
57            writeln!(w)?;
58        }
59
60        Ok(())
61    }
62
63    /// Read records from a buffer into `self`.
64    /// Assumes the buffer is properly formatted and terminated with a newline.
65    /// An empty buffer will result in no mutation to `self`.
66    pub fn read(r: &mut impl Read) -> io::Result<Self> {
67        let br = BufReader::new(r);
68        let mut records = Vec::new();
69
70        for line_res in br.lines() {
71            let line = line_res?;
72
73            let record: Record = serde_json::from_str(&line)?;
74            records.push(record);
75        }
76
77        Ok(Self { records })
78    }
79}
80
81impl Default for Stats {
82    fn default() -> Self {
83        Self::new()
84    }
85}