grit_util/
analysis_logs.rs

1use crate::{Position, Range};
2use derive_builder::Builder;
3use std::fmt::{self, Debug, Display};
4use std::ops;
5use std::path::PathBuf;
6
7// TypedBuilder offers type safe builds at compile time.
8// unfortunately it's a consuming builder, I don't believe it's
9// possible to make a non consuming typed-builder.
10#[derive(Builder, Clone, Debug, Default)]
11pub struct AnalysisLog {
12    #[builder(setter(into, strip_option), default)]
13    pub engine_id: Option<String>,
14    #[builder(setter(into, strip_option), default)]
15    pub file: Option<PathBuf>,
16    #[builder(setter(into, strip_option), default)]
17    pub level: Option<u16>,
18    #[builder(setter(into))]
19    pub message: String,
20    #[builder(setter(into, strip_option), default)]
21    pub position: Option<Position>,
22    // FIXME: We seem to only need this for the end position, and I don't see
23    // any usages for the byte indices either. We can probably trim this.
24    #[builder(setter(into, strip_option), default)]
25    pub range: Option<Range>,
26    #[builder(setter(into, strip_option), default)]
27    pub syntax_tree: Option<String>,
28    #[builder(setter(into, strip_option), default)]
29    pub source: Option<String>,
30}
31
32pub struct AnalysisLogs(Vec<AnalysisLog>);
33
34impl AnalysisLogs {
35    pub fn new() -> Self {
36        Self(Vec::new())
37    }
38
39    pub fn add_warning(&mut self, file: Option<PathBuf>, message: impl Into<String>) {
40        self.0.push(AnalysisLog {
41            level: Some(339),
42            file,
43            message: message.into(),
44            ..AnalysisLog::default()
45        });
46    }
47}
48
49impl Default for AnalysisLogs {
50    fn default() -> Self {
51        Self::new()
52    }
53}
54
55impl AnalysisLogs {
56    pub fn logs(self) -> Vec<AnalysisLog> {
57        self.0
58    }
59}
60
61impl fmt::Display for AnalysisLogs {
62    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63        self.0.iter().try_fold((), |_, log| writeln!(f, "{}", log))
64    }
65}
66
67impl From<Vec<AnalysisLog>> for AnalysisLogs {
68    fn from(logs: Vec<AnalysisLog>) -> Self {
69        Self(logs)
70    }
71}
72
73impl ops::Deref for AnalysisLogs {
74    type Target = Vec<AnalysisLog>;
75
76    fn deref(&self) -> &Self::Target {
77        &self.0
78    }
79}
80
81impl ops::DerefMut for AnalysisLogs {
82    fn deref_mut(&mut self) -> &mut Self::Target {
83        &mut self.0
84    }
85}
86
87impl Debug for AnalysisLogs {
88    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89        self.0.iter().try_fold((), |_, log| writeln!(f, "{}", log))
90    }
91}
92
93impl Display for AnalysisLog {
94    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        write!(
96            f,
97            "engine_id: {:?}\nfile_name: {:?}\nlevel: {:?}\nmessage: {:?}\nposition: {:?}",
98            self.engine_id, self.file, self.level, self.message, self.position
99        )
100    }
101}