Skip to content

Commit 41617bd

Browse files
Add attribute crate to proc-macro wasm-bindgen-test (#3593)
1 parent 4d4851d commit 41617bd

File tree

5 files changed

+65
-26
lines changed

5 files changed

+65
-26
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@
4242
* Add bindings for `CanvasTransform.setTransform(DOMMatrix2DInit)`.
4343
[#3580](https://github.com/rustwasm/wasm-bindgen/pull/3580)
4444

45+
* Add a `crate` attribute to the `wasm_bindgen_test` proc-macro to specify a
46+
non-default path to the `wasm-bindgen-test` crate.
47+
[#3593](https://github.com/rustwasm/wasm-bindgen/pull/3593)
48+
4549
### Changed
4650

4751
* Updated the WebGPU WebIDL.

crates/test-macro/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ proc-macro = true
1414
[dependencies]
1515
proc-macro2 = "1.0"
1616
quote = "1.0"
17+
syn = { version = "2.0", default-features = false, features = [ "parsing", "proc-macro", "derive", "printing" ] }
1718

1819
[dev-dependencies]
1920
wasm-bindgen-test = { path = "../test" }

crates/test-macro/src/lib.rs

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,11 @@ pub fn wasm_bindgen_test(
1616
attr: proc_macro::TokenStream,
1717
body: proc_macro::TokenStream,
1818
) -> proc_macro::TokenStream {
19-
let mut attr = attr.into_iter();
20-
let mut r#async = false;
19+
let mut attributes = Attributes::default();
20+
let attribute_parser = syn::meta::parser(|meta| attributes.parse(meta));
21+
22+
syn::parse_macro_input!(attr with attribute_parser);
2123
let mut should_panic = None;
22-
while let Some(token) = attr.next() {
23-
match &token {
24-
proc_macro::TokenTree::Ident(i) if i.to_string() == "async" => r#async = true,
25-
_ => {
26-
return compile_error(
27-
token.span().into(),
28-
"malformed `#[wasm_bindgen_test]` attribute",
29-
)
30-
}
31-
}
32-
match &attr.next() {
33-
Some(proc_macro::TokenTree::Punct(op)) if op.as_char() == ',' => {}
34-
Some(_) => {
35-
return compile_error(
36-
token.span().into(),
37-
"malformed `#[wasm_bindgen_test]` attribute",
38-
)
39-
}
40-
None => break,
41-
}
42-
}
4324

4425
let mut body = TokenStream::from(body).into_iter().peekable();
4526

@@ -64,7 +45,7 @@ pub fn wasm_bindgen_test(
6445
leading_tokens.push(token.clone());
6546
if let TokenTree::Ident(token) = token {
6647
if token == "async" {
67-
r#async = true;
48+
attributes.r#async = true;
6849
}
6950
if token == "fn" {
7051
break;
@@ -83,7 +64,7 @@ pub fn wasm_bindgen_test(
8364
None => quote! { ::core::option::Option::None },
8465
};
8566

86-
let test_body = if r#async {
67+
let test_body = if attributes.r#async {
8768
quote! { cx.execute_async(test_name, #ident, #should_panic); }
8869
} else {
8970
quote! { cx.execute_sync(test_name, #ident, #should_panic); }
@@ -93,10 +74,11 @@ pub fn wasm_bindgen_test(
9374
// later slurp up all of these functions and pass them as arguments to the
9475
// main test harness. This is the entry point for all tests.
9576
let name = format_ident!("__wbgt_{}_{}", ident, CNT.fetch_add(1, Ordering::SeqCst));
77+
let wasm_bindgen_path = attributes.wasm_bindgen_path;
9678
tokens.extend(
9779
quote! {
9880
#[no_mangle]
99-
pub extern "C" fn #name(cx: &::wasm_bindgen_test::__rt::Context) {
81+
pub extern "C" fn #name(cx: &#wasm_bindgen_path::__rt::Context) {
10082
let test_name = ::core::concat!(::core::module_path!(), "::", ::core::stringify!(#ident));
10183
#test_body
10284
}
@@ -205,3 +187,30 @@ fn find_ident(iter: &mut impl Iterator<Item = TokenTree>) -> Option<Ident> {
205187
fn compile_error(span: Span, msg: &str) -> proc_macro::TokenStream {
206188
quote_spanned! { span => compile_error!(#msg); }.into()
207189
}
190+
191+
struct Attributes {
192+
r#async: bool,
193+
wasm_bindgen_path: syn::Path,
194+
}
195+
196+
impl Default for Attributes {
197+
fn default() -> Self {
198+
Self {
199+
r#async: false,
200+
wasm_bindgen_path: syn::parse_quote!(::wasm_bindgen_test),
201+
}
202+
}
203+
}
204+
205+
impl Attributes {
206+
fn parse(&mut self, meta: syn::meta::ParseNestedMeta) -> syn::parse::Result<()> {
207+
if meta.path.is_ident("async") {
208+
self.r#async = true;
209+
} else if meta.path.is_ident("crate") {
210+
self.wasm_bindgen_path = meta.value()?.parse::<syn::Path>()?;
211+
} else {
212+
return Err(meta.error("unknown attribute"));
213+
}
214+
Ok(())
215+
}
216+
}

crates/test-macro/ui-tests/crate.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![no_implicit_prelude]
2+
3+
extern crate wasm_bindgen_test_macro;
4+
//
5+
use wasm_bindgen_test_macro::wasm_bindgen_test;
6+
7+
pub mod wasm {
8+
pub extern crate wasm_bindgen_test as test;
9+
}
10+
11+
#[wasm_bindgen_test(crate = ::wasm_bindgen_test)]
12+
fn success_1() {}
13+
14+
#[wasm_bindgen_test(crate = crate::wasm::test)]
15+
fn success_2() {}
16+
17+
#[wasm_bindgen_test(crate = foo)]
18+
fn failure_1() {}
19+
20+
fn main() {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
error[E0433]: failed to resolve: use of undeclared crate or module `foo`
2+
--> ui-tests/crate.rs:17:29
3+
|
4+
17 | #[wasm_bindgen_test(crate = foo)]
5+
| ^^^ use of undeclared crate or module `foo`

0 commit comments

Comments
 (0)