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
83
84
85
86
87
88
89
90
91
92
93
94
95
use proc_macro2::{Span as Span2, TokenStream as TokenStream2};
use quote::quote;
use syn::{spanned::Spanned, Error, Ident, ImplItem, ItemImpl, Visibility};
use crate::{
token_streams::{TokenStreams, TraitImplDetails},
widgets::ViewWidgets,
};
pub(crate) fn generate_tokens(vis: Option<Visibility>, mut item_impl: ItemImpl) -> TokenStream2 {
if item_impl.items.len() != 1 {
return Error::new(
item_impl.span(),
"Expected only one view macro and nothing else",
)
.into_compile_error();
}
let item = item_impl.items.pop().unwrap();
if let ImplItem::Macro(mac) = item {
if Some("view") == mac.mac.path.get_ident().map(|i| i.to_string()).as_deref() {
match syn::parse_macro_input::parse::<ViewWidgets>(mac.mac.tokens.into()) {
Ok(mut view_widgets) => {
view_widgets.mark_root_as_used();
let TokenStreams {
error,
init,
assign,
struct_fields,
return_fields,
..
} = view_widgets.generate_streams(
&TraitImplDetails {
vis: vis.clone(),
model_name: Ident::new("_", Span2::call_site()),
sender_name: Ident::new("sender", Span2::call_site()),
root_name: None,
},
true,
);
let view_output = quote! {
#init
#assign
{
#error
}
};
let root_widget_type = view_widgets.root_type();
item_impl.items.push(ImplItem::Verbatim(quote! {
type Root = #root_widget_type;
}));
let root_name = view_widgets.root_name();
item_impl.items.push(ImplItem::Verbatim(quote! {
fn init() -> Self {
#view_output
Self {
#return_fields
}
}
}));
let type_name = &item_impl.self_ty;
quote! {
#[derive(Debug, Clone)]
#vis struct #type_name {
#struct_fields
}
impl ::std::ops::Deref for #type_name {
type Target = #root_widget_type;
fn deref(&self) -> &Self::Target {
&self.#root_name
}
}
#item_impl
}
}
Err(err) => err.to_compile_error(),
}
} else {
Error::new(mac.mac.path.span(), "Expected a view macro").into_compile_error()
}
} else {
Error::new(item.span(), "Expected a macro").into_compile_error()
}
}