py_declare/
error.rs

1use crate::Type;
2use std::rc::Rc;
3use terl::{Message, Span, WithSpan};
4
5#[derive(Debug, Clone)]
6pub enum DeclareError {
7    UniqueDeleted {
8        reason: Box<DeclareError>,
9    },
10    NonBranchSelected {
11        expect: String,
12    },
13    ConflictSelected {
14        conflict_with: Type,
15        this: Type,
16    },
17    NeverUsed {
18        in_group: Span,
19        reason: Option<Box<DeclareError>>,
20    },
21    //
22    Declared {
23        declare_as: Type,
24    },
25    Unexpect {
26        expect: String,
27    },
28    ShouldAlign {
29        left: Span,
30        right: Span,
31    },
32    WithLocation {
33        location: Span,
34        error: Box<DeclareError>,
35    },
36    WithPrevious {
37        previous: Type,
38        error: Box<DeclareError>,
39    },
40    Shared {
41        err: Rc<DeclareError>,
42    },
43
44    Filtered,
45    Empty,
46}
47
48impl DeclareError {
49    pub fn with_location(self, location: Span) -> Self {
50        Self::WithLocation {
51            location,
52            error: Box::new(self),
53        }
54    }
55
56    pub fn into_shared(self) -> Self {
57        Self::Shared { err: Rc::new(self) }
58    }
59
60    pub fn with_previous(self, previous: Type) -> Self {
61        Self::WithPrevious {
62            previous,
63            error: Box::new(self),
64        }
65    }
66
67    fn generate_inner(&self, msgs: &mut Vec<terl::Message>) {
68        match self {
69            DeclareError::UniqueDeleted { reason } => {
70                msgs.push(Message::Text(
71                    "this has been declared, but filtered latter".to_owned(),
72                ));
73                reason.generate_inner(msgs)
74            }
75            DeclareError::NonBranchSelected { expect } => {
76                msgs.push(Message::Text(format!("this should be `{expect}`")))
77            }
78            DeclareError::ConflictSelected {
79                conflict_with,
80                this,
81            } => msgs.push(Message::Text(format!(
82                "this is required to been declared as {} and {} together, but its impossiable",
83                this, conflict_with
84            ))),
85            DeclareError::NeverUsed { reason, in_group } => {
86                msgs.push(in_group.make_message("the branch is never used in group"));
87                if let Some(reason) = reason.as_ref() {
88                    reason.generate_inner(msgs)
89                }
90            }
91
92            DeclareError::ShouldAlign { left, right } => {
93                msgs.push("those two has been declared to have same type".into());
94                msgs.push((*left).into());
95                msgs.push((*right).into());
96            }
97            DeclareError::Declared { declare_as } => msgs.push(Message::Text(format!(
98                "this has been declared as {declare_as}"
99            ))),
100            DeclareError::Unexpect { expect } => msgs.push(Message::Text(format!(
101                "expect this to be declared as `{}`",
102                expect.to_owned()
103            ))),
104            DeclareError::Filtered => msgs.push(Message::Text("this has been filtered".to_owned())),
105            DeclareError::Shared { err } => err.generate_inner(msgs),
106
107            DeclareError::WithLocation { location, error } => {
108                let len = msgs.len();
109                error.generate_inner(msgs);
110                if let Message::Text(ref mut msg) = msgs[len] {
111                    msgs[len] = Message::Rich(std::mem::take(msg), *location)
112                }
113            }
114            DeclareError::WithPrevious { previous, error } => {
115                error.generate_inner(msgs);
116                msgs.push(Message::Text(format!(
117                    "note: this used to be guessed as {previous}"
118                )))
119            }
120            DeclareError::Empty => {}
121        }
122    }
123
124    pub fn generate(&self) -> Vec<terl::Message> {
125        let mut msgs = vec![];
126        self.generate_inner(&mut msgs);
127        msgs
128    }
129}