sylvia_derive/types/
msg_field.rs

1use crate::fold::StripSelfPath;
2use crate::parser::check_generics::{CheckGenerics, GetPath};
3use proc_macro2::TokenStream;
4use proc_macro_error::emit_error;
5use quote::quote;
6use syn::fold::Fold;
7use syn::spanned::Spanned;
8use syn::visit::Visit;
9use syn::{Attribute, Ident, Pat, PatType, Type};
10
11/// Representation of single message variant field
12#[derive(Debug)]
13pub struct MsgField<'a> {
14    name: &'a Ident,
15    ty: &'a Type,
16    stripped_ty: Type,
17    attrs: &'a Vec<Attribute>,
18}
19
20impl<'a> MsgField<'a> {
21    /// Creates new field from trait method argument
22    pub fn new<Generic>(
23        item: &'a PatType,
24        generics_checker: &mut CheckGenerics<Generic>,
25    ) -> Option<MsgField<'a>>
26    where
27        Generic: GetPath + PartialEq,
28    {
29        let name = match &*item.pat {
30            Pat::Ident(p) => Some(&p.ident),
31            pat => {
32                // TODO: Support pattern arguments, when decorated with argument with item
33                // name
34                //
35                // Eg.
36                //
37                // ```
38                // fn exec_foo(&self, ctx: Ctx, #[sv::msg(name=metadata)] SomeData { addr, sender }: SomeData);
39                // ```
40                //
41                // should expand to enum variant:
42                //
43                // ```
44                // ExecFoo {
45                //   metadata: SomeDaa
46                // }
47                // ```
48                emit_error!(pat.span(), "Expected argument name, pattern occurred");
49                None
50            }
51        }?;
52
53        let ty = &item.ty;
54        let stripped_ty = StripSelfPath.fold_type((*item.ty).clone());
55        let attrs = &item.attrs;
56        generics_checker.visit_type(&stripped_ty);
57
58        Some(Self {
59            name,
60            ty,
61            stripped_ty,
62            attrs,
63        })
64    }
65
66    /// Emits message field
67    pub fn emit(&self) -> TokenStream {
68        let Self {
69            name,
70            stripped_ty,
71            attrs,
72            ..
73        } = self;
74
75        quote! {
76            #(#attrs)*
77            #name: #stripped_ty
78        }
79    }
80
81    /// Emits struct field
82    pub fn emit_pub(&self) -> TokenStream {
83        let Self {
84            name,
85            stripped_ty,
86            attrs,
87            ..
88        } = self;
89
90        quote! {
91            #(#attrs)*
92            pub #name: #stripped_ty
93        }
94    }
95
96    /// Emits method field
97    pub fn emit_method_field(&self) -> TokenStream {
98        let Self {
99            name, stripped_ty, ..
100        } = self;
101
102        quote! {
103            #name: #stripped_ty
104        }
105    }
106
107    pub fn emit_method_field_folded(&self) -> TokenStream {
108        let Self { name, ty, .. } = self;
109
110        quote! {
111            #name: #ty
112        }
113    }
114
115    pub fn name(&self) -> &'a Ident {
116        self.name
117    }
118
119    pub fn ty(&self) -> &'a Type {
120        self.ty
121    }
122
123    pub fn attrs(&self) -> &'a Vec<Attribute> {
124        self.attrs
125    }
126}