git.delta.rocks / unique-network / refs/commits / a1ef1e7a88a7

difftreelog

reafactor: Better error reporting

Trubnikov Sergey2022-11-23parent: #11dcf7d.patch.diff
in: master

2 files changed

modifiedcrates/evm-coder/procedural/src/abi_derive.rsdiffbeforeafterboth
4 let name = &ast.ident;4 let name = &ast.ident;
5
6 match &ast.data {5 match &ast.data {
7 syn::Data::Struct(ds) => {6 syn::Data::Struct(ds) => expand_struct(ds, ast),
8 let docs = extract_docs(&ast.attrs)?;
9 let (is_named_fields, field_names, field_types, field_docs, params_count) =
10 match ds.fields {
11 syn::Fields::Named(ref fields) => Ok((
12 true,
13 fields.named.iter().enumerate().map(map_field_to_name),
14 fields.named.iter().map(map_field_to_type),
15 fields.named.iter().map(map_field_to_doc),
16 fields.named.len(),
17 )),
18 syn::Fields::Unnamed(ref fields) => Ok((
19 false,
20 fields.unnamed.iter().enumerate().map(map_field_to_name),
21 fields.unnamed.iter().map(map_field_to_type),
22 fields.unnamed.iter().map(map_field_to_doc),
23 fields.unnamed.len(),
24 )),
25 syn::Fields::Unit => {
26 Err(syn::Error::new(name.span(), "Unit structs not supported"))
27 }
28 }?;
29
30 if params_count == 0 {
31 return Err(syn::Error::new(name.span(), "Empty structs not supported"));
32 };
33
34 let tuple_type = tuple_type(field_types.clone());
35 let tuple_ref_type = tuple_ref_type(field_types.clone());
36 let tuple_data = tuple_data_as_ref(is_named_fields, field_names.clone());
37 let tuple_names = tuple_names(is_named_fields, field_names.clone());
38 let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());
39
40 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);
41 let abi_type = impl_abi_type(name, tuple_type.clone());
42 let abi_read = impl_abi_read(name, tuple_type, tuple_names, struct_from_tuple);
43 let abi_write = impl_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);
44 let solidity_type = impl_solidity_type(name, field_types.clone(), params_count);
45 let solidity_type_name =
46 impl_solidity_type_name(name, field_types.clone(), params_count);
47 let solidity_struct_collect =
48 impl_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;
49
50 Ok(quote! {
51 #can_be_plcaed_in_vec
52 #abi_type
53 #abi_read
54 #abi_write
55 #solidity_type
56 #solidity_type_name
57 #solidity_struct_collect
58 })
59 }
60 syn::Data::Enum(de) => {7 syn::Data::Enum(de) => expand_enum(de, ast),
61 check_repr_u8(name, &ast.attrs)?;
62
63 dbg!(&de);
64 for f in de.variants.iter().filter_map(|v| {
65 if !v.fields.is_empty() {
66 Some(Err(syn::Error::new(
67 v.ident.span(),
68 "Enumeration parameters should not have fields",
69 )))
70 } else if v.discriminant.is_some() {
71 Some(Err(syn::Error::new(
72 v.ident.span(),
73 "Enumeration options should not have an explicit specified value",
74 )))
75 } else {
76 None
77 }
78 }) {
79 f?;
80 }
81 Ok(quote!())
82 }
83 syn::Data::Union(_) => Err(syn::Error::new(name.span(), "Unions not supported")),8 syn::Data::Union(_) => Err(syn::Error::new(name.span(), "Unions not supported")),
84 }9 }
85}10}
11
12fn expand_struct(
13 ds: &syn::DataStruct,
14 ast: &syn::DeriveInput,
15) -> syn::Result<proc_macro2::TokenStream> {
16 let name = &ast.ident;
17 let docs = extract_docs(&ast.attrs)?;
18 let (is_named_fields, field_names, field_types, field_docs, params_count) = match ds.fields {
19 syn::Fields::Named(ref fields) => Ok((
20 true,
21 fields.named.iter().enumerate().map(map_field_to_name),
22 fields.named.iter().map(map_field_to_type),
23 fields.named.iter().map(map_field_to_doc),
24 fields.named.len(),
25 )),
26 syn::Fields::Unnamed(ref fields) => Ok((
27 false,
28 fields.unnamed.iter().enumerate().map(map_field_to_name),
29 fields.unnamed.iter().map(map_field_to_type),
30 fields.unnamed.iter().map(map_field_to_doc),
31 fields.unnamed.len(),
32 )),
33 syn::Fields::Unit => Err(syn::Error::new(name.span(), "Unit structs not supported")),
34 }?;
35
36 if params_count == 0 {
37 return Err(syn::Error::new(name.span(), "Empty structs not supported"));
38 };
39
40 let tuple_type = tuple_type(field_types.clone());
41 let tuple_ref_type = tuple_ref_type(field_types.clone());
42 let tuple_data = tuple_data_as_ref(is_named_fields, field_names.clone());
43 let tuple_names = tuple_names(is_named_fields, field_names.clone());
44 let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());
45
46 let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);
47 let abi_type = impl_abi_type(name, tuple_type.clone());
48 let abi_read = impl_abi_read(name, tuple_type, tuple_names, struct_from_tuple);
49 let abi_write = impl_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);
50 let solidity_type = impl_solidity_type(name, field_types.clone(), params_count);
51 let solidity_type_name = impl_solidity_type_name(name, field_types.clone(), params_count);
52 let solidity_struct_collect =
53 impl_solidity_struct_collect(name, field_names, field_types, field_docs, &docs)?;
54
55 Ok(quote! {
56 #can_be_plcaed_in_vec
57 #abi_type
58 #abi_read
59 #abi_write
60 #solidity_type
61 #solidity_type_name
62 #solidity_struct_collect
63 })
64}
65
66fn expand_enum(
67 de: &syn::DataEnum,
68 ast: &syn::DeriveInput,
69) -> syn::Result<proc_macro2::TokenStream> {
70 let name = &ast.ident;
71 check_repr_u8(name, &ast.attrs)?;
72 check_option_validity(de)?;
73
74 dbg!(&de);
75
76 Ok(quote!())
77}
78
79fn check_option_validity(de: &syn::DataEnum) -> syn::Result<()> {
80 for error in de.variants.iter().filter_map(|v| {
81 if !v.fields.is_empty() {
82 Some(Err(syn::Error::new(
83 v.ident.span(),
84 "Enumeration parameters should not have fields",
85 )))
86 } else if v.discriminant.is_some() {
87 Some(Err(syn::Error::new(
88 v.ident.span(),
89 "Enumeration options should not have an explicit specified value",
90 )))
91 } else {
92 None
93 }
94 }) {
95 return error;
96 }
97
98 Ok(())
99}
86100
87fn check_repr_u8(name: &syn::Ident, attrs: &Vec<syn::Attribute>) -> syn::Result<()> {101fn check_repr_u8(name: &syn::Ident, attrs: &Vec<syn::Attribute>) -> syn::Result<()> {
88 let repr_u8 = attrs102 let mut has_repr = false;
89 .iter()103 for error in attrs.iter().filter_map(|attr| {
90 .filter_map(|attr| {
91 if let Some(ps) = attr.path.segments.first() {104 if let Some(ps) = attr.path.segments.first() {
92 if ps.ident == "repr" {105 if ps.ident == "repr" {
106 has_repr = true;
93 let meta = match attr.parse_meta() {107 let meta = match attr.parse_meta() {
94 Ok(meta) => meta,108 Ok(meta) => meta,
95 Err(e) => return Some(Err(e)),109 Err(e) => return Some(Err(e)),
96 };110 };
97 let is_repr_u8 = match meta {111 match meta {
98 syn::Meta::List(p) => {112 syn::Meta::List(p) => {
99 p.nested113 for error in p.nested.iter().filter_map(|nm| match nm {
100 .iter()
101 .filter(|nm| match nm {
102 syn::NestedMeta::Meta(m) => match m {114 syn::NestedMeta::Meta(m) => match m {
103 syn::Meta::Path(p) => {115 syn::Meta::Path(p) => {
104 p.segments.iter().filter(|ps| ps.ident == "u8").count()116 for i in p.segments.iter().filter_map(|ps| {
105 == 1117 if ps.ident != "u8" {
118 Some(Err(syn::Error::new(
119 ps.ident.span(),
120 "Enum is not \"repr(u8)\"",
121 )))
122 } else {
123 None
124 }
125 }) {
126 return Some(i);
127 }
128 None
106 }129 }
107 _ => false,130 _ => None,
108 },131 },
109 _ => false,132 _ => None,
110 })133 }) {
111 .count() == 1134 return Some(error);
135 }
136 None::<syn::Result<()>>
112 }137 }
113 _ => false,138 _ => None,
114 };139 };
115
116 if is_repr_u8 {
117 return Some(Ok(()));
118 };
119 }140 }
120 }141 }
121 None::<syn::Result<()>>142 None
122 })143 }) {
123 .collect::<syn::Result<Vec<_>>>()?;144 return error;
145 }
124146
125 if repr_u8.len() != 1 {147 if !has_repr {
126 return Err(syn::Error::new(name.span(), "Enum is not \"repr(u8)\""));148 return Err(syn::Error::new(name.span(), "Enum is not \"repr(u8)\""));
127 };149 }
128150
129 Ok(())151 Ok(())
130}152}
modifiedcrates/evm-coder/tests/build_failed/abi_derive_enum_generation.stderrdiffbeforeafterboth
5 | ^^^^^^^5 | ^^^^^^^
66
7error: Enum is not "repr(u8)"7error: Enum is not "repr(u8)"
8 --> tests/build_failed/abi_derive_enum_generation.rs:12:68 --> tests/build_failed/abi_derive_enum_generation.rs:11:8
9 |9 |
1012 | enum NonReprU8 {1011 | #[repr(u32)]
11 | ^^^^^^^^^11 | ^^^
1212
13error: Enumeration parameters should not have fields13error: Enumeration parameters should not have fields
14 --> tests/build_failed/abi_derive_enum_generation.rs:21:214 --> tests/build_failed/abi_derive_enum_generation.rs:21:2