Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion taurpc/src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,21 @@ fn generate_function(
};

let name = function.name().split_once("_taurpc_fn__").unwrap().1;
Ok(format!(r#"{name}: ({args}) => Promise<{return_ty}>"#))

let docs = function.docs();
let jsdoc = if docs.is_empty() {
String::new()
} else {
let lines: Vec<&str> = docs.lines().collect();
if lines.len() == 1 {
format!("/** {} */ ", lines[0])
} else {
let body = lines.iter().map(|l| format!(" * {l}")).join("\n");
format!("/**\n{body}\n */ ")
}
};

Ok(format!(r#"{jsdoc}{name}: ({args}) => Promise<{return_ty}>"#))
}

fn try_write(file: &mut File, data: &str) {
Expand Down
9 changes: 7 additions & 2 deletions taurpc/taurpc-macros/src/args.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, ToTokens};
use quote::{quote_spanned, ToTokens};
use syn::{ext::IdentExt, spanned::Spanned, Ident, Pat, PatType, Type};

// TODO: Add raw request??
Expand All @@ -20,6 +20,10 @@ impl Arg {
pub fn pat(&self) -> &Pat {
&self.pat.pat
}

pub fn span(&self) -> proc_macro2::Span {
self.pat.span()
}
}

impl From<PatType> for Arg {
Expand Down Expand Up @@ -77,8 +81,9 @@ fn parse_arg(arg: &Arg, message: &Ident, proc_ident: &Ident) -> syn::Result<Toke
));
}

let arg_span = arg.span();
// this way tauri knows how to deserialize the different types of the args
Ok(quote!(::tauri::ipc::CommandArg::from_command(
Ok(quote_spanned!(arg_span=> ::tauri::ipc::CommandArg::from_command(
::tauri::ipc::CommandItem {
name: stringify!(#proc_ident),
key: #key,
Expand Down
26 changes: 17 additions & 9 deletions taurpc/taurpc-macros/src/attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,14 @@ impl Parse for ProceduresAttrs {
/// Attributes defined on methods inside a procedures trait.
/// Parse the attributes to make sure they are defined in the correct way, like `#[taurpc( ... )]`, accumulate
/// all errors and then display them together with `extend_errors!()`.
#[derive(Default, Debug)]
#[derive(Default)]
pub struct MethodAttrs {
pub(crate) skip: bool,
pub(crate) alias: Option<String>,
pub(crate) is_event: bool,
pub(crate) comments: Vec<String>,
/// Attributes to forward to the generated code (e.g., #[allow(...)])
pub(crate) passthrough_attrs: Vec<Attribute>,
}

impl Parse for MethodAttrs {
Expand All @@ -116,15 +119,20 @@ impl Parse for MethodAttrs {
let mut errors = Ok(());

for attr in attrs {
if attr.path().is_ident("doc") {
if let syn::Meta::NameValue(meta) = &attr.meta {
if let Expr::Lit(expr_lit) = &meta.value {
if let Lit::Str(lit_str) = &expr_lit.lit {
res.comments.push(lit_str.value().trim().to_string());
}
}
}
continue;
}
if !attr.path().is_ident("taurpc") {
extend_errors!(
errors,
syn::Error::new(
attr.meta.span(),
"these attributes are not supported, use `#[taurpc(...)]` instead"
)
);
// continue;
// Forward non-taurpc attributes (like #[allow(...)], #[cfg(...)], etc.) to generated code
res.passthrough_attrs.push(attr);
continue;
}

if let Err(e) = attr.parse_nested_meta(|meta| {
Expand Down
45 changes: 34 additions & 11 deletions taurpc/taurpc-macros/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::args::{parse_arg_key, parse_args};
use crate::{method_fut_ident, proc::IpcMethod};

use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote, ToTokens};
use quote::{format_ident, quote, quote_spanned, ToTokens};
use std::collections::BTreeMap;
use syn::{parse_quote, Attribute, Generics, Ident, Type, Visibility};

Expand Down Expand Up @@ -38,11 +38,20 @@ impl ProceduresGenerator<'_> {
} = self;

let fn_types = alias_method_idents.iter().zip(methods).map(
|(ident, IpcMethod { output, args, .. })| {
|(ident, IpcMethod { output, args, attrs, span, .. })| {
let args = args.iter().filter(|&arg| !arg.skip_type);
let fn_ident = fn_ident(trait_ident, ident);

quote! {
let doc_attrs = if attrs.comments.is_empty() {
quote! {}
} else {
let lines = attrs.comments.iter().map(|line| quote! { #[doc = #line] });
quote! { #( #lines )* }
};
let passthrough_attrs = &attrs.passthrough_attrs;

quote_spanned! {*span=>
#doc_attrs
#( #passthrough_attrs )*
#[specta::specta]
#[allow(non_snake_case, unused_variables)]
fn #fn_ident( #( #args ),*) #output {
Expand All @@ -59,6 +68,7 @@ impl ProceduresGenerator<'_> {
args,
generics,
attrs,
span,
..
},
output_ty,
Expand All @@ -69,12 +79,21 @@ impl ProceduresGenerator<'_> {
}
let ty_doc = format!("The response future returned by [`{trait_ident}::{ident}`].");
let future_type_ident = method_fut_ident(ident);

Some(quote! {
let doc_attrs = if attrs.comments.is_empty() {
quote! {}
} else {
let lines = attrs.comments.iter().map(|line| quote! { #[doc = #line] });
quote! { #( #lines )* }
};
let passthrough_attrs = &attrs.passthrough_attrs;

Some(quote_spanned! {*span=>
#[allow(non_camel_case_types)]
#[doc = #ty_doc]
type #future_type_ident: std::future::Future<Output = #output_ty> + Send;

#doc_attrs
#( #passthrough_attrs )*
fn #ident #generics(self, #( #args ),*) -> Self::#future_type_ident;
})
},
Expand Down Expand Up @@ -250,19 +269,20 @@ impl ProceduresGenerator<'_> {
|(
proc_name,
IpcMethod {
ident, args, attrs, ..
ident, args, attrs, span, ..
},
)| {
if attrs.is_event {
return None;
}
let args = parse_args(args, &message, ident).unwrap();
let method_call = quote_spanned!(*span=> #trait_ident::#ident(
self.methods, #( #args.unwrap() ),*
));

Some(quote! { stringify!(#proc_name) => {
#resolver.respond_async_serialized(async move {
let res = #trait_ident::#ident(
self.methods, #( #args.unwrap() ),*
);
let res = #method_call;
let kind = (&res).async_kind();
kind.future(res).await
});
Expand Down Expand Up @@ -386,6 +406,7 @@ impl ProceduresGenerator<'_> {
args,
generics,
attrs,
span,
..
},
)| {
Expand All @@ -396,8 +417,10 @@ impl ProceduresGenerator<'_> {

let args = args.iter().filter(|arg| !arg.skip_type).collect::<Vec<_>>();
let arg_pats = args.iter().map(|arg| arg.pat()).collect::<Vec<_>>();
let passthrough_attrs = &attrs.passthrough_attrs;

Some(quote! {
Some(quote_spanned! {*span=>
#( #passthrough_attrs )*
#[allow(unused)]
#vis fn #ident #generics(&self, #( #args ),*) -> tauri::Result<()> {
let proc_name = stringify!(#alias_ident);
Expand Down
6 changes: 5 additions & 1 deletion taurpc/taurpc-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ pub fn resolvers(_attr: TokenStream, item: TokenStream) -> TokenStream {
item.items.push(syn::ImplItem::Type(t));
}

quote!(#item).into()
quote! {
#[allow(non_camel_case_types)]
#item
}
.into()
}

/// Transform an async method into a sync one that returns a `Pin<Box<Future<Output = ... >>`.
Expand Down
9 changes: 8 additions & 1 deletion taurpc/taurpc-macros/src/proc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::extend_errors;
use proc_macro2::Span;
use syn::{
braced,
ext::IdentExt,
Expand Down Expand Up @@ -27,6 +28,8 @@ pub struct IpcMethod {
pub args: Vec<Arg>,
pub generics: Generics,
pub attrs: MethodAttrs,
/// Span of the method signature, used for better error reporting
pub span: Span,
}

impl Parse for Procedures {
Expand Down Expand Up @@ -107,7 +110,7 @@ impl Parse for IpcMethod {
fn parse(input: ParseStream) -> parse::Result<Self> {
let attrs = MethodAttrs::parse(input)?;

<Token![async]>::parse(input)?;
let async_token = <Token![async]>::parse(input)?;
<Token![fn]>::parse(input)?;

let ident: Ident = input.parse()?;
Expand All @@ -134,12 +137,16 @@ impl Parse for IpcMethod {
let output = input.parse()?;
<Token![;]>::parse(input)?;

// Capture the span from async token (start of signature), fallback to ident span
let span = async_token.span;

Ok(IpcMethod {
ident,
output,
args,
generics,
attrs,
span,
})
}
}
Loading