language_reporting/
models.rs1use crate::diagnostic::Diagnostic;
2use crate::{FileName, Label, LabelStyle, Location, ReportingFiles, ReportingSpan, Severity};
3
4#[derive(Copy, Clone, Debug)]
5pub(crate) struct Header<'doc> {
6 severity: Severity,
7 code: Option<&'doc str>,
8 message: &'doc str,
9}
10
11impl<'doc> Header<'doc> {
12 pub(crate) fn new(diagnostic: &'doc Diagnostic<impl ReportingSpan>) -> Header<'doc> {
13 Header {
14 severity: diagnostic.severity,
15 code: diagnostic.code.as_ref().map(|c| &c[..]),
16 message: &diagnostic.message,
17 }
18 }
19
20 pub(crate) fn severity(&self) -> &'static str {
21 match self.severity {
22 Severity::Bug => "bug",
23 Severity::Error => "error",
24 Severity::Warning => "warning",
25 Severity::Help => "help",
26 Severity::Note => "note",
27 }
28 }
29
30 pub(crate) fn code(&self) -> &Option<&'doc str> {
31 &self.code
32 }
33
34 pub(crate) fn message(&self) -> String {
35 self.message.to_string()
36 }
37}
38
39pub(crate) fn severity(diagnostic: &Diagnostic<impl ReportingSpan>) -> &'static str {
40 match diagnostic.severity {
41 Severity::Bug => "bug",
42 Severity::Error => "error",
43 Severity::Warning => "warning",
44 Severity::Help => "help",
45 Severity::Note => "note",
46 }
47}
48
49#[derive(Copy, Clone, Debug)]
50pub(crate) struct SourceLine<'doc, Files: ReportingFiles> {
51 files: &'doc Files,
52 label: &'doc Label<Files::Span>,
53 config: &'doc dyn crate::Config,
54}
55
56impl<'doc, Files: ReportingFiles> SourceLine<'doc, Files> {
57 pub(crate) fn new(
58 files: &'doc Files,
59 label: &'doc Label<Files::Span>,
60 config: &'doc dyn crate::Config,
61 ) -> SourceLine<'doc, Files> {
62 SourceLine {
63 files,
64 label,
65 config,
66 }
67 }
68
69 pub(crate) fn location(&self) -> Location {
70 let span = self.label.span;
71
72 self.files
73 .location(self.files.file_id(span), span.start())
74 .expect("A valid location")
75 }
76
77 pub(crate) fn filename(&self) -> String {
78 match &self.files.file_name(self.files.file_id(self.label.span)) {
79 FileName::Virtual(name) => format!("<{}>", name.to_str().unwrap()),
80 FileName::Real(name) => self.config.filename(name),
81 FileName::Verbatim(name) => format!("{}", name),
82 }
83 }
84
85 pub(crate) fn line_span(&self) -> Files::Span {
86 let span = self.label.span;
87
88 self.files
89 .line_span(self.files.file_id(span), self.location().line)
90 .expect("line_span")
91 }
92
93 pub(crate) fn line_number(&self) -> usize {
94 self.location().line + 1
95 }
96
97 pub(crate) fn line_number_len(&self) -> usize {
98 self.line_number().to_string().len()
99 }
100
101 pub(crate) fn before_marked(&self) -> String {
107 self.files
108 .source(self.line_span().with_end(self.label.span.start()))
109 .expect("line_prefix")
110 }
111
112 pub(crate) fn after_marked(&self) -> String {
113 self.files
114 .source(self.line_span().with_start(self.label.span.end()))
115 .expect("line_suffix")
116 .trim_end_matches(|ch| ch == '\r' || ch == '\n')
117 .to_string()
118 }
119
120 pub(crate) fn marked(&self) -> String {
121 self.files.source(self.label.span).expect("line_marked")
122 }
123}
124
125#[derive(Clone)]
126pub struct LabelledLine<'doc, Files: ReportingFiles> {
127 source_line: SourceLine<'doc, Files>,
128 label: &'doc Label<Files::Span>,
129}
130
131impl<'doc, Files: ReportingFiles> LabelledLine<'doc, Files> {
132 pub(crate) fn new(
133 source_line: SourceLine<'doc, Files>,
134 label: &'doc Label<Files::Span>,
135 ) -> LabelledLine<'doc, Files> {
136 LabelledLine { source_line, label }
137 }
138
139 pub(crate) fn mark(&self) -> &'static str {
140 match self.label.style {
141 LabelStyle::Primary => "^",
142 LabelStyle::Secondary => "-",
143 }
144 }
145
146 pub(crate) fn style(&self) -> &'static str {
147 match self.label.style {
148 LabelStyle::Primary => "primary",
149 LabelStyle::Secondary => "secondary",
150 }
151 }
152
153 pub(crate) fn message(&self) -> &Option<String> {
154 self.label.message()
155 }
156
157 pub(crate) fn source_line(&self) -> &SourceLine<'doc, Files> {
158 &self.source_line
159 }
160}