add emit_to_{stderr,string} helpers for validation errors (#2012)

Mirrors those already found for parse errors.

Also removes the `StringErrorBuffer` writer in favor of the existing `NoColor` writer (from `codespan`) and added the emit_to_string_with_path method to complete the set.
This commit is contained in:
Christofer Nolander
2022-08-06 23:48:07 +02:00
committed by GitHub
parent c6f34fa4d8
commit cfbc91d6cf
2 changed files with 87 additions and 49 deletions

View File

@@ -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<usize>;
@@ -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<crate::Module, ParseError> {
Parser::new().parse(source)
}
pub struct StringErrorBuffer {
buf: Vec<u8>,
}
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<usize> {
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(())
}
}

View File

@@ -236,6 +236,83 @@ impl<E> WithSpan<E> {
pub fn location(&self, _source: &str) -> Option<SourceLocation> {
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.