Fork of daniellemaywood.uk/gleam — Wasm codegen work
2

Configure Feed

Select the types of activity you want to include in your feed.

gleam / compiler-core / src / diagnostic.rs
3.7 kB 118 lines
1use camino::Utf8PathBuf; 2 3pub use codespan_reporting::diagnostic::{LabelStyle, Severity}; 4use codespan_reporting::{diagnostic::Label as CodespanLabel, files::SimpleFile}; 5use ecow::EcoString; 6use termcolor::Buffer; 7 8use crate::ast::SrcSpan; 9 10#[derive(Debug, Clone, Copy, PartialEq, Eq)] 11pub enum Level { 12 Error, 13 Warning, 14} 15 16#[derive(Debug, Clone, PartialEq, Eq)] 17pub struct Label { 18 pub text: Option<String>, 19 pub span: SrcSpan, 20} 21 22#[derive(Debug, Clone, PartialEq, Eq)] 23pub struct Location { 24 pub src: EcoString, 25 pub path: Utf8PathBuf, 26 pub label: Label, 27 pub extra_labels: Vec<Label>, 28} 29 30impl Location { 31 fn labels(&self) -> impl Iterator<Item = &Label> { 32 std::iter::once(&self.label).chain(self.extra_labels.iter()) 33 } 34} 35 36// TODO: split this into locationed diagnostics and locationless diagnostics 37#[derive(Debug, Clone, PartialEq, Eq)] 38pub struct Diagnostic { 39 pub title: String, 40 pub text: String, 41 pub level: Level, 42 pub location: Option<Location>, 43 pub hint: Option<String>, 44} 45 46impl Diagnostic { 47 pub fn write(&self, buffer: &mut Buffer) { 48 use std::io::Write; 49 match &self.location { 50 Some(location) => self.write_span(location, buffer), 51 None => self.write_title(buffer), 52 }; 53 54 if !self.text.is_empty() { 55 writeln!(buffer, "{}", self.text).expect("write text"); 56 } 57 58 if let Some(hint) = &self.hint { 59 writeln!(buffer, "Hint: {hint}").expect("write hint"); 60 } 61 } 62 63 fn write_span(&self, location: &Location, buffer: &mut Buffer) { 64 let file = SimpleFile::new(location.path.to_string(), location.src.as_str()); 65 let labels = location 66 .labels() 67 .map(|l| { 68 let label = CodespanLabel::new( 69 LabelStyle::Primary, 70 (), 71 (l.span.start as usize)..(l.span.end as usize), 72 ); 73 match &l.text { 74 None => label, 75 Some(text) => label.with_message(text.clone()), 76 } 77 }) 78 .collect(); 79 80 let severity = match self.level { 81 Level::Error => Severity::Error, 82 Level::Warning => Severity::Warning, 83 }; 84 85 let diagnostic = codespan_reporting::diagnostic::Diagnostic::new(severity) 86 .with_message(&self.title) 87 .with_labels(labels); 88 let config = codespan_reporting::term::Config::default(); 89 codespan_reporting::term::emit(buffer, &config, &file, &diagnostic) 90 .expect("write_diagnostic"); 91 } 92 93 fn write_title(&self, buffer: &mut Buffer) { 94 use std::io::Write; 95 use termcolor::{Color, ColorSpec, WriteColor}; 96 let (kind, colour) = match self.level { 97 Level::Error => ("error", Color::Red), 98 Level::Warning => ("warning", Color::Yellow), 99 }; 100 buffer 101 .set_color(ColorSpec::new().set_bold(true).set_fg(Some(colour))) 102 .expect("write_title_color1"); 103 write!(buffer, "{kind}").expect("write_title_kind"); 104 buffer 105 .set_color(ColorSpec::new().set_bold(true)) 106 .expect("write_title_color2"); 107 write!(buffer, ": {}\n\n", self.title).expect("write_title_title"); 108 buffer 109 .set_color(&ColorSpec::new()) 110 .expect("write_title_reset"); 111 } 112 113 pub fn pretty_string(&self) -> String { 114 let mut nocolor = Buffer::no_color(); 115 self.write(&mut nocolor); 116 String::from_utf8(nocolor.into_inner()).expect("Error printing produced invalid utf8") 117 } 118}