From 56196551b89426633e754201c8f70b61093af32e Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Thu, 20 Aug 2026 20:02:23 -0500 Subject: [PATCH] Add better error reporting for repl. --- dm/src/common.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ dm/src/main.rs | 4 +++- dm/src/repl.rs | 13 +++++++++++-- dm/src/run.rs | 40 ++-------------------------------------- 4 files changed, 59 insertions(+), 41 deletions(-) create mode 100644 dm/src/common.rs diff --git a/dm/src/common.rs b/dm/src/common.rs new file mode 100644 index 0000000..9f4325b --- /dev/null +++ b/dm/src/common.rs @@ -0,0 +1,43 @@ +use codespan_reporting::diagnostic::Label; +use dmc_lib::diagnostic::Diagnostic; + +pub fn to_csr_diagnostic( + file_id: usize, + diagnostic: &Diagnostic, +) -> codespan_reporting::diagnostic::Diagnostic { + let mut primary_label = Label::primary(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> = diagnostic + .secondary_labels() + .iter() + .map(|secondary_label| { + let mut label = + Label::secondary(file_id, 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{:04}", 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 + )); + } + + csr_diagnostic +} diff --git a/dm/src/main.rs b/dm/src/main.rs index 51a233e..d756d24 100644 --- a/dm/src/main.rs +++ b/dm/src/main.rs @@ -1,9 +1,11 @@ +mod common; mod repl; mod run; use crate::repl::repl; use crate::run::compile_and_run_script; use clap::{Parser, Subcommand}; +use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; use std::io; use std::path::PathBuf; @@ -47,7 +49,7 @@ fn main() { repl( &mut io::stdin().lock(), &mut io::stdout().lock(), - &mut io::stderr().lock(), + &mut StandardStream::stderr(ColorChoice::Always), register_count, ); } diff --git a/dm/src/repl.rs b/dm/src/repl.rs index dda915b..5bfde99 100644 --- a/dm/src/repl.rs +++ b/dm/src/repl.rs @@ -1,3 +1,6 @@ +use crate::common::to_csr_diagnostic; +use codespan_reporting::files::SimpleFiles; +use codespan_reporting::term::{Config, WriteStyle, emit_to_write_style}; use dmc_lib::SyntheticFunctionSession; use dmc_lib::constants_table::ConstantsTable; use dmc_lib::diagnostic::Diagnostics; @@ -11,9 +14,13 @@ use std::io::{BufRead, Write}; pub fn repl( read: &mut impl BufRead, out: &mut impl Write, - err: &mut impl Write, + err: &mut impl WriteStyle, register_count: usize, ) { + let diagnostics_config = Config::default(); + let mut files: SimpleFiles<&str, String> = SimpleFiles::new(); + let mut current_file_id; + let mut buffer = String::new(); let mut session = SyntheticFunctionSession::new("__repl"); @@ -48,8 +55,10 @@ pub fn repl( .insert(function.name_owned(), function); } Err(diagnostics) => { + current_file_id = files.add("input", String::from(input)); for diagnostic in diagnostics { - writeln!(err, "{}", diagnostic.message()).unwrap(); + let csr_diagnostic = to_csr_diagnostic(current_file_id, &diagnostic); + emit_to_write_style(err, &diagnostics_config, &files, &csr_diagnostic).unwrap(); } buffer.clear(); continue 'repl; diff --git a/dm/src/run.rs b/dm/src/run.rs index d42889d..37226c9 100644 --- a/dm/src/run.rs +++ b/dm/src/run.rs @@ -1,4 +1,4 @@ -use codespan_reporting::diagnostic::Label; +use crate::common::to_csr_diagnostic; use codespan_reporting::files::SimpleFiles; use codespan_reporting::term; use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; @@ -88,43 +88,7 @@ fn report_and_exit( let writer = StandardStream::stderr(ColorChoice::Always); let config = term::Config::default(); for diagnostic in diagnostics { - 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> = diagnostic - .secondary_labels() - .iter() - .map(|secondary_label| { - let mut label = Label::secondary( - script_file_id, - 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{:04}", 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 - )); - } - + let csr_diagnostic = to_csr_diagnostic(script_file_id, diagnostic); term::emit_to_write_style(&mut writer.lock(), &config, files, &csr_diagnostic).unwrap(); } if diagnostics.len() == 1 {