diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index 2f68534cf2..2732c5b572 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -27,15 +27,10 @@ use codespan_reporting::{ files::SimpleFile, term::{ self, - termcolor::{ColorChoice, ColorSpec, StandardStream, WriteColor}, + termcolor::{ColorChoice, NoColor, StandardStream}, }, }; -use std::{ - borrow::Cow, - convert::TryFrom, - io::{self, Write}, - ops, -}; +use std::{borrow::Cow, convert::TryFrom, ops}; use thiserror::Error; type Span = ops::Range; @@ -1320,11 +1315,16 @@ impl ParseError { /// Emits a summary of the error to a string. pub fn emit_to_string(&self, source: &str) -> String { - let files = SimpleFile::new("wgsl", source); + self.emit_to_string_with_path(source, "wgsl") + } + + /// Emits a summary of the error to a string. + pub fn emit_to_string_with_path(&self, source: &str, path: &str) -> String { + let files = SimpleFile::new(path, source); let config = codespan_reporting::term::Config::default(); - let mut writer = StringErrorBuffer::new(); + let mut writer = NoColor::new(Vec::new()); term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error"); - writer.into_string() + String::from_utf8(writer.into_inner()).unwrap() } /// Returns a [`SourceLocation`] for the first label in the error message. @@ -4556,42 +4556,3 @@ impl Parser { pub fn parse_str(source: &str) -> Result { Parser::new().parse(source) } - -pub struct StringErrorBuffer { - buf: Vec, -} - -impl StringErrorBuffer { - pub const fn new() -> Self { - Self { buf: Vec::new() } - } - - pub fn into_string(self) -> String { - String::from_utf8(self.buf).unwrap() - } -} - -impl Write for StringErrorBuffer { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.buf.extend(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl WriteColor for StringErrorBuffer { - fn supports_color(&self) -> bool { - false - } - - fn set_color(&mut self, _spec: &ColorSpec) -> io::Result<()> { - Ok(()) - } - - fn reset(&mut self) -> io::Result<()> { - Ok(()) - } -} diff --git a/src/span.rs b/src/span.rs index 6f2583a5eb..a4670e2dad 100644 --- a/src/span.rs +++ b/src/span.rs @@ -236,6 +236,83 @@ impl WithSpan { pub fn location(&self, _source: &str) -> Option { None } + + #[cfg(feature = "span")] + fn diagnostic(&self) -> codespan_reporting::diagnostic::Diagnostic<()> + where + E: Error, + { + use codespan_reporting::diagnostic::{Diagnostic, Label}; + let diagnostic = Diagnostic::error() + .with_message(self.inner.to_string()) + .with_labels( + self.spans() + .map(|&(span, ref desc)| { + Label::primary((), span.to_range().unwrap()).with_message(desc.to_owned()) + }) + .collect(), + ) + .with_notes({ + let mut notes = Vec::new(); + let mut source: &dyn Error = &self.inner; + while let Some(next) = Error::source(source) { + notes.push(next.to_string()); + source = next; + } + notes + }); + diagnostic + } + + /// Emits a summary of the error to standard error stream. + #[cfg(feature = "span")] + pub fn emit_to_stderr(&self, source: &str) + where + E: Error, + { + self.emit_to_stderr_with_path(source, "wgsl") + } + + /// Emits a summary of the error to standard error stream. + #[cfg(feature = "span")] + pub fn emit_to_stderr_with_path(&self, source: &str, path: &str) + where + E: Error, + { + use codespan_reporting::{files, term}; + use term::termcolor::{ColorChoice, StandardStream}; + + let files = files::SimpleFile::new(path, source); + let config = term::Config::default(); + let writer = StandardStream::stderr(ColorChoice::Auto); + term::emit(&mut writer.lock(), &config, &files, &self.diagnostic()) + .expect("cannot write error"); + } + + /// Emits a summary of the error to a string. + #[cfg(feature = "span")] + pub fn emit_to_string(&self, source: &str) -> String + where + E: Error, + { + self.emit_to_string_with_path(source, "wgsl") + } + + /// Emits a summary of the error to a string. + #[cfg(feature = "span")] + pub fn emit_to_string_with_path(&self, source: &str, path: &str) -> String + where + E: Error, + { + use codespan_reporting::{files, term}; + use term::termcolor::NoColor; + + let files = files::SimpleFile::new(path, source); + let config = codespan_reporting::term::Config::default(); + let mut writer = NoColor::new(Vec::new()); + term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error"); + String::from_utf8(writer.into_inner()).unwrap() + } } /// Convenience trait for [`Error`] to be able to apply spans to anything.