1 | //! This module contains `Diagnostic` and the types/functions it uses for deserialization. |
2 | |
3 | #[cfg (feature = "builder" )] |
4 | use derive_builder::Builder; |
5 | use serde::{Deserialize, Serialize}; |
6 | use std::fmt; |
7 | |
8 | /// The error code associated to this diagnostic. |
9 | #[derive (Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] |
10 | #[cfg_attr (feature = "builder" , derive(Builder))] |
11 | #[non_exhaustive ] |
12 | #[cfg_attr (feature = "builder" , builder(pattern = "owned" , setter(into)))] |
13 | pub struct DiagnosticCode { |
14 | /// The code itself. |
15 | pub code: String, |
16 | /// An explanation for the code |
17 | pub explanation: Option<String>, |
18 | } |
19 | |
20 | /// A line of code associated with the Diagnostic |
21 | #[derive (Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] |
22 | #[cfg_attr (feature = "builder" , derive(Builder))] |
23 | #[non_exhaustive ] |
24 | #[cfg_attr (feature = "builder" , builder(pattern = "owned" , setter(into)))] |
25 | pub struct DiagnosticSpanLine { |
26 | /// The line of code associated with the error |
27 | pub text: String, |
28 | /// Start of the section of the line to highlight. 1-based, character offset in self.text |
29 | pub highlight_start: usize, |
30 | /// End of the section of the line to highlight. 1-based, character offset in self.text |
31 | pub highlight_end: usize, |
32 | } |
33 | |
34 | /// Macro expansion information associated with a diagnostic. |
35 | #[derive (Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] |
36 | #[cfg_attr (feature = "builder" , derive(Builder))] |
37 | #[non_exhaustive ] |
38 | #[cfg_attr (feature = "builder" , builder(pattern = "owned" , setter(into)))] |
39 | pub struct DiagnosticSpanMacroExpansion { |
40 | /// span where macro was applied to generate this code; note that |
41 | /// this may itself derive from a macro (if |
42 | /// `span.expansion.is_some()`) |
43 | pub span: DiagnosticSpan, |
44 | |
45 | /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]") |
46 | pub macro_decl_name: String, |
47 | |
48 | /// span where macro was defined (if known) |
49 | pub def_site_span: Option<DiagnosticSpan>, |
50 | } |
51 | |
52 | /// A section of the source code associated with a Diagnostic |
53 | #[derive (Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] |
54 | #[cfg_attr (feature = "builder" , derive(Builder))] |
55 | #[non_exhaustive ] |
56 | #[cfg_attr (feature = "builder" , builder(pattern = "owned" , setter(into)))] |
57 | pub struct DiagnosticSpan { |
58 | /// The file name or the macro name this diagnostic comes from. |
59 | pub file_name: String, |
60 | /// The byte offset in the file where this diagnostic starts from. |
61 | pub byte_start: u32, |
62 | /// The byte offset in the file where this diagnostic ends. |
63 | pub byte_end: u32, |
64 | /// 1-based. The line in the file. |
65 | pub line_start: usize, |
66 | /// 1-based. The line in the file. |
67 | pub line_end: usize, |
68 | /// 1-based, character offset. |
69 | pub column_start: usize, |
70 | /// 1-based, character offset. |
71 | pub column_end: usize, |
72 | /// Is this a "primary" span -- meaning the point, or one of the points, |
73 | /// where the error occurred? |
74 | /// |
75 | /// There are rare cases where multiple spans are marked as primary, |
76 | /// e.g. "immutable borrow occurs here" and "mutable borrow ends here" can |
77 | /// be two separate spans both "primary". Top (parent) messages should |
78 | /// always have at least one primary span, unless it has 0 spans. Child |
79 | /// messages may have 0 or more primary spans. |
80 | pub is_primary: bool, |
81 | /// Source text from the start of line_start to the end of line_end. |
82 | pub text: Vec<DiagnosticSpanLine>, |
83 | /// Label that should be placed at this location (if any) |
84 | pub label: Option<String>, |
85 | /// If we are suggesting a replacement, this will contain text |
86 | /// that should be sliced in atop this span. |
87 | pub suggested_replacement: Option<String>, |
88 | /// If the suggestion is approximate |
89 | pub suggestion_applicability: Option<Applicability>, |
90 | /// Macro invocations that created the code at this span, if any. |
91 | pub expansion: Option<Box<DiagnosticSpanMacroExpansion>>, |
92 | } |
93 | |
94 | /// Whether a suggestion can be safely applied. |
95 | #[derive (Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] |
96 | #[non_exhaustive ] |
97 | pub enum Applicability { |
98 | /// The suggested replacement can be applied automatically safely |
99 | MachineApplicable, |
100 | /// The suggested replacement has placeholders that will need to be manually |
101 | /// replaced. |
102 | HasPlaceholders, |
103 | /// The suggested replacement may be incorrect in some circumstances. Needs |
104 | /// human review. |
105 | MaybeIncorrect, |
106 | /// The suggested replacement will probably not work. |
107 | Unspecified, |
108 | } |
109 | |
110 | /// The diagnostic level |
111 | #[derive (Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)] |
112 | #[non_exhaustive ] |
113 | #[serde(rename_all = "lowercase" )] |
114 | pub enum DiagnosticLevel { |
115 | /// Internal compiler error |
116 | #[serde(rename = "error: internal compiler error" )] |
117 | Ice, |
118 | /// Error |
119 | Error, |
120 | /// Warning |
121 | Warning, |
122 | /// Failure note |
123 | #[serde(rename = "failure-note" )] |
124 | FailureNote, |
125 | /// Note |
126 | Note, |
127 | /// Help |
128 | Help, |
129 | } |
130 | |
131 | /// A diagnostic message generated by rustc |
132 | #[derive (Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] |
133 | #[cfg_attr (feature = "builder" , derive(Builder))] |
134 | #[non_exhaustive ] |
135 | #[cfg_attr (feature = "builder" , builder(pattern = "owned" , setter(into)))] |
136 | pub struct Diagnostic { |
137 | /// The error message of this diagnostic. |
138 | pub message: String, |
139 | /// The associated error code for this diagnostic |
140 | pub code: Option<DiagnosticCode>, |
141 | /// "error: internal compiler error", "error", "warning", "note", "help" |
142 | pub level: DiagnosticLevel, |
143 | /// A list of source code spans this diagnostic is associated with. |
144 | pub spans: Vec<DiagnosticSpan>, |
145 | /// Associated diagnostic messages. |
146 | pub children: Vec<Diagnostic>, |
147 | /// The message as rustc would render it |
148 | pub rendered: Option<String>, |
149 | } |
150 | |
151 | impl fmt::Display for Diagnostic { |
152 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
153 | if let Some(ref rendered: &String) = self.rendered { |
154 | f.write_str(data:rendered)?; |
155 | } else { |
156 | f.write_str(data:"cargo didn't render this message" )?; |
157 | } |
158 | Ok(()) |
159 | } |
160 | } |
161 | |