Add file location information when failing to parse WebIDL files. (#562)

This commit is contained in:
Richard Dodd (dodj)
2018-07-26 18:09:04 +01:00
committed by Alex Crichton
parent 64591ef403
commit 2c69d25289
5 changed files with 122 additions and 20 deletions

View File

@ -16,6 +16,7 @@ wasm-bindgen-test-project-builder = { path = "../test-project-builder", version
[dependencies]
failure = "0.1"
failure_derive = "0.1"
heck = "0.3"
log = "0.4.1"
proc-macro2 = "0.4.8"

View File

@ -0,0 +1,65 @@
use failure::{Backtrace, Context, Fail};
use std::fmt;
/// Either `Ok(t)` or `Err(Error)`.
pub type Result<T> = ::std::result::Result<T, Error>;
/// The different contexts an error can occur in in this crate.
#[derive(Debug, Fail, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ErrorKind {
/// Failed to open a WebIDL file.
#[fail(display="opening WebIDL file")]
OpeningWebIDLFile,
/// Failed to read a WebIDL file.
#[fail(display="reading WebIDL file")]
ReadingWebIDLFile,
/// Failed to parse a WebIDL file.
#[fail(display="parsing WebIDL source text at {}", _0)]
ParsingWebIDLSourcePos(usize),
/// Failed to parse a WebIDL file.
#[fail(display="parsing WebIDL source text")]
ParsingWebIDLSource,
}
/// The error type for this crate.
#[derive(Debug)]
pub struct Error {
inner: Context<ErrorKind>,
}
impl Fail for Error {
fn cause(&self) -> Option<&Fail> {
self.inner.cause()
}
fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.inner, f)
}
}
impl Error {
/// The context for this error.
pub fn kind(&self) -> ErrorKind {
*self.inner.get_context()
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error { inner: Context::new(kind) }
}
}
impl From<Context<ErrorKind>> for Error {
fn from(inner: Context<ErrorKind>) -> Error {
Error { inner: inner }
}
}

View File

@ -10,6 +10,8 @@ emitted for the types and methods described in the WebIDL.
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-webidl/0.2")]
extern crate failure;
#[macro_use]
extern crate failure_derive;
extern crate heck;
#[macro_use]
extern crate log;
@ -23,38 +25,54 @@ extern crate webidl;
mod first_pass;
mod util;
mod error;
use std::collections::BTreeSet;
use std::fs;
use std::io::{self, Read};
use std::iter::{self, FromIterator};
use std::iter::FromIterator;
use std::path::Path;
use backend::defined::{ImportedTypeDefinitions, RemoveUndefinedImports};
use backend::util::{ident_ty, raw_ident, rust_ident, wrap_import_function};
use failure::ResultExt;
use backend::util::{ident_ty, rust_ident, wrap_import_function};
use failure::{ResultExt, Fail};
use heck::{CamelCase, ShoutySnakeCase};
use quote::ToTokens;
use first_pass::{FirstPass, FirstPassRecord};
use util::{public, webidl_const_ty_to_syn_ty, webidl_const_v_to_backend_const_v, TypePosition};
/// Either `Ok(t)` or `Err(failure::Error)`.
pub type Result<T> = ::std::result::Result<T, failure::Error>;
pub use error::{Error, ErrorKind, Result};
/// Parse the WebIDL at the given path into a wasm-bindgen AST.
fn parse_file(webidl_path: &Path) -> Result<backend::ast::Program> {
let file = fs::File::open(webidl_path).context("opening WebIDL file")?;
let file = fs::File::open(webidl_path).context(ErrorKind::OpeningWebIDLFile)?;
let mut file = io::BufReader::new(file);
let mut source = String::new();
file.read_to_string(&mut source)
.context("reading WebIDL file")?;
file.read_to_string(&mut source).context(ErrorKind::ReadingWebIDLFile)?;
parse(&source)
}
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
fn parse(webidl_source: &str) -> Result<backend::ast::Program> {
let definitions = webidl::parse_string(webidl_source).context("parsing WebIDL source text")?;
let definitions = match webidl::parse_string(webidl_source) {
Ok(def) => def,
Err(e) => {
let kind = match &e {
webidl::ParseError::InvalidToken { location } => {
ErrorKind::ParsingWebIDLSourcePos(*location)
}
webidl::ParseError::UnrecognizedToken { token: Some((start, ..)), .. } => {
ErrorKind::ParsingWebIDLSourcePos(*start)
}
webidl::ParseError::ExtraToken { token: (start, ..) } => {
ErrorKind::ParsingWebIDLSourcePos(*start)
},
_ => ErrorKind::ParsingWebIDLSource
};
return Err(e.context(kind).into());
}
};
let mut first_pass_record = Default::default();
definitions.first_pass(&mut first_pass_record)?;
@ -528,9 +546,9 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::RegularAttribute {
impl<'a> WebidlParse<&'a str> for webidl::ast::Iterable {
fn webidl_parse(
&self,
program: &mut backend::ast::Program,
first_pass: &FirstPassRecord<'_>,
self_name: &'a str,
_program: &mut backend::ast::Program,
_first_pass: &FirstPassRecord<'_>,
_self_name: &'a str,
) -> Result<()> {
if util::is_chrome_only(&self.extended_attributes) {
return Ok(());