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