diff options
Diffstat (limited to 'src/errors/mod.rs')
-rw-r--r-- | src/errors/mod.rs | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/errors/mod.rs b/src/errors/mod.rs new file mode 100644 index 0000000..b0bf7e4 --- /dev/null +++ b/src/errors/mod.rs @@ -0,0 +1,71 @@ +mod file_error; +mod merge_error; +mod resolver_error; + +pub use file_error::*; +pub use merge_error::*; +pub use resolver_error::*; + +use crate::*; + +use ansi::*; +use log::LogLevel; + + +pub fn report_source_issue(level: LogLevel, context: &Context, message: &str) { + // Prepare variables. + let in_merged = &context.source.in_merged; + let line_num = in_merged.start.line + 1; + let digits = line_num.to_string().len(); + let w = digits + 3; + let arrow = "-->"; + let mut string = message.to_string(); + + macro_rules! push { + ($($tokens:tt)*) => { string.push_str(&format!($($tokens)*)) }; + } + + // Format message and locations. + push!("{NORMAL}\n"); + push!("{BLUE}{arrow:>w$}{NORMAL} {in_merged}\n", w=w); + if let Some(in_source) = &context.source.in_source { + push!("{BLUE}{arrow:>w$}{NORMAL} {in_source}\n", w=w); + } + + // Format source context. + let left = in_merged.start.column; + let right = in_merged.end.column + 1; + let source_line = context.source_code.split('\n').nth(in_merged.start.line) + .unwrap_or("<error reading line from source>"); + let space = " "; + let colour = match level { + LogLevel::Info => BLUE, + LogLevel::Warn => YELLOW, + LogLevel::Error => RED, + LogLevel::Fatal => RED, + }; + + // Print source code line. + push!("{BLUE} {line_num} | {NORMAL}"); + for (i, c) in source_line.chars().enumerate() { + if i == left { push!("{colour}") } + if i == right { push!("{NORMAL}") } + push!("{c}"); + } + push!("{NORMAL}\n"); + + // Print source code underline. + push!("{BLUE} {space:>w$} | {NORMAL}", w=digits); + for _ in 0..left { push!(" "); } + push!("{colour}"); + for _ in left..right { push!("^"); } + push!("{NORMAL}"); + + // Print the completed message. + match level { + LogLevel::Info => log::info!( "{}", string), + LogLevel::Warn => log::warn!( "{}", string), + LogLevel::Error => log::error!("{}", string), + LogLevel::Fatal => log::fatal!("{}", string), + } +} |