1e73685ebSopenharmony_ci//! Diagnostic data structures. 2e73685ebSopenharmony_ci 3e73685ebSopenharmony_ci#[cfg(feature = "serialization")] 4e73685ebSopenharmony_ciuse serde::{Deserialize, Serialize}; 5e73685ebSopenharmony_ciuse std::ops::Range; 6e73685ebSopenharmony_ci 7e73685ebSopenharmony_ci/// A severity level for diagnostic messages. 8e73685ebSopenharmony_ci/// 9e73685ebSopenharmony_ci/// These are ordered in the following way: 10e73685ebSopenharmony_ci/// 11e73685ebSopenharmony_ci/// ```rust 12e73685ebSopenharmony_ci/// use codespan_reporting::diagnostic::Severity; 13e73685ebSopenharmony_ci/// 14e73685ebSopenharmony_ci/// assert!(Severity::Bug > Severity::Error); 15e73685ebSopenharmony_ci/// assert!(Severity::Error > Severity::Warning); 16e73685ebSopenharmony_ci/// assert!(Severity::Warning > Severity::Note); 17e73685ebSopenharmony_ci/// assert!(Severity::Note > Severity::Help); 18e73685ebSopenharmony_ci/// ``` 19e73685ebSopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 20e73685ebSopenharmony_ci#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 21e73685ebSopenharmony_cipub enum Severity { 22e73685ebSopenharmony_ci /// An unexpected bug. 23e73685ebSopenharmony_ci Bug, 24e73685ebSopenharmony_ci /// An error. 25e73685ebSopenharmony_ci Error, 26e73685ebSopenharmony_ci /// A warning. 27e73685ebSopenharmony_ci Warning, 28e73685ebSopenharmony_ci /// A note. 29e73685ebSopenharmony_ci Note, 30e73685ebSopenharmony_ci /// A help message. 31e73685ebSopenharmony_ci Help, 32e73685ebSopenharmony_ci} 33e73685ebSopenharmony_ci 34e73685ebSopenharmony_ciimpl Severity { 35e73685ebSopenharmony_ci /// We want bugs to be the maximum severity, errors next, etc... 36e73685ebSopenharmony_ci fn to_cmp_int(self) -> u8 { 37e73685ebSopenharmony_ci match self { 38e73685ebSopenharmony_ci Severity::Bug => 5, 39e73685ebSopenharmony_ci Severity::Error => 4, 40e73685ebSopenharmony_ci Severity::Warning => 3, 41e73685ebSopenharmony_ci Severity::Note => 2, 42e73685ebSopenharmony_ci Severity::Help => 1, 43e73685ebSopenharmony_ci } 44e73685ebSopenharmony_ci } 45e73685ebSopenharmony_ci} 46e73685ebSopenharmony_ci 47e73685ebSopenharmony_ciimpl PartialOrd for Severity { 48e73685ebSopenharmony_ci fn partial_cmp(&self, other: &Severity) -> Option<std::cmp::Ordering> { 49e73685ebSopenharmony_ci u8::partial_cmp(&self.to_cmp_int(), &other.to_cmp_int()) 50e73685ebSopenharmony_ci } 51e73685ebSopenharmony_ci} 52e73685ebSopenharmony_ci 53e73685ebSopenharmony_ci#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd)] 54e73685ebSopenharmony_ci#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 55e73685ebSopenharmony_cipub enum LabelStyle { 56e73685ebSopenharmony_ci /// Labels that describe the primary cause of a diagnostic. 57e73685ebSopenharmony_ci Primary, 58e73685ebSopenharmony_ci /// Labels that provide additional context for a diagnostic. 59e73685ebSopenharmony_ci Secondary, 60e73685ebSopenharmony_ci} 61e73685ebSopenharmony_ci 62e73685ebSopenharmony_ci/// A label describing an underlined region of code associated with a diagnostic. 63e73685ebSopenharmony_ci#[derive(Clone, Debug, PartialEq, Eq)] 64e73685ebSopenharmony_ci#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 65e73685ebSopenharmony_cipub struct Label<FileId> { 66e73685ebSopenharmony_ci /// The style of the label. 67e73685ebSopenharmony_ci pub style: LabelStyle, 68e73685ebSopenharmony_ci /// The file that we are labelling. 69e73685ebSopenharmony_ci pub file_id: FileId, 70e73685ebSopenharmony_ci /// The range in bytes we are going to include in the final snippet. 71e73685ebSopenharmony_ci pub range: Range<usize>, 72e73685ebSopenharmony_ci /// An optional message to provide some additional information for the 73e73685ebSopenharmony_ci /// underlined code. These should not include line breaks. 74e73685ebSopenharmony_ci pub message: String, 75e73685ebSopenharmony_ci} 76e73685ebSopenharmony_ci 77e73685ebSopenharmony_ciimpl<FileId> Label<FileId> { 78e73685ebSopenharmony_ci /// Create a new label. 79e73685ebSopenharmony_ci pub fn new( 80e73685ebSopenharmony_ci style: LabelStyle, 81e73685ebSopenharmony_ci file_id: FileId, 82e73685ebSopenharmony_ci range: impl Into<Range<usize>>, 83e73685ebSopenharmony_ci ) -> Label<FileId> { 84e73685ebSopenharmony_ci Label { 85e73685ebSopenharmony_ci style, 86e73685ebSopenharmony_ci file_id, 87e73685ebSopenharmony_ci range: range.into(), 88e73685ebSopenharmony_ci message: String::new(), 89e73685ebSopenharmony_ci } 90e73685ebSopenharmony_ci } 91e73685ebSopenharmony_ci 92e73685ebSopenharmony_ci /// Create a new label with a style of [`LabelStyle::Primary`]. 93e73685ebSopenharmony_ci /// 94e73685ebSopenharmony_ci /// [`LabelStyle::Primary`]: LabelStyle::Primary 95e73685ebSopenharmony_ci pub fn primary(file_id: FileId, range: impl Into<Range<usize>>) -> Label<FileId> { 96e73685ebSopenharmony_ci Label::new(LabelStyle::Primary, file_id, range) 97e73685ebSopenharmony_ci } 98e73685ebSopenharmony_ci 99e73685ebSopenharmony_ci /// Create a new label with a style of [`LabelStyle::Secondary`]. 100e73685ebSopenharmony_ci /// 101e73685ebSopenharmony_ci /// [`LabelStyle::Secondary`]: LabelStyle::Secondary 102e73685ebSopenharmony_ci pub fn secondary(file_id: FileId, range: impl Into<Range<usize>>) -> Label<FileId> { 103e73685ebSopenharmony_ci Label::new(LabelStyle::Secondary, file_id, range) 104e73685ebSopenharmony_ci } 105e73685ebSopenharmony_ci 106e73685ebSopenharmony_ci /// Add a message to the diagnostic. 107e73685ebSopenharmony_ci pub fn with_message(mut self, message: impl Into<String>) -> Label<FileId> { 108e73685ebSopenharmony_ci self.message = message.into(); 109e73685ebSopenharmony_ci self 110e73685ebSopenharmony_ci } 111e73685ebSopenharmony_ci} 112e73685ebSopenharmony_ci 113e73685ebSopenharmony_ci/// Represents a diagnostic message that can provide information like errors and 114e73685ebSopenharmony_ci/// warnings to the user. 115e73685ebSopenharmony_ci/// 116e73685ebSopenharmony_ci/// The position of a Diagnostic is considered to be the position of the [`Label`] that has the earliest starting position and has the highest style which appears in all the labels of the diagnostic. 117e73685ebSopenharmony_ci#[derive(Clone, Debug, PartialEq, Eq)] 118e73685ebSopenharmony_ci#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))] 119e73685ebSopenharmony_cipub struct Diagnostic<FileId> { 120e73685ebSopenharmony_ci /// The overall severity of the diagnostic 121e73685ebSopenharmony_ci pub severity: Severity, 122e73685ebSopenharmony_ci /// An optional code that identifies this diagnostic. 123e73685ebSopenharmony_ci pub code: Option<String>, 124e73685ebSopenharmony_ci /// The main message associated with this diagnostic. 125e73685ebSopenharmony_ci /// 126e73685ebSopenharmony_ci /// These should not include line breaks, and in order support the 'short' 127e73685ebSopenharmony_ci /// diagnostic display mod, the message should be specific enough to make 128e73685ebSopenharmony_ci /// sense on its own, without additional context provided by labels and notes. 129e73685ebSopenharmony_ci pub message: String, 130e73685ebSopenharmony_ci /// Source labels that describe the cause of the diagnostic. 131e73685ebSopenharmony_ci /// The order of the labels inside the vector does not have any meaning. 132e73685ebSopenharmony_ci /// The labels are always arranged in the order they appear in the source code. 133e73685ebSopenharmony_ci pub labels: Vec<Label<FileId>>, 134e73685ebSopenharmony_ci /// Notes that are associated with the primary cause of the diagnostic. 135e73685ebSopenharmony_ci /// These can include line breaks for improved formatting. 136e73685ebSopenharmony_ci pub notes: Vec<String>, 137e73685ebSopenharmony_ci} 138e73685ebSopenharmony_ci 139e73685ebSopenharmony_ciimpl<FileId> Diagnostic<FileId> { 140e73685ebSopenharmony_ci /// Create a new diagnostic. 141e73685ebSopenharmony_ci pub fn new(severity: Severity) -> Diagnostic<FileId> { 142e73685ebSopenharmony_ci Diagnostic { 143e73685ebSopenharmony_ci severity, 144e73685ebSopenharmony_ci code: None, 145e73685ebSopenharmony_ci message: String::new(), 146e73685ebSopenharmony_ci labels: Vec::new(), 147e73685ebSopenharmony_ci notes: Vec::new(), 148e73685ebSopenharmony_ci } 149e73685ebSopenharmony_ci } 150e73685ebSopenharmony_ci 151e73685ebSopenharmony_ci /// Create a new diagnostic with a severity of [`Severity::Bug`]. 152e73685ebSopenharmony_ci /// 153e73685ebSopenharmony_ci /// [`Severity::Bug`]: Severity::Bug 154e73685ebSopenharmony_ci pub fn bug() -> Diagnostic<FileId> { 155e73685ebSopenharmony_ci Diagnostic::new(Severity::Bug) 156e73685ebSopenharmony_ci } 157e73685ebSopenharmony_ci 158e73685ebSopenharmony_ci /// Create a new diagnostic with a severity of [`Severity::Error`]. 159e73685ebSopenharmony_ci /// 160e73685ebSopenharmony_ci /// [`Severity::Error`]: Severity::Error 161e73685ebSopenharmony_ci pub fn error() -> Diagnostic<FileId> { 162e73685ebSopenharmony_ci Diagnostic::new(Severity::Error) 163e73685ebSopenharmony_ci } 164e73685ebSopenharmony_ci 165e73685ebSopenharmony_ci /// Create a new diagnostic with a severity of [`Severity::Warning`]. 166e73685ebSopenharmony_ci /// 167e73685ebSopenharmony_ci /// [`Severity::Warning`]: Severity::Warning 168e73685ebSopenharmony_ci pub fn warning() -> Diagnostic<FileId> { 169e73685ebSopenharmony_ci Diagnostic::new(Severity::Warning) 170e73685ebSopenharmony_ci } 171e73685ebSopenharmony_ci 172e73685ebSopenharmony_ci /// Create a new diagnostic with a severity of [`Severity::Note`]. 173e73685ebSopenharmony_ci /// 174e73685ebSopenharmony_ci /// [`Severity::Note`]: Severity::Note 175e73685ebSopenharmony_ci pub fn note() -> Diagnostic<FileId> { 176e73685ebSopenharmony_ci Diagnostic::new(Severity::Note) 177e73685ebSopenharmony_ci } 178e73685ebSopenharmony_ci 179e73685ebSopenharmony_ci /// Create a new diagnostic with a severity of [`Severity::Help`]. 180e73685ebSopenharmony_ci /// 181e73685ebSopenharmony_ci /// [`Severity::Help`]: Severity::Help 182e73685ebSopenharmony_ci pub fn help() -> Diagnostic<FileId> { 183e73685ebSopenharmony_ci Diagnostic::new(Severity::Help) 184e73685ebSopenharmony_ci } 185e73685ebSopenharmony_ci 186e73685ebSopenharmony_ci /// Add an error code to the diagnostic. 187e73685ebSopenharmony_ci pub fn with_code(mut self, code: impl Into<String>) -> Diagnostic<FileId> { 188e73685ebSopenharmony_ci self.code = Some(code.into()); 189e73685ebSopenharmony_ci self 190e73685ebSopenharmony_ci } 191e73685ebSopenharmony_ci 192e73685ebSopenharmony_ci /// Add a message to the diagnostic. 193e73685ebSopenharmony_ci pub fn with_message(mut self, message: impl Into<String>) -> Diagnostic<FileId> { 194e73685ebSopenharmony_ci self.message = message.into(); 195e73685ebSopenharmony_ci self 196e73685ebSopenharmony_ci } 197e73685ebSopenharmony_ci 198e73685ebSopenharmony_ci /// Add some labels to the diagnostic. 199e73685ebSopenharmony_ci pub fn with_labels(mut self, labels: Vec<Label<FileId>>) -> Diagnostic<FileId> { 200e73685ebSopenharmony_ci self.labels = labels; 201e73685ebSopenharmony_ci self 202e73685ebSopenharmony_ci } 203e73685ebSopenharmony_ci 204e73685ebSopenharmony_ci /// Add some notes to the diagnostic. 205e73685ebSopenharmony_ci pub fn with_notes(mut self, notes: Vec<String>) -> Diagnostic<FileId> { 206e73685ebSopenharmony_ci self.notes = notes; 207e73685ebSopenharmony_ci self 208e73685ebSopenharmony_ci } 209e73685ebSopenharmony_ci} 210