lib.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. extern crate proc_macro;
  2. use proc_macro::TokenStream;
  3. use quote::{quote, ToTokens};
  4. use syn::{
  5. self,
  6. parse::{Parse, ParseStream},
  7. punctuated::Punctuated,
  8. token::Paren,
  9. Field, Ident, Token, Type, TypeTuple,
  10. };
  11. #[derive(PartialEq)]
  12. enum DepKind {
  13. NodeDepState,
  14. ChildDepState,
  15. ParentDepState,
  16. }
  17. // macro that streams data from the State for any attributes that end with _
  18. #[proc_macro_derive(State, attributes(node_dep_state, child_dep_state, parent_dep_state))]
  19. pub fn state_macro_derive(input: TokenStream) -> TokenStream {
  20. let ast = syn::parse(input).unwrap();
  21. impl_derive_macro(&ast)
  22. }
  23. fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
  24. let type_name = &ast.ident;
  25. let fields: Vec<_> = match &ast.data {
  26. syn::Data::Struct(data) => match &data.fields {
  27. syn::Fields::Named(e) => &e.named,
  28. syn::Fields::Unnamed(_) => todo!("unnamed fields"),
  29. syn::Fields::Unit => todo!("unit fields"),
  30. }
  31. .iter()
  32. .collect(),
  33. _ => unimplemented!(),
  34. };
  35. let strct = Struct::parse(&fields);
  36. let state_strct = StateStruct::parse(&fields, &strct);
  37. let node_dep_state_fields = quote::__private::TokenStream::from_iter(
  38. state_strct
  39. .state_members
  40. .iter()
  41. .filter(|f| f.dep_kind == DepKind::NodeDepState)
  42. .map(|f| {
  43. let ty_id = &f.type_id();
  44. let reduce = &f.reduce_self();
  45. quote! {
  46. else if ty == #ty_id {
  47. #reduce
  48. }
  49. }
  50. }),
  51. );
  52. let child_dep_state_fields = quote::__private::TokenStream::from_iter(
  53. state_strct
  54. .state_members
  55. .iter()
  56. .filter(|f| f.dep_kind == DepKind::ChildDepState)
  57. .map(|f| {
  58. let ty_id = &f.type_id();
  59. let reduce = &f.reduce_self();
  60. quote! {
  61. else if ty == #ty_id {
  62. #reduce
  63. }
  64. }
  65. }),
  66. );
  67. let parent_dep_state_fields = quote::__private::TokenStream::from_iter(
  68. state_strct
  69. .state_members
  70. .iter()
  71. .filter(|f| f.dep_kind == DepKind::ParentDepState)
  72. .map(|f| {
  73. let ty_id = &f.type_id();
  74. let reduce = &f.reduce_self();
  75. quote! {
  76. else if ty == #ty_id {
  77. #reduce
  78. }
  79. }
  80. }),
  81. );
  82. let node_types = state_strct
  83. .state_members
  84. .iter()
  85. .filter(|f| f.dep_kind == DepKind::NodeDepState)
  86. .map(|f| &f.mem.ty);
  87. let child_types = state_strct
  88. .state_members
  89. .iter()
  90. .filter(|f| f.dep_kind == DepKind::ChildDepState)
  91. .map(|f| &f.mem.ty);
  92. let parent_types = state_strct
  93. .state_members
  94. .iter()
  95. .filter(|f| f.dep_kind == DepKind::ParentDepState)
  96. .map(|f| &f.mem.ty);
  97. let type_name_str = type_name.to_string();
  98. let gen = quote! {
  99. impl State for #type_name{
  100. fn update_node_dep_state<'a>(&'a mut self, ty: std::any::TypeId, node: Option<&'a dioxus_core::VElement<'a>>, ctx: &anymap::AnyMap) -> bool{
  101. use dioxus_native_core::real_dom_new_api::NodeDepState as _;
  102. // println!("called update_node_dep_state with ty: {:?}", ty);
  103. if false {
  104. unreachable!();
  105. }
  106. #node_dep_state_fields
  107. else{
  108. panic!("{:?} not in {}", ty, #type_name_str)
  109. }
  110. }
  111. fn update_parent_dep_state<'a>(&'a mut self, ty: std::any::TypeId, node: Option<&'a dioxus_core::VElement<'a>>, parent: Option<&Self>, ctx: &anymap::AnyMap) -> bool{
  112. use dioxus_native_core::real_dom_new_api::ParentDepState as _;
  113. // println!("called update_parent_dep_state with ty: {:?}", ty);
  114. if false {
  115. unreachable!();
  116. }
  117. #parent_dep_state_fields
  118. else{
  119. panic!("{:?} not in {}", ty, #type_name_str)
  120. }
  121. }
  122. fn update_child_dep_state<'a>(&'a mut self, ty: std::any::TypeId, node: Option<&'a dioxus_core::VElement<'a>>, children: &[&Self], ctx: &anymap::AnyMap) -> bool{
  123. use dioxus_native_core::real_dom_new_api::ChildDepState as _;
  124. // println!("called update_child_dep_state with ty: {:?}", ty);
  125. if false {
  126. unreachable!()
  127. }
  128. #child_dep_state_fields
  129. else{
  130. panic!("{:?} not in {}", ty, #type_name_str)
  131. }
  132. }
  133. fn child_dep_types(&self, mask: &dioxus_native_core::real_dom_new_api::NodeMask) -> Vec<std::any::TypeId>{
  134. let mut dep_types = Vec::new();
  135. #(if #child_types::NODE_MASK.overlaps(mask) {
  136. dep_types.push(std::any::TypeId::of::<#child_types>());
  137. })*
  138. dep_types
  139. }
  140. fn parent_dep_types(&self, mask: &dioxus_native_core::real_dom_new_api::NodeMask) -> Vec<std::any::TypeId>{
  141. let mut dep_types = Vec::new();
  142. #(if #parent_types::NODE_MASK.overlaps(mask) {
  143. dep_types.push(std::any::TypeId::of::<#parent_types>());
  144. })*
  145. dep_types
  146. }
  147. fn node_dep_types(&self, mask: &dioxus_native_core::real_dom_new_api::NodeMask) -> Vec<std::any::TypeId>{
  148. let mut dep_types = Vec::new();
  149. #(if #node_types::NODE_MASK.overlaps(mask) {
  150. dep_types.push(std::any::TypeId::of::<#node_types>());
  151. })*
  152. dep_types
  153. }
  154. }
  155. };
  156. gen.into()
  157. }
  158. struct Struct {
  159. members: Vec<Member>,
  160. }
  161. impl Struct {
  162. fn parse(fields: &[&Field]) -> Self {
  163. let members = fields.iter().filter_map(|f| Member::parse(f)).collect();
  164. Self { members }
  165. }
  166. }
  167. struct StateStruct<'a> {
  168. state_members: Vec<StateMember<'a>>,
  169. }
  170. impl<'a> StateStruct<'a> {
  171. fn parse(fields: &[&'a Field], strct: &'a Struct) -> Self {
  172. let state_members = strct
  173. .members
  174. .iter()
  175. .zip(fields.iter())
  176. .filter_map(|(m, f)| StateMember::parse(f, m, &strct))
  177. .collect();
  178. // todo: sort members
  179. Self { state_members }
  180. }
  181. }
  182. struct DepTypes {
  183. ctx_ty: Option<Type>,
  184. dep_ty: Option<Type>,
  185. }
  186. impl Parse for DepTypes {
  187. fn parse(input: ParseStream) -> Result<Self, syn::Error> {
  188. let dep_ty = input.parse().ok();
  189. let comma: Option<Token![,]> = input.parse().ok();
  190. let ctx_ty = input.parse().ok();
  191. Ok(Self {
  192. ctx_ty: comma.and(ctx_ty),
  193. dep_ty,
  194. })
  195. }
  196. }
  197. struct NodeDepTypes {
  198. ctx_ty: Option<Type>,
  199. }
  200. impl Parse for NodeDepTypes {
  201. fn parse(input: ParseStream) -> Result<Self, syn::Error> {
  202. let ctx_ty = input.parse().ok();
  203. Ok(Self { ctx_ty })
  204. }
  205. }
  206. impl From<NodeDepTypes> for DepTypes {
  207. fn from(node_dep_types: NodeDepTypes) -> Self {
  208. Self {
  209. ctx_ty: node_dep_types.ctx_ty,
  210. dep_ty: None,
  211. }
  212. }
  213. }
  214. struct Member {
  215. ty: Type,
  216. ident: Ident,
  217. }
  218. impl Member {
  219. fn parse(field: &Field) -> Option<Self> {
  220. Some(Self {
  221. ty: field.ty.clone(),
  222. ident: field.ident.as_ref()?.clone(),
  223. })
  224. }
  225. }
  226. struct StateMember<'a> {
  227. mem: &'a Member,
  228. dep_kind: DepKind,
  229. dep_mem: Option<&'a Member>,
  230. ctx_ty: Option<Type>,
  231. }
  232. impl<'a> StateMember<'a> {
  233. fn parse(field: &Field, mem: &'a Member, parent: &'a Struct) -> Option<StateMember<'a>> {
  234. field.attrs.iter().find_map(|a| {
  235. let dep_kind = a
  236. .path
  237. .get_ident()
  238. .map(|i| match i.to_string().as_str() {
  239. "node_dep_state" => Some(DepKind::NodeDepState),
  240. "child_dep_state" => Some(DepKind::ChildDepState),
  241. "parent_dep_state" => Some(DepKind::ParentDepState),
  242. _ => None,
  243. })
  244. .flatten()?;
  245. let deps: DepTypes = match dep_kind {
  246. DepKind::NodeDepState => a.parse_args::<NodeDepTypes>().ok()?.into(),
  247. _ => a.parse_args().ok()?,
  248. };
  249. Some(Self {
  250. mem,
  251. dep_kind,
  252. dep_mem: deps
  253. .dep_ty
  254. .map(|ty| parent.members.iter().find(|m| m.ty == ty))
  255. .flatten(),
  256. ctx_ty: deps.ctx_ty,
  257. })
  258. })
  259. }
  260. fn reduce_self(&self) -> quote::__private::TokenStream {
  261. let ident = &self.mem.ident;
  262. let get_ctx = if let Some(ctx_ty) = &self.ctx_ty {
  263. if ctx_ty
  264. == &Type::Tuple(TypeTuple {
  265. paren_token: Paren {
  266. span: quote::__private::Span::call_site(),
  267. },
  268. elems: Punctuated::new(),
  269. })
  270. {
  271. quote! {&()}
  272. } else {
  273. let msg = ctx_ty.to_token_stream().to_string() + " not found in context";
  274. quote! {ctx.get().expect(#msg)}
  275. }
  276. } else {
  277. quote! {&()}
  278. };
  279. let ty = &self.mem.ty;
  280. let node_view = quote!(NodeView::new(node, #ty::NODE_MASK));
  281. if let Some(dep_ident) = &self.dep_mem.map(|m| &m.ident) {
  282. match self.dep_kind {
  283. DepKind::NodeDepState => {
  284. quote!(self.#ident.reduce(#node_view, #get_ctx))
  285. }
  286. DepKind::ChildDepState => {
  287. quote!(self.#ident.reduce(#node_view, children.iter().map(|s| &s.#dep_ident).collect(), #get_ctx))
  288. }
  289. DepKind::ParentDepState => {
  290. quote!(self.#ident.reduce(#node_view, parent.as_ref().map(|p| &p.#dep_ident), #get_ctx))
  291. }
  292. }
  293. } else {
  294. match self.dep_kind {
  295. DepKind::NodeDepState => {
  296. quote!(self.#ident.reduce(#node_view, #get_ctx))
  297. }
  298. DepKind::ChildDepState => {
  299. quote!(self.#ident.reduce(#node_view, &(), #get_ctx))
  300. }
  301. DepKind::ParentDepState => {
  302. quote!(self.#ident.reduce(#node_view, Some(&()), #get_ctx))
  303. }
  304. }
  305. }
  306. }
  307. fn type_id(&self) -> quote::__private::TokenStream {
  308. let ty = &self.mem.ty;
  309. // quote!(std::any::TypeId::of::<#ty>())
  310. quote!({
  311. let type_id = std::any::TypeId::of::<#ty>();
  312. // println!("{:?}", type_id);
  313. type_id
  314. })
  315. }
  316. }