Expand diagnostic API.

This commit is contained in:
Jesse Brault 2026-03-12 16:15:03 -05:00
parent 93eb5eb204
commit 75802e6ee4
2 changed files with 107 additions and 11 deletions

View File

@ -125,12 +125,42 @@ fn report_and_exit(
let writer = StandardStream::stderr(ColorChoice::Always);
let config = term::Config::default();
for diagnostic in diagnostics {
let csr_diagnostic = codespan_reporting::diagnostic::Diagnostic::error()
.with_message(diagnostic.message())
.with_label(Label::primary(
let mut primary_label =
Label::primary(script_file_id, diagnostic.start()..diagnostic.end());
if let Some(primary_label_message) = diagnostic.primary_label_message() {
primary_label = primary_label.with_message(primary_label_message);
}
let secondary_labels: Vec<Label<usize>> = diagnostic
.secondary_labels()
.iter()
.map(|secondary_label| {
let mut label = Label::secondary(
script_file_id,
diagnostic.start()..diagnostic.end(),
secondary_label.start()..secondary_label.end(),
);
if let Some(message) = secondary_label.message() {
label = label.with_message(message);
}
label
})
.collect();
let mut csr_diagnostic = codespan_reporting::diagnostic::Diagnostic::error()
.with_message(diagnostic.message())
.with_label(primary_label)
.with_labels(secondary_labels);
if let Some(error_code) = diagnostic.error_code() {
csr_diagnostic = csr_diagnostic.with_code(format!("E{}", error_code));
}
if let Some((reporter_file, reporter_line)) = diagnostic.reporter() {
csr_diagnostic = csr_diagnostic.with_note(format!(
"Reported by (Rust) source: {}, line {}",
reporter_file, reporter_line
));
}
term::emit_to_write_style(&mut writer.lock(), &config, files, &csr_diagnostic).unwrap();
}

View File

@ -1,20 +1,26 @@
#[derive(Debug)]
pub struct Diagnostic {
message: String,
primary_label_message: Option<String>,
error_code: Option<usize>,
start: usize,
end: usize,
reporter_file: Option<&'static str>,
reporter_line: Option<u32>,
secondary_labels: Vec<SecondaryLabel>,
}
impl Diagnostic {
pub fn new(message: &str, start: usize, end: usize) -> Self {
Self {
message: message.into(),
primary_label_message: None,
error_code: None,
start,
end,
reporter_line: None,
reporter_file: None,
secondary_labels: vec![],
}
}
@ -22,6 +28,14 @@ impl Diagnostic {
&self.message
}
pub fn primary_label_message(&self) -> Option<&str> {
self.primary_label_message.as_deref()
}
pub fn error_code(&self) -> Option<usize> {
self.error_code
}
pub fn start(&self) -> usize {
self.start
}
@ -30,13 +44,65 @@ impl Diagnostic {
self.end
}
pub fn with_reporter(&self, file: &'static str, line: u32) -> Self {
pub fn reporter(&self) -> Option<(&'static str, u32)> {
if let Some(file) = self.reporter_file {
Some((file, self.reporter_line.unwrap()))
} else {
None
}
}
pub fn secondary_labels(&self) -> &[SecondaryLabel] {
&self.secondary_labels
}
pub fn with_error_code(mut self, code: usize) -> Self {
self.error_code = Some(code);
self
}
pub fn with_primary_label_message(mut self, message: &str) -> Self {
self.primary_label_message = Some(message.into());
self
}
pub fn with_reporter(mut self, file: &'static str, line: u32) -> Self {
self.reporter_file = Some(file);
self.reporter_line = Some(line);
self
}
pub fn with_secondary_labels(mut self, labels: &[SecondaryLabel]) -> Self {
self.secondary_labels.extend_from_slice(labels);
self
}
}
#[derive(Debug, Clone)]
pub struct SecondaryLabel {
start: usize,
end: usize,
message: Option<String>,
}
impl SecondaryLabel {
pub fn new(start: usize, end: usize, message: Option<String>) -> Self {
Self {
message: self.message.clone(),
start: self.start,
end: self.end,
reporter_file: Some(file),
reporter_line: Some(line),
start,
end,
message,
}
}
pub fn start(&self) -> usize {
self.start
}
pub fn end(&self) -> usize {
self.end
}
pub fn message(&self) -> Option<&str> {
self.message.as_deref()
}
}