tiger_lib/report/
report_struct.rs

1use serde::Serialize;
2use strum_macros::{Display, EnumCount, EnumIter, EnumString, IntoStaticStr};
3
4use crate::report::ErrorKey;
5use crate::token::Loc;
6
7pub type LogReport = (LogReportMetadata, LogReportPointers);
8
9#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
10pub enum LogReportStyle {
11    Full,
12    Abbreviated,
13}
14
15/// Describes a report about a potentially problematic situation that can be logged.
16#[derive(Debug, Clone, Hash, PartialEq, Eq)]
17pub struct LogReportMetadata {
18    /// Used for choosing output colors and for filtering reports.
19    pub severity: Severity,
20    /// Mostly used for filtering reports.
21    pub confidence: Confidence,
22    /// Defines the problem category. Used for filtering reports.
23    pub key: ErrorKey,
24    /// The primary error message. A short description of the problem.
25    pub msg: String,
26    /// Optional info message to be printed at the end.
27    pub info: Option<String>,
28    /// Optional wiki link to be printed at the end.
29    pub wiki: Option<String>,
30    // /// Output style for this report
31    pub style: LogReportStyle,
32}
33
34#[derive(Debug, Clone, Hash, PartialEq, Eq)]
35pub struct PointedMessage {
36    /// Which file and where in the file the error occurs.
37    /// Might point to a whole file, rather than a specific location in the file.
38    pub loc: Loc,
39    /// The length of the offending phrase in characters.
40    /// Set this to 1 if the length cannot be determined.
41    /// This will determine the number of carets that are printed at the given location.
42    /// e.g.:     ^^^^^^^^^
43    /// A length of 0 will hide the carets
44    /// TODO: If we end up adding length to Loc, this field can be deleted.
45    pub length: usize,
46    /// A short message that will be printed at the caret location.
47    pub msg: Option<String>,
48}
49
50impl PointedMessage {
51    pub fn new(loc: Loc) -> Self {
52        Self { loc, msg: None, length: 0 }
53    }
54}
55
56/// Should contain one or more elements.
57pub type LogReportPointers = Vec<PointedMessage>;
58
59pub fn pointer_indentation(pointers: &LogReportPointers) -> usize {
60    pointers.iter().map(|pointer| pointer.loc.line.to_string().len()).max().unwrap_or(0)
61}
62
63/// Determines the output colour.
64/// User can also filter by minimum severity level: e.g. don't show me Info-level messages.
65///
66/// The order of these enum values determines the level of severity they denote.
67/// Do not change the order unless you mean to change the logic of the program!
68#[derive(
69    Default,
70    Debug,
71    Display,
72    Clone,
73    Copy,
74    Ord,
75    PartialOrd,
76    Eq,
77    PartialEq,
78    Hash,
79    IntoStaticStr,
80    EnumString,
81    EnumCount,
82    EnumIter,
83    Serialize,
84)]
85#[serde(rename_all = "kebab-case")]
86#[strum(serialize_all = "kebab-case")]
87pub enum Severity {
88    /// These are things that aren't necessarily wrong, but there may be a better, more
89    /// idiomatic way to do it. This may also include performance issues.
90    Tips,
91    /// This code smells.
92    /// The player is unlikely to be impacted directly, but developers working on this codebase
93    /// will likely experience maintenance headaches.
94    Untidy,
95    /// This will result in glitches that will noticeably impact the player's gaming experience.
96    /// Missing translations are an example.
97    #[default]
98    Warning,
99    /// This code probably doesn't work as intended. The player may experience bugs.
100    Error,
101    /// This is likely to cause crashes.
102    Fatal,
103}
104
105impl Severity {
106    /// Reduce the severity to at most `max_sev`, unless severity is `Fatal`, then stays `Fatal`.
107    #[must_use]
108    pub fn at_most(self, max_sev: Severity) -> Severity {
109        if self == Severity::Fatal {
110            Severity::Fatal
111        } else {
112            self.min(max_sev)
113        }
114    }
115}
116
117/// Mostly invisible in the output.
118/// User can filter by minimum confidence level.
119/// This would be a dial for how many false positives they're willing to put up with.
120///
121/// The order of these enum values determines the level of confidence they denote.
122/// Do not change the order unless you mean to change the logic of the program!
123#[derive(
124    Default,
125    Debug,
126    Clone,
127    Copy,
128    Ord,
129    PartialOrd,
130    Eq,
131    PartialEq,
132    Hash,
133    IntoStaticStr,
134    EnumIter,
135    EnumString,
136    Serialize,
137)]
138#[serde(rename_all = "kebab-case")]
139#[strum(serialize_all = "kebab-case")]
140pub enum Confidence {
141    /// Quite likely to be a false positive.
142    Weak,
143    /// Reasonably confident that the problem is real.
144    #[default]
145    Reasonable,
146    /// Very confident that this problem is real.
147    Strong,
148}