| 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 | |