kodept_macros/error/
report.rs1use std::convert::Infallible;
2
3use codespan_reporting::diagnostic::{Diagnostic, Label};
4pub use codespan_reporting::diagnostic::Severity;
5
6use kodept_core::code_point::CodePoint;
7use kodept_core::file_relative::CodePath;
8
9#[derive(Debug)]
10pub struct ReportMessage {
11 pub severity: Severity,
12 pub code: String,
13 pub message: String,
14 pub additional_message: String,
15 pub notes: Vec<String>
16}
17
18#[derive(Debug)]
19pub struct Report {
20 diagnostic: Diagnostic<()>,
21}
22
23impl ReportMessage {
24 pub fn new<S: Into<String>>(severity: Severity, code: S, message: String) -> Self {
25 Self {
26 severity,
27 code: code.into(),
28 message,
29 additional_message: "here".to_string(),
30 notes: vec![]
31 }
32 }
33
34 #[must_use]
35 pub fn with_additional_message(self, additional_message: String) -> Self {
36 Self {
37 additional_message,
38 ..self
39 }
40 }
41
42 pub fn with_notes(self, notes: Vec<String>) -> Self {
43 Self {
44 notes,
45 ..self
46 }
47 }
48}
49
50impl Report {
51 #[must_use]
52 pub const fn is_error(&self) -> bool {
53 matches!(self.diagnostic.severity, Severity::Error | Severity::Bug)
54 }
55
56 pub fn new<R: Into<ReportMessage>>(
57 _file: &CodePath,
58 points: Vec<CodePoint>,
59 message: R,
60 ) -> Self {
61 let msg = message.into();
62 let diagnostic = Diagnostic::new(msg.severity)
63 .with_code(msg.code)
64 .with_message(msg.message)
65 .with_notes(msg.notes);
66 let diagnostic = if let [p] = points.as_slice() {
67 diagnostic.with_labels(vec![Label::primary((), p.as_range())])
68 } else if let [p, s @ ..] = points.as_slice() {
69 let mut secondaries: Vec<_> = s
70 .iter()
71 .map(|it| Label::secondary((), it.as_range()))
72 .collect();
73 secondaries.insert(0, Label::primary((), p.as_range()));
74 diagnostic.with_labels(secondaries)
75 } else {
76 diagnostic
77 };
78 Self { diagnostic }
79 }
80
81 pub fn into_diagnostic(self) -> Diagnostic<()> {
82 self.diagnostic
83 }
84}
85
86impl From<Infallible> for ReportMessage {
87 fn from(_: Infallible) -> Self {
88 unreachable!()
89 }
90}