yew_macro/
use_transitive_state.rs1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::parse::{Parse, ParseStream};
4use syn::{Expr, ExprClosure, ReturnType, Token, Type};
5
6#[derive(Debug)]
7pub struct TransitiveState {
8 closure: ExprClosure,
9 return_type: Type,
10 deps: Expr,
11}
12
13impl Parse for TransitiveState {
14 fn parse(input: ParseStream) -> syn::Result<Self> {
15 let deps = input.parse()?;
17
18 input.parse::<Token![,]>().map_err(|e| {
19 syn::Error::new(
20 e.span(),
21 "this hook takes 2 arguments but 1 argument was supplied",
22 )
23 })?;
24
25 let expr: Expr = input.parse()?;
27
28 let closure = match expr {
29 Expr::Closure(m) => m,
30 other => return Err(syn::Error::new_spanned(other, "expected closure")),
31 };
32
33 let return_type = match &closure.output {
34 ReturnType::Default => {
35 return Err(syn::Error::new_spanned(
36 &closure,
37 "You must specify a return type for this closure. This is used when the \
38 closure is omitted from the client side rendering bundle.",
39 ))
40 }
41 ReturnType::Type(_rarrow, ty) => *ty.to_owned(),
42 };
43
44 if !input.is_empty() {
45 let maybe_trailing_comma = input.lookahead1();
46
47 if !maybe_trailing_comma.peek(Token![,]) {
48 return Err(maybe_trailing_comma.error());
49 }
50 }
51
52 Ok(Self {
53 closure,
54 return_type,
55 deps,
56 })
57 }
58}
59
60impl TransitiveState {
61 pub fn to_token_stream_with_closure(&self) -> TokenStream {
62 let deps = &self.deps;
63 let rt = &self.return_type;
64 let closure = &self.closure;
65
66 quote! {
67 ::yew::functional::use_transitive_state::<#rt, _, _>(#deps, #closure)
68 }
69 }
70
71 pub fn to_token_stream_without_closure(&self) -> TokenStream {
75 let deps = &self.deps;
76 let rt = &self.return_type;
77
78 quote! {
79 ::yew::functional::use_transitive_state::<#rt, _>(#deps)
80 }
81 }
82}