Skip to content

Commit 1453d4b

Browse files
feat(core): support generics (especially Param) in #[command] (#1622)
* wip: param argument proof of concept for #[command] * use macros for automatic type inference in commands * refactor command for better error handling * remove redundant ToTokens impl for Wrapper and Handler * create `StateP` to allow state to use type inference during commands * wrap State instead of T * remove accidental edit of attribute * remove StateP because we recommend `_: Window<P>` for type inference, the following function types are now supported: * Pat::Wild (arg: "_") * Pat::Struct (arg: final path segment) * Pat::TupleStruct (arg: final path segment) * add wildcard, struct, and tuple struct commands to examples * better unsupported command argument message * feat(examples): move some commands to a separate module * add change file Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
1 parent c78db1b commit 1453d4b

10 files changed

Lines changed: 363 additions & 179 deletions

File tree

‎.changes/command-generics.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-macros": patch
3+
---
4+
5+
`#[command]` now generates a macro instead of a function to allow passing through `Params` and other generics.
6+
`generate_handler!` has been changed to consume the generated `#[command]` macro

‎core/tauri-macros/src/command.rs‎

Lines changed: 0 additions & 151 deletions
This file was deleted.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
2+
// SPDX-License-Identifier: Apache-2.0
3+
// SPDX-License-Identifier: MIT
4+
5+
use syn::{
6+
parse::{Parse, ParseBuffer},
7+
Ident, Path, Token,
8+
};
9+
10+
/// The items parsed from [`generate_handle!`](crate::generate_handle).
11+
pub struct Handler {
12+
paths: Vec<Path>,
13+
commands: Vec<Ident>,
14+
wrappers: Vec<Path>,
15+
}
16+
17+
impl Parse for Handler {
18+
fn parse(input: &ParseBuffer) -> syn::Result<Self> {
19+
let paths = input.parse_terminated::<Path, Token![,]>(Path::parse)?;
20+
21+
// parse the command names and wrappers from the passed paths
22+
let (commands, wrappers) = paths
23+
.iter()
24+
.map(|path| {
25+
let mut wrapper = path.clone();
26+
let last = super::path_to_command(&mut wrapper);
27+
28+
// the name of the actual command function
29+
let command = last.ident.clone();
30+
31+
// set the path to the command function wrapper
32+
last.ident = super::format_command_wrapper(&command);
33+
34+
(command, wrapper)
35+
})
36+
.unzip();
37+
38+
Ok(Self {
39+
paths: paths.into_iter().collect(), // remove punctuation separators
40+
commands,
41+
wrappers,
42+
})
43+
}
44+
}
45+
46+
impl From<Handler> for proc_macro::TokenStream {
47+
fn from(
48+
Handler {
49+
paths,
50+
commands,
51+
wrappers,
52+
}: Handler,
53+
) -> Self {
54+
quote::quote!(move |invoke| {
55+
let cmd = invoke.message.command();
56+
match cmd {
57+
#(stringify!(#commands) => #wrappers!(#paths, invoke),)*
58+
_ => {
59+
invoke.resolver.reject(format!("command {} not found", cmd))
60+
},
61+
}
62+
})
63+
.into()
64+
}
65+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
2+
// SPDX-License-Identifier: Apache-2.0
3+
// SPDX-License-Identifier: MIT
4+
5+
use proc_macro2::Ident;
6+
use syn::{Path, PathSegment};
7+
8+
pub use self::{
9+
handler::Handler,
10+
wrapper::{Wrapper, WrapperBody},
11+
};
12+
13+
mod handler;
14+
mod wrapper;
15+
16+
/// The autogenerated wrapper ident.
17+
fn format_command_wrapper(function: &Ident) -> Ident {
18+
quote::format_ident!("__cmd__{}", function)
19+
}
20+
21+
/// This function will panic if the passed [`syn::Path`] does not have any segments.
22+
fn path_to_command(path: &mut Path) -> &mut PathSegment {
23+
path
24+
.segments
25+
.last_mut()
26+
.expect("parsed syn::Path has no segment")
27+
}

0 commit comments

Comments
 (0)