mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-05-11 13:29:43 +00:00
Add file location information when failing to parse WebIDL files. (#562)
This commit is contained in:
parent
64591ef403
commit
2c69d25289
@ -8,6 +8,7 @@ readme = "./README.md"
|
|||||||
env_logger = "0.5.10"
|
env_logger = "0.5.10"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
wasm-bindgen-webidl = { path = "../webidl", version = "=0.2.14" }
|
wasm-bindgen-webidl = { path = "../webidl", version = "=0.2.14" }
|
||||||
|
sourcefile = "0.1"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = { path = "../..", version = "=0.2.14" }
|
wasm-bindgen = { path = "../..", version = "=0.2.14" }
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
extern crate wasm_bindgen_webidl;
|
extern crate wasm_bindgen_webidl;
|
||||||
|
extern crate sourcefile;
|
||||||
|
|
||||||
use failure::ResultExt;
|
use failure::{Fail, ResultExt};
|
||||||
|
use sourcefile::SourceFile;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -27,20 +29,34 @@ fn try_main() -> Result<(), failure::Error> {
|
|||||||
println!("cargo:rerun-if-changed=webidls/enabled");
|
println!("cargo:rerun-if-changed=webidls/enabled");
|
||||||
let entries = fs::read_dir("webidls/enabled").context("reading webidls/enabled directory")?;
|
let entries = fs::read_dir("webidls/enabled").context("reading webidls/enabled directory")?;
|
||||||
|
|
||||||
let mut contents = String::new();
|
let mut source = SourceFile::default();
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
let entry = entry.context("getting webidls/enabled/*.webidl entry")?;
|
let entry = entry.context("getting webidls/enabled/*.webidl entry")?;
|
||||||
if entry.path().extension() == Some(OsStr::new("webidl")) {
|
if entry.path().extension() == Some(OsStr::new("webidl")) {
|
||||||
println!("cargo:rerun-if-changed={}", entry.path().display());
|
println!("cargo:rerun-if-changed={}", entry.path().display());
|
||||||
|
source = source.add_file(entry.path())
|
||||||
let this_contents =
|
.with_context(|_| format!("reading contents of file \"{}\"",
|
||||||
fs::read_to_string(entry.path()).context("reading WebIDL file contents")?;
|
entry.path().display()))?;
|
||||||
contents.push_str(&this_contents);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let bindings = wasm_bindgen_webidl::compile(&contents)
|
let bindings = match wasm_bindgen_webidl::compile(&source.contents) {
|
||||||
.context("compiling WebIDL into wasm-bindgen bindings")?;
|
Ok(bindings) => bindings,
|
||||||
|
Err(e) => match e.kind() {
|
||||||
|
wasm_bindgen_webidl::ErrorKind::ParsingWebIDLSourcePos(pos) => {
|
||||||
|
if let Some(pos) = source.resolve_offset(pos) {
|
||||||
|
let ctx = format!("compiling WebIDL into wasm-bindgen bindings in file \
|
||||||
|
\"{}\", line {} column {}", pos.filename, pos.line + 1, pos.col + 1);
|
||||||
|
return Err(e.context(ctx).into());
|
||||||
|
} else {
|
||||||
|
return Err(e.context("compiling WebIDL into wasm-bindgen bindings").into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(e.context("compiling WebIDL into wasm-bindgen bindings").into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let out_dir = env::var("OUT_DIR").context("reading OUT_DIR environment variable")?;
|
let out_dir = env::var("OUT_DIR").context("reading OUT_DIR environment variable")?;
|
||||||
let mut out_file = fs::File::create(path::Path::new(&out_dir).join("bindings.rs"))
|
let mut out_file = fs::File::create(path::Path::new(&out_dir).join("bindings.rs"))
|
||||||
@ -51,3 +67,4 @@ fn try_main() -> Result<(), failure::Error> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ wasm-bindgen-test-project-builder = { path = "../test-project-builder", version
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
|
failure_derive = "0.1"
|
||||||
heck = "0.3"
|
heck = "0.3"
|
||||||
log = "0.4.1"
|
log = "0.4.1"
|
||||||
proc-macro2 = "0.4.8"
|
proc-macro2 = "0.4.8"
|
||||||
|
65
crates/webidl/src/error.rs
Normal file
65
crates/webidl/src/error.rs
Normal 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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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")]
|
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-webidl/0.2")]
|
||||||
|
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate failure_derive;
|
||||||
extern crate heck;
|
extern crate heck;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
@ -23,38 +25,54 @@ extern crate webidl;
|
|||||||
|
|
||||||
mod first_pass;
|
mod first_pass;
|
||||||
mod util;
|
mod util;
|
||||||
|
mod error;
|
||||||
|
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
use std::iter::{self, FromIterator};
|
use std::iter::FromIterator;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use backend::defined::{ImportedTypeDefinitions, RemoveUndefinedImports};
|
use backend::defined::{ImportedTypeDefinitions, RemoveUndefinedImports};
|
||||||
use backend::util::{ident_ty, raw_ident, rust_ident, wrap_import_function};
|
use backend::util::{ident_ty, rust_ident, wrap_import_function};
|
||||||
use failure::ResultExt;
|
use failure::{ResultExt, Fail};
|
||||||
use heck::{CamelCase, ShoutySnakeCase};
|
use heck::{CamelCase, ShoutySnakeCase};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
|
|
||||||
use first_pass::{FirstPass, FirstPassRecord};
|
use first_pass::{FirstPass, FirstPassRecord};
|
||||||
use util::{public, webidl_const_ty_to_syn_ty, webidl_const_v_to_backend_const_v, TypePosition};
|
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 use error::{Error, ErrorKind, Result};
|
||||||
pub type Result<T> = ::std::result::Result<T, failure::Error>;
|
|
||||||
|
|
||||||
/// Parse the WebIDL at the given path into a wasm-bindgen AST.
|
/// Parse the WebIDL at the given path into a wasm-bindgen AST.
|
||||||
fn parse_file(webidl_path: &Path) -> Result<backend::ast::Program> {
|
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 file = io::BufReader::new(file);
|
||||||
let mut source = String::new();
|
let mut source = String::new();
|
||||||
file.read_to_string(&mut source)
|
file.read_to_string(&mut source).context(ErrorKind::ReadingWebIDLFile)?;
|
||||||
.context("reading WebIDL file")?;
|
|
||||||
parse(&source)
|
parse(&source)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
|
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
|
||||||
fn parse(webidl_source: &str) -> Result<backend::ast::Program> {
|
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();
|
let mut first_pass_record = Default::default();
|
||||||
definitions.first_pass(&mut first_pass_record)?;
|
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 {
|
impl<'a> WebidlParse<&'a str> for webidl::ast::Iterable {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&self,
|
||||||
program: &mut backend::ast::Program,
|
_program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
_first_pass: &FirstPassRecord<'_>,
|
||||||
self_name: &'a str,
|
_self_name: &'a str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.extended_attributes) {
|
if util::is_chrome_only(&self.extended_attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user