circom_lsp_program_structure/program_library/
error_definition.rs1use super::error_code::ReportCode;
2use super::file_definition::{FileID, FileLibrary, FileLocation};
3use codespan_reporting::diagnostic::{Diagnostic, Label};
4use codespan_reporting::term;
5
6pub type ReportCollection = Vec<Report>;
7pub type DiagnosticCode = String;
8type ReportLabel = Label<FileID>;
9type ReportNote = String;
10
11#[derive(Copy, Clone)]
12pub enum MessageCategory {
13 Error,
14 Warning,
15}
16impl MessageCategory {
17 fn is_error(&self) -> bool {
18 use MessageCategory::*;
19 match self {
20 Error => true,
21 _ => false,
22 }
23 }
24 fn is_warning(&self) -> bool {
25 use MessageCategory::*;
26 match self {
27 Warning => true,
28 _ => false,
29 }
30 }
31}
32
33#[derive(Clone)]
34pub struct Report {
35 category: MessageCategory,
36 error_message: String,
37 error_code: ReportCode,
38 primary: Vec<ReportLabel>,
39 secondary: Vec<ReportLabel>,
40 notes: Vec<ReportNote>,
41}
42impl Report {
43 fn new(category: MessageCategory, error_message: String, error_code: ReportCode) -> Report {
44 Report {
45 category,
46 error_message,
47 error_code,
48 primary: Vec::new(),
49 secondary: Vec::new(),
50 notes: Vec::new(),
51 }
52 }
53 pub fn print_reports(reports: &[Report], file_library: &FileLibrary) {
54 use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
55 let writer = StandardStream::stderr(ColorChoice::Always);
56 let config = term::Config::default();
57 let mut diagnostics = Vec::new();
58 let files = file_library.to_storage();
59 for report in reports.iter() {
60 diagnostics.push(report.to_diagnostic());
61 }
62 for diagnostic in diagnostics.iter() {
63 let print_result = term::emit(&mut writer.lock(), &config, files, &diagnostic);
64 if print_result.is_err() {
65 panic!("Error printing reports")
66 }
67 }
68 }
69 pub fn error_code_to_diagnostic_code(error_code: &ReportCode) -> DiagnosticCode {
70 error_code.to_string()
71 }
72 pub fn error(error_message: String, code: ReportCode) -> Report {
73 Report::new(MessageCategory::Error, error_message, code)
74 }
75 pub fn warning(error_message: String, code: ReportCode) -> Report {
76 Report::new(MessageCategory::Warning, error_message, code)
77 }
78 pub fn add_primary(
79 &mut self,
80 location: FileLocation,
81 file_id: FileID,
82 message: String,
83 ) -> &mut Self {
84 let label = ReportLabel::primary(file_id, location).with_message(message);
85 self.get_mut_primary().push(label);
86 self
87 }
88 pub fn add_secondary(
89 &mut self,
90 location: FileLocation,
91 file_id: FileID,
92 possible_message: Option<String>,
93 ) -> &mut Self {
94 let mut label = ReportLabel::secondary(file_id, location);
95 if let Option::Some(message) = possible_message {
96 label = label.with_message(message);
97 }
98 self.get_mut_secondary().push(label);
99 self
100 }
101 pub fn add_note(&mut self, note: String) -> &mut Self {
102 self.get_mut_notes().push(note);
103 self
104 }
105
106 pub fn to_diagnostic(&self) -> Diagnostic<FileID> {
107 let mut labels = self.get_primary().clone();
108 let mut secondary = self.get_secondary().clone();
109 labels.append(&mut secondary);
110
111 if self.is_warning() { Diagnostic::warning() } else { Diagnostic::error() }
112 .with_message(self.get_message())
113 .with_code(Report::error_code_to_diagnostic_code(self.get_code()))
114 .with_labels(labels)
115 .with_notes(self.get_notes().clone())
116 }
117
118 pub fn is_error(&self) -> bool {
119 self.get_category().is_error()
120 }
121 pub fn is_warning(&self) -> bool {
122 self.get_category().is_warning()
123 }
124 pub fn get_category(&self) -> &MessageCategory {
125 &self.category
126 }
127 pub fn get_message(&self) -> &String {
128 &self.error_message
129 }
130 pub fn get_code(&self) -> &ReportCode {
131 &self.error_code
132 }
133 pub fn get_primary(&self) -> &Vec<ReportLabel> {
134 &self.primary
135 }
136 fn get_mut_primary(&mut self) -> &mut Vec<ReportLabel> {
137 &mut self.primary
138 }
139 pub fn get_secondary(&self) -> &Vec<ReportLabel> {
140 &self.secondary
141 }
142 fn get_mut_secondary(&mut self) -> &mut Vec<ReportLabel> {
143 &mut self.secondary
144 }
145 pub fn get_notes(&self) -> &Vec<ReportNote> {
146 &self.notes
147 }
148 fn get_mut_notes(&mut self) -> &mut Vec<ReportNote> {
149 &mut self.notes
150 }
151}