Skip to content

Commit

Permalink
Merge pull request #59 from oscartbeaumont/generic-commands
Browse files Browse the repository at this point in the history
make collect_commands a proc macro to support generic commands
  • Loading branch information
oscartbeaumont authored Oct 5, 2023
2 parents 5ae9eef + 9574da6 commit 67f2e24
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 14 deletions.
7 changes: 6 additions & 1 deletion examples/app/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ fn has_error() -> Result<&'static str, i32> {
Err(32)
}

#[tauri::command]
#[specta::specta]
fn generic<T: tauri::Runtime>(app: tauri::AppHandle<T>) {}

mod nested {
use super::*;

Expand Down Expand Up @@ -57,7 +61,8 @@ fn main() {
hello_world,
goodbye_world,
has_error,
nested::some_struct
nested::some_struct,
generic::<tauri::Wry>
])
.events(tauri_specta::collect_events![DemoEvent, EmptyEvent])
.config(specta::ts::ExportConfig::default().formatter(specta::ts::prettier));
Expand Down
66 changes: 66 additions & 0 deletions macros/src/collect_commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use proc_macro2::{Ident, TokenStream};

Check warning on line 1 in macros/src/collect_commands.rs

View workflow job for this annotation

GitHub Actions / clippy

unused import: `TokenStream`

warning: unused import: `TokenStream` --> macros/src/collect_commands.rs:1:26 | 1 | use proc_macro2::{Ident, TokenStream}; | ^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default
use quote::quote;
use syn::{
bracketed,

Check warning on line 4 in macros/src/collect_commands.rs

View workflow job for this annotation

GitHub Actions / clippy

unused imports: `ItemStruct`, `bracketed`

warning: unused imports: `ItemStruct`, `bracketed` --> macros/src/collect_commands.rs:4:5 | 4 | bracketed, | ^^^^^^^^^ ... 8 | ItemStruct, Path, Token, | ^^^^^^^^^^
parse::{Parse, ParseStream},
parse_macro_input,
punctuated::Punctuated,
ItemStruct, Path, Token,
};

pub struct Input {
type_map: Option<Ident>,
paths: Punctuated<Path, Token![,]>,
}

mod kw {
syn::custom_keyword!(type_map);
}

impl Parse for Input {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(Self {
type_map: {
if input.peek(kw::type_map) && input.peek2(Token![:]) {
input.parse::<kw::type_map>()?;
input.parse::<Token![:]>()?;
Some(input.parse()?)
} else {
None
}
},
paths: Punctuated::parse_terminated(input)?,
})
}
}

pub fn proc_macro(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let Input { type_map, paths } = parse_macro_input!(input as Input);

let tauri_paths = paths.iter().map(|p| {
let Path {
leading_colon,
segments,
} = p;

let segments = segments.iter().map(|s| &s.ident);

quote!(#leading_colon #(#segments)::*)
});

let type_map = type_map
.map(|i| quote!(#i))
.unwrap_or_else(|| quote!(::specta::TypeMap::new()));

let body = quote! {(
::specta::collect_functions![type_map; #paths],
::tauri::generate_handler![#(#tauri_paths),*],
)};

quote! {{
let mut type_map = #type_map;

#body
}}
.into()
}
7 changes: 7 additions & 0 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod collect_commands;

use heck::ToKebabCase;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
Expand All @@ -17,3 +19,8 @@ pub fn derive_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
}
.into()
}

#[proc_macro]
pub fn collect_commands(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
collect_commands::proc_macro(input)
}
14 changes: 1 addition & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,7 @@ pub use event::*;
pub type CollectCommandsTuple<TInvokeHandler> =
(specta::functions::CollectFunctionsResult, TInvokeHandler);

#[macro_export]
macro_rules! collect_commands {
(type_map: $type_map:ident, $($command:path),*) => {
(
specta::collect_functions![$type_map; $($command),*],
::tauri::generate_handler![$($command),*],
)
};
($($command:path),*) => {{
let mut type_map = specta::TypeMap::default();
$crate::collect_commands![type_map: type_map, $($command),*]
}};
}
pub use tauri_specta_macros::collect_commands;

// TODO
// #[cfg(doctest)]
Expand Down

0 comments on commit 67f2e24

Please sign in to comment.