odra_ir/module_item/
impl_item.rs1use std::convert::TryFrom;
2
3use proc_macro2::Ident;
4use syn::{punctuated::Punctuated, token::Comma};
5
6use crate::attrs::partition_attributes;
7
8use super::{constructor::Constructor, method::Method, utils};
9
10pub enum ImplItem {
14 Constructor(Constructor),
16 Method(Method),
18 Other(syn::ImplItem)
20}
21
22impl quote::ToTokens for ImplItem {
23 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
24 match self {
25 Self::Constructor(constructor) => constructor.to_tokens(tokens),
26 Self::Method(method) => method.to_tokens(tokens),
27 Self::Other(other) => other.to_tokens(tokens)
28 }
29 }
30}
31
32impl TryFrom<syn::ImplItem> for ImplItem {
33 type Error = syn::Error;
34
35 fn try_from(value: syn::ImplItem) -> Result<Self, Self::Error> {
36 match value {
37 syn::ImplItem::Method(method) => {
38 let (odra_attrs, _) = partition_attributes(method.attrs.clone())?;
39 if odra_attrs.is_empty() {
40 return Ok(ImplItem::Method(method.try_into()?));
41 }
42 let is_constructor = odra_attrs.iter().any(|attr| attr.is_constructor());
43 match is_constructor {
44 true => Ok(ImplItem::Constructor(Constructor::try_from(method)?)),
45 false => Ok(ImplItem::Method(method.try_into()?))
46 }
47 }
48 other_item => Ok(ImplItem::Other(other_item))
49 }
50 }
51}
52
53pub struct ContractEntrypoint {
54 pub ident: Ident,
55 pub args: Punctuated<syn::PatType, Comma>,
56 pub ret: syn::ReturnType,
57 pub full_sig: syn::Signature
58}
59
60impl From<syn::ImplItemMethod> for ContractEntrypoint {
61 fn from(method: syn::ImplItemMethod) -> Self {
62 let ident = method.sig.ident.to_owned();
63 let args = utils::extract_typed_inputs(&method.sig);
64 let ret = method.clone().sig.output;
65 let full_sig = method.sig;
66 Self {
67 ident,
68 args,
69 ret,
70 full_sig
71 }
72 }
73}
74
75#[cfg(test)]
76mod test {
77 use std::convert::TryFrom;
78
79 use super::ImplItem;
80
81 macro_rules! assert_enum_variant {
82 ($v:expr, $p:pat) => {
83 assert!(if let $p = $v { true } else { false })
84 };
85 }
86
87 #[test]
88 fn test_parse_fn_without_odra_attr() {
89 let item: syn::ImplItem = syn::parse_quote! {
90 #[some(a)]
91 pub fn set_initial_value(&self, value: u32) {
92 self.set_value(value);
93 }
94 };
95 let parsed = ImplItem::try_from(item);
96 assert_enum_variant!(parsed.unwrap(), ImplItem::Method(_));
97 }
98
99 #[test]
100 fn test_parse_fn_without_any_attr() {
101 let item: syn::ImplItem = syn::parse_quote! {
102 pub fn set_initial_value(&self, value: u32) {
103 self.set_value(value);
104 }
105 };
106 let parsed = ImplItem::try_from(item);
107 assert_enum_variant!(parsed.unwrap(), ImplItem::Method(_));
108 }
109
110 #[test]
111 fn test_parse_fn_with_odra_init_attr() {
112 let item: syn::ImplItem = syn::parse_quote! {
113 #[odra(init)]
114 pub fn set_initial_value(&self, value: u32) {
115 self.set_value(value);
116 }
117 };
118 let parsed = ImplItem::try_from(item);
119 assert_enum_variant!(parsed.unwrap(), ImplItem::Constructor(_));
120 }
121
122 #[test]
123 fn test_parse_other_impl_item() {
124 let item: syn::ImplItem = syn::parse_quote! {
125 const A: i32 = 3;
126 };
127 let parsed = ImplItem::try_from(item);
128 assert_enum_variant!(parsed.unwrap(), ImplItem::Other(_));
129 }
130}