mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-13 21:11:22 +00:00
Prepare to have targeted error diagnostics (#604)
This commit starts to add infrastructure for targeted diagnostics in the `#[wasm_bindgen]` attribute, intended eventually at providing much better errors as they'll be pointing to exactly the code in question rather than always to a `#[wasm_bindgen]` attribute. The general changes are are: * A new `Diagnostic` error type is added to the backend. A `Diagnostic` is created with a textual error or with a span, and it can also be created from a list of diagnostics. A `Diagnostic` implements `ToTokens` which emits a bunch of invocations of `compile_error!` that will cause rustc to later generate errors. * Fallible implementations of `ToTokens` have switched to using a new trait, `TryToTokens`, which returns a `Result` to use `?` with. * The `MacroParse` trait has changed to returning a `Result` to propagate errors upwards. * A new `ui-tests` crate was added which uses `compiletest_rs` to add UI tests. These UI tests will verify that our output improves over time and does not regress. This test suite is added to CI as a new builder as well. * No `Diagnostic` instances are created just yet, everything continues to panic and return `Ok`, with the one exception of the top-level invocations of `syn::parse` which now create a `Diagnostic` and pass it along. This commit does not immediately improve diagnostics but the intention is that it is laying the groundwork for improving diagnostics over time. It should ideally be much easier to contribute improved diagnostics after this commit! cc #601
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
use backend::ast;
|
||||
use backend::Diagnostic;
|
||||
use backend::util::{ident_ty, ShortHash};
|
||||
use proc_macro2::{Ident, Span, TokenStream, TokenTree};
|
||||
use quote::ToTokens;
|
||||
@ -590,7 +591,8 @@ pub(crate) trait MacroParse<Ctx> {
|
||||
///
|
||||
/// The context is used to have access to the attributes on `#[wasm_bindgen]`, and to allow
|
||||
/// writing to the output `TokenStream`.
|
||||
fn macro_parse(self, program: &mut ast::Program, context: Ctx);
|
||||
fn macro_parse(self, program: &mut ast::Program, context: Ctx)
|
||||
-> Result<(), Diagnostic>;
|
||||
}
|
||||
|
||||
impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
|
||||
@ -598,7 +600,7 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
|
||||
self,
|
||||
program: &mut ast::Program,
|
||||
(opts, tokens): (Option<BindgenAttrs>, &'a mut TokenStream),
|
||||
) {
|
||||
) -> Result<(), Diagnostic> {
|
||||
match self {
|
||||
syn::Item::Fn(mut f) => {
|
||||
let no_mangle = f
|
||||
@ -629,27 +631,31 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
|
||||
s.to_tokens(tokens);
|
||||
}
|
||||
syn::Item::Impl(mut i) => {
|
||||
(&mut i).macro_parse(program, ());
|
||||
(&mut i).macro_parse(program, ())?;
|
||||
i.to_tokens(tokens);
|
||||
}
|
||||
syn::Item::ForeignMod(mut f) => {
|
||||
let opts = opts.unwrap_or_else(|| BindgenAttrs::find(&mut f.attrs));
|
||||
f.macro_parse(program, opts);
|
||||
f.macro_parse(program, opts)?;
|
||||
}
|
||||
syn::Item::Enum(e) => {
|
||||
e.to_tokens(tokens);
|
||||
e.macro_parse(program, ());
|
||||
e.macro_parse(program, ())?;
|
||||
}
|
||||
_ => panic!(
|
||||
"#[wasm_bindgen] can only be applied to a function, \
|
||||
struct, enum, impl, or extern block"
|
||||
),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MacroParse<()> for &'a mut syn::ItemImpl {
|
||||
fn macro_parse(self, program: &mut ast::Program, (): ()) {
|
||||
fn macro_parse(self, program: &mut ast::Program, (): ())
|
||||
-> Result<(), Diagnostic>
|
||||
{
|
||||
if self.defaultness.is_some() {
|
||||
panic!("default impls are not supported");
|
||||
}
|
||||
@ -672,14 +678,20 @@ impl<'a> MacroParse<()> for &'a mut syn::ItemImpl {
|
||||
},
|
||||
_ => panic!("unsupported self type in impl"),
|
||||
};
|
||||
let mut errors = Vec::new();
|
||||
for item in self.items.iter_mut() {
|
||||
(&name, item).macro_parse(program, ())
|
||||
if let Err(e) = (&name, item).macro_parse(program, ()) {
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
Diagnostic::from_vec(errors)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) {
|
||||
fn macro_parse(self, program: &mut ast::Program, (): ()) {
|
||||
fn macro_parse(self, program: &mut ast::Program, (): ())
|
||||
-> Result<(), Diagnostic>
|
||||
{
|
||||
let (class, item) = self;
|
||||
replace_self(class, item);
|
||||
let method = match item {
|
||||
@ -691,7 +703,7 @@ impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) {
|
||||
};
|
||||
match method.vis {
|
||||
syn::Visibility::Public(_) => {}
|
||||
_ => return,
|
||||
_ => return Ok(()),
|
||||
}
|
||||
if method.defaultness.is_some() {
|
||||
panic!("default methods are not supported");
|
||||
@ -728,11 +740,14 @@ impl<'a, 'b> MacroParse<()> for (&'a Ident, &'b mut syn::ImplItem) {
|
||||
comments,
|
||||
rust_name: method.sig.ident.clone(),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MacroParse<()> for syn::ItemEnum {
|
||||
fn macro_parse(self, program: &mut ast::Program, (): ()) {
|
||||
fn macro_parse(self, program: &mut ast::Program, (): ())
|
||||
-> Result<(), Diagnostic>
|
||||
{
|
||||
match self.vis {
|
||||
syn::Visibility::Public(_) => {}
|
||||
_ => panic!("only public enums are allowed"),
|
||||
@ -776,11 +791,14 @@ impl MacroParse<()> for syn::ItemEnum {
|
||||
variants,
|
||||
comments,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl MacroParse<BindgenAttrs> for syn::ItemForeignMod {
|
||||
fn macro_parse(self, program: &mut ast::Program, opts: BindgenAttrs) {
|
||||
fn macro_parse(self, program: &mut ast::Program, opts: BindgenAttrs)
|
||||
-> Result<(), Diagnostic>
|
||||
{
|
||||
match self.abi.name {
|
||||
Some(ref l) if l.value() == "C" => {}
|
||||
None => {}
|
||||
@ -816,6 +834,7 @@ impl MacroParse<BindgenAttrs> for syn::ItemForeignMod {
|
||||
kind,
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user