|
@@ -4,17 +4,18 @@
|
|
|
|
|
|
use heck::{ToLowerCamelCase, ToSnakeCase};
|
|
|
use proc_macro::TokenStream;
|
|
|
-use proc_macro2::TokenStream as TokenStream2;
|
|
|
+use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
|
|
|
use quote::{format_ident, quote};
|
|
|
use syn::{
|
|
|
ext::IdentExt,
|
|
|
parse::{Parse, ParseStream},
|
|
|
parse_macro_input,
|
|
|
spanned::Spanned,
|
|
|
- FnArg, Ident, ItemFn, Lit, Meta, Pat, Token, Visibility,
|
|
|
+ FnArg, ItemFn, Lit, Meta, Pat, Token, Visibility,
|
|
|
};
|
|
|
|
|
|
struct WrapperAttributes {
|
|
|
+ root: TokenStream2,
|
|
|
execution_context: ExecutionContext,
|
|
|
argument_case: ArgumentCase,
|
|
|
}
|
|
@@ -22,6 +23,7 @@ struct WrapperAttributes {
|
|
|
impl Parse for WrapperAttributes {
|
|
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
|
|
let mut wrapper_attributes = WrapperAttributes {
|
|
|
+ root: quote!(::tauri),
|
|
|
execution_context: ExecutionContext::Blocking,
|
|
|
argument_case: ArgumentCase::Camel,
|
|
|
};
|
|
@@ -43,6 +45,11 @@ impl Parse for WrapperAttributes {
|
|
|
}
|
|
|
};
|
|
|
}
|
|
|
+ } else if v.path.is_ident("root") {
|
|
|
+ if let Lit::Str(s) = v.lit {
|
|
|
+ let ident = Ident::new(&s.value(), Span::call_site());
|
|
|
+ wrapper_attributes.root = quote!(#ident);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
Ok(Meta::Path(p)) => {
|
|
@@ -104,21 +111,28 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
|
|
|
};
|
|
|
|
|
|
// body to the command wrapper or a `compile_error!` of an error occurred while parsing it.
|
|
|
- let body = syn::parse::<WrapperAttributes>(attributes)
|
|
|
+ let (body, attributes) = syn::parse::<WrapperAttributes>(attributes)
|
|
|
.map(|mut attrs| {
|
|
|
if function.sig.asyncness.is_some() {
|
|
|
attrs.execution_context = ExecutionContext::Async;
|
|
|
}
|
|
|
attrs
|
|
|
})
|
|
|
- .and_then(|attrs| match attrs.execution_context {
|
|
|
- ExecutionContext::Async => body_async(&function, &invoke, attrs.argument_case),
|
|
|
- ExecutionContext::Blocking => body_blocking(&function, &invoke, attrs.argument_case),
|
|
|
+ .and_then(|attrs| {
|
|
|
+ let body = match attrs.execution_context {
|
|
|
+ ExecutionContext::Async => body_async(&function, &invoke, &attrs),
|
|
|
+ ExecutionContext::Blocking => body_blocking(&function, &invoke, &attrs),
|
|
|
+ };
|
|
|
+ body.map(|b| (b, Some(attrs)))
|
|
|
})
|
|
|
- .unwrap_or_else(syn::Error::into_compile_error);
|
|
|
+ .unwrap_or_else(|e| (syn::Error::into_compile_error(e), None));
|
|
|
|
|
|
let Invoke { message, resolver } = invoke;
|
|
|
|
|
|
+ let root = attributes
|
|
|
+ .map(|a| a.root)
|
|
|
+ .unwrap_or_else(|| quote!(::tauri));
|
|
|
+
|
|
|
// Rely on rust 2018 edition to allow importing a macro from a path.
|
|
|
quote!(
|
|
|
#function
|
|
@@ -129,10 +143,10 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
|
|
|
// double braces because the item is expected to be a block expression
|
|
|
($path:path, $invoke:ident) => {{
|
|
|
#[allow(unused_imports)]
|
|
|
- use ::tauri::command::private::*;
|
|
|
+ use #root::command::private::*;
|
|
|
// prevent warnings when the body is a `compile_error!` or if the command has no arguments
|
|
|
#[allow(unused_variables)]
|
|
|
- let ::tauri::Invoke { message: #message, resolver: #resolver } = $invoke;
|
|
|
+ let #root::Invoke { message: #message, resolver: #resolver } = $invoke;
|
|
|
|
|
|
#body
|
|
|
}};
|
|
@@ -150,9 +164,13 @@ pub fn wrapper(attributes: TokenStream, item: TokenStream) -> TokenStream {
|
|
|
/// See the [`tauri::command`] module for all the items and traits that make this possible.
|
|
|
///
|
|
|
/// [`tauri::command`]: https://docs.rs/tauri/*/tauri/runtime/index.html
|
|
|
-fn body_async(function: &ItemFn, invoke: &Invoke, case: ArgumentCase) -> syn::Result<TokenStream2> {
|
|
|
+fn body_async(
|
|
|
+ function: &ItemFn,
|
|
|
+ invoke: &Invoke,
|
|
|
+ attributes: &WrapperAttributes,
|
|
|
+) -> syn::Result<TokenStream2> {
|
|
|
let Invoke { message, resolver } = invoke;
|
|
|
- parse_args(function, message, case).map(|args| {
|
|
|
+ parse_args(function, message, attributes).map(|args| {
|
|
|
quote! {
|
|
|
#resolver.respond_async_serialized(async move {
|
|
|
let result = $path(#(#args?),*);
|
|
@@ -171,10 +189,10 @@ fn body_async(function: &ItemFn, invoke: &Invoke, case: ArgumentCase) -> syn::Re
|
|
|
fn body_blocking(
|
|
|
function: &ItemFn,
|
|
|
invoke: &Invoke,
|
|
|
- case: ArgumentCase,
|
|
|
+ attributes: &WrapperAttributes,
|
|
|
) -> syn::Result<TokenStream2> {
|
|
|
let Invoke { message, resolver } = invoke;
|
|
|
- let args = parse_args(function, message, case)?;
|
|
|
+ let args = parse_args(function, message, attributes)?;
|
|
|
|
|
|
// the body of a `match` to early return any argument that wasn't successful in parsing.
|
|
|
let match_body = quote!({
|
|
@@ -193,13 +211,13 @@ fn body_blocking(
|
|
|
fn parse_args(
|
|
|
function: &ItemFn,
|
|
|
message: &Ident,
|
|
|
- case: ArgumentCase,
|
|
|
+ attributes: &WrapperAttributes,
|
|
|
) -> syn::Result<Vec<TokenStream2>> {
|
|
|
function
|
|
|
.sig
|
|
|
.inputs
|
|
|
.iter()
|
|
|
- .map(|arg| parse_arg(&function.sig.ident, arg, message, case))
|
|
|
+ .map(|arg| parse_arg(&function.sig.ident, arg, message, attributes))
|
|
|
.collect()
|
|
|
}
|
|
|
|
|
@@ -208,7 +226,7 @@ fn parse_arg(
|
|
|
command: &Ident,
|
|
|
arg: &FnArg,
|
|
|
message: &Ident,
|
|
|
- case: ArgumentCase,
|
|
|
+ attributes: &WrapperAttributes,
|
|
|
) -> syn::Result<TokenStream2> {
|
|
|
// we have no use for self arguments
|
|
|
let mut arg = match arg {
|
|
@@ -243,7 +261,7 @@ fn parse_arg(
|
|
|
));
|
|
|
}
|
|
|
|
|
|
- match case {
|
|
|
+ match attributes.argument_case {
|
|
|
ArgumentCase::Camel => {
|
|
|
key = key.to_lower_camel_case();
|
|
|
}
|
|
@@ -252,8 +270,10 @@ fn parse_arg(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Ok(quote!(::tauri::command::CommandArg::from_command(
|
|
|
- ::tauri::command::CommandItem {
|
|
|
+ let root = &attributes.root;
|
|
|
+
|
|
|
+ Ok(quote!(#root::command::CommandArg::from_command(
|
|
|
+ #root::command::CommandItem {
|
|
|
name: stringify!(#command),
|
|
|
key: #key,
|
|
|
message: &#message,
|