From 160130a29e18e66c4bbdf6b59dc39c72f5c1b3a0 Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Thu, 12 Nov 2020 17:48:09 +0100 Subject: [PATCH] WIP: support re-exporting macros --- src/console/mod.rs | 2 + src/console/web_sys.rs | 280 +++++++++++++++++++++++++++ src/lib.rs | 9 +- weblog-proc-macro/src/weblog_impl.rs | 30 ++- 4 files changed, 305 insertions(+), 16 deletions(-) create mode 100644 src/console/web_sys.rs diff --git a/src/console/mod.rs b/src/console/mod.rs index c80f14c..7594c1b 100644 --- a/src/console/mod.rs +++ b/src/console/mod.rs @@ -1,2 +1,4 @@ #[cfg(feature = "std_web")] pub mod std_web; +#[cfg(feature = "web_sys")] +pub mod web_sys; diff --git a/src/console/web_sys.rs b/src/console/web_sys.rs new file mode 100644 index 0000000..0ce70db --- /dev/null +++ b/src/console/web_sys.rs @@ -0,0 +1,280 @@ +#[doc(hidden)] +pub use ::wasm_bindgen; +#[doc(hidden)] +pub use ::web_sys; + +// It is necessary to expose these wrapper macros in order to pass the $crate +// meta-variable to the proc macro. This in turn allows the macros to be +// re-exported from third-party crates without breakage. +// +// TODO: a declarative macro to remove the duplication here would be nice. + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_assert as __weblog_console_assert; + +#[macro_export] +/// Call the browser's `console.assert()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/assert) +macro_rules! console_assert { + ($($input:tt)*) => { + $crate::__weblog_console_assert! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_clear as __weblog_console_clear; + +#[macro_export] +/// Call the browser's `console.clear()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/clear) +macro_rules! console_clear { + ($($input:tt)*) => { + $crate::__weblog_console_clear! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_count as __weblog_console_count; + +#[macro_export] +/// Call the browser's `console.count()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/count) +macro_rules! console_count { + ($($input:tt)*) => { + $crate::__weblog_console_count! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_count_reset as __weblog_console_count_reset; + +#[macro_export] +/// Call the browser's `console.count_reset()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/count_reset) +macro_rules! console_count_reset { + ($($input:tt)*) => { + $crate::__weblog_console_count_reset! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_debug as __weblog_console_debug; + +#[macro_export] +/// Call the browser's `console.debug()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/debug) +macro_rules! console_debug { + ($($input:tt)*) => { + $crate::__weblog_console_debug! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_dir as __weblog_console_dir; + +#[macro_export] +/// Call the browser's `console.dir()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/dir) +macro_rules! console_dir { + ($($input:tt)*) => { + $crate::__weblog_console_dir! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_dirxml as __weblog_console_dirxml; + +#[macro_export] +/// Call the browser's `console.dirxml()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/dirxml) +macro_rules! console_dirxml { + ($($input:tt)*) => { + $crate::__weblog_console_dirxml! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_error as __weblog_console_error; + +#[macro_export] +/// Call the browser's `console.error()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/error) +macro_rules! console_error { + ($($input:tt)*) => { + $crate::__weblog_console_error! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_exception as __weblog_console_exception; + +#[macro_export] +/// Call the browser's `console.exception()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/exception) +macro_rules! console_exception { + ($($input:tt)*) => { + $crate::__weblog_console_exception! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_info as __weblog_console_info; + +#[macro_export] +/// Call the browser's `console.info()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/info) +macro_rules! console_info { + ($($input:tt)*) => { + $crate::__weblog_console_info! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_log as __weblog_console_log; + +#[macro_export] +/// Call the browser's `console.log()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/log) +macro_rules! console_log { + ($($input:tt)*) => { + $crate::__weblog_console_log! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_table as __weblog_console_table; + +#[macro_export] +/// Call the browser's `console.table()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/table) +macro_rules! console_table { + ($($input:tt)*) => { + $crate::__weblog_console_table! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_time as __weblog_console_time; + +#[macro_export] +/// Call the browser's `console.time()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/time) +macro_rules! console_time { + ($($input:tt)*) => { + $crate::__weblog_console_time! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_time_end as __weblog_console_time_end; + +#[macro_export] +/// Call the browser's `console.time_end()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/time_end) +macro_rules! console_time_end { + ($($input:tt)*) => { + $crate::__weblog_console_time_end! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_time_log as __weblog_console_time_log; + +#[macro_export] +/// Call the browser's `console.time_log()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/time_log) +macro_rules! console_time_log { + ($($input:tt)*) => { + $crate::__weblog_console_time_log! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_time_stamp as __weblog_console_time_stamp; + +#[macro_export] +/// Call the browser's `console.time_stamp()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/time_stamp) +macro_rules! console_time_stamp { + ($($input:tt)*) => { + $crate::__weblog_console_time_stamp! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_trace as __weblog_console_trace; + +#[macro_export] +/// Call the browser's `console.trace()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/trace) +macro_rules! console_trace { + ($($input:tt)*) => { + $crate::__weblog_console_trace! { + #![crate = $crate] + $($input)* + } + }; +} + +#[doc(hidden)] +pub use ::weblog_proc_macro::console_warn as __weblog_console_warn; + +#[macro_export] +/// Call the browser's `console.warn()` function. +/// [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Console/warn) +macro_rules! console_warn { + ($($input:tt)*) => { + $crate::__weblog_console_warn! { + #![crate = $crate] + $($input)* + } + }; +} diff --git a/src/lib.rs b/src/lib.rs index 922cf68..bd53771 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,16 +75,11 @@ //! weblog = { version = "0.3", default-features = false, features = ["stdweb"] } //! ``` //! + mod console; #[cfg(feature = "web_sys")] -pub use weblog_proc_macro::*; - -#[cfg(feature = "web_sys")] -pub use ::web_sys; - -#[cfg(feature = "web_sys")] -pub use ::wasm_bindgen; +pub use self::console::web_sys::*; #[cfg(feature = "std_web")] pub use self::console::std_web::*; diff --git a/weblog-proc-macro/src/weblog_impl.rs b/weblog-proc-macro/src/weblog_impl.rs index b983458..814f5bf 100644 --- a/weblog-proc-macro/src/weblog_impl.rs +++ b/weblog-proc-macro/src/weblog_impl.rs @@ -4,7 +4,7 @@ use quote::quote; use std::cmp; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; -use syn::{parse_macro_input, Expr, Result, Token}; +use syn::{bracketed, parse_macro_input, Expr, Result, Token}; // quote_console_func builds and quotes a call to the browser's console API, based on the // provided console function and argument types and the input token stream provider by @@ -24,10 +24,10 @@ pub fn quote_console_func( mut arg_modes: impl Iterator, input: TokenStream, ) -> TokenStream { - let InArgs(in_args) = parse_macro_input!(input as InArgs); + let InArgs(crate_name, in_args) = parse_macro_input!(input as InArgs); let mut out_args = in_args .iter() - .map(|arg| quote_arg(arg, arg_modes.next().unwrap_or_default())); + .map(|arg| quote_arg(&crate_name, arg, arg_modes.next().unwrap_or_default())); let num_provided = out_args.len(); let num_fixed = cmp::min(num_provided, params_fixed); @@ -60,16 +60,18 @@ pub fn quote_console_func( } } - (quote! { ::weblog::web_sys::console::#ident(#args) }).into() + (quote! { #crate_name::web_sys::console::#ident(#args) }).into() } -fn quote_arg(arg: &Expr, arg_mode: ArgMode) -> TokenStream2 { +fn quote_arg(crate_name: &TokenStream2, arg: &Expr, arg_mode: ArgMode) -> TokenStream2 { match arg_mode { ArgMode::PassThrough => { quote! { #arg } } ArgMode::IntoJsValue => { - quote! { &::std::convert::Into::<::weblog::wasm_bindgen::JsValue>::into(#arg) } + quote! { + &::std::convert::Into::<#crate_name::wasm_bindgen::JsValue>::into(#arg) + } } } } @@ -114,11 +116,21 @@ impl Default for ArgMode { } // InArgs is a struct required during parsing of input arguments. -struct InArgs(Punctuated); +struct InArgs(TokenStream2, Punctuated); impl Parse for InArgs { fn parse(input: ParseStream) -> Result { - let in_args: Punctuated = Punctuated::parse_terminated(&input)?; - Ok(Self(in_args)) + input.parse::()?; + input.parse::()?; + + let bracketed; + bracketed!(bracketed in input); + bracketed.parse::()?; + bracketed.parse::()?; + + let crate_name = bracketed.parse()?; + let args: Punctuated = Punctuated::parse_terminated(&input)?; + + Ok(Self(crate_name, args)) } }