Skip to content

Commit fad2642

Browse files
authored
fix(sol-macro-expander): propagate all_derives and extra_derives to periphery SC structs (#1011)
* Fix derives * Simplify * Do not affect functions_enum * Avoid extra enum expander * Doc * Comment
1 parent 175183b commit fad2642

File tree

2 files changed

+102
-11
lines changed

2 files changed

+102
-11
lines changed

crates/sol-macro-expander/src/expand/contract.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,7 @@ pub(super) fn expand(cx: &mut ExpCtxt<'_>, contract: &ItemContract) -> Result<To
141141
item_tokens.extend(cx.expand_item(&item)?);
142142
}
143143
}
144-
cx.attrs = prev_cx_attrs;
145144

146-
let enum_expander = CallLikeExpander { cx, contract_name: name.clone(), extra_methods };
147145
// Remove any `Default` derives.
148146
let mut enum_attrs = item_attrs;
149147
for attr in &mut enum_attrs {
@@ -166,14 +164,7 @@ pub(super) fn expand(cx: &mut ExpCtxt<'_>, contract: &ItemContract) -> Result<To
166164
attr.meta = parse_quote! { derive(#(#derives),*) };
167165
}
168166

169-
let functions_enum = (!functions.is_empty()).then(|| {
170-
let mut attrs = enum_attrs.clone();
171-
let doc_str = format!("Container for all the [`{name}`](self) function calls.");
172-
attrs.push(parse_quote!(#[doc = #doc_str]));
173-
attrs.push(parse_quote!(#[derive(Clone)]));
174-
enum_expander.expand(ToExpand::Functions(&functions), attrs)
175-
});
176-
167+
let enum_expander = CallLikeExpander { cx, contract_name: name.clone(), extra_methods };
177168
let errors_enum = (!errors.is_empty()).then(|| {
178169
let mut attrs = enum_attrs.clone();
179170
let doc_str = format!("Container for all the [`{name}`](self) custom errors.");
@@ -183,13 +174,25 @@ pub(super) fn expand(cx: &mut ExpCtxt<'_>, contract: &ItemContract) -> Result<To
183174
});
184175

185176
let events_enum = (!events.is_empty()).then(|| {
186-
let mut attrs = enum_attrs;
177+
let mut attrs = enum_attrs.clone();
187178
let doc_str = format!("Container for all the [`{name}`](self) events.");
188179
attrs.push(parse_quote!(#[doc = #doc_str]));
189180
attrs.push(parse_quote!(#[derive(Clone)]));
190181
enum_expander.expand(ToExpand::Events(&events), attrs)
191182
});
192183

184+
// Do not propagate contract-level derives to the functions enum.
185+
cx.attrs = prev_cx_attrs;
186+
187+
let functions_enum = (!functions.is_empty()).then(|| {
188+
let mut attrs = enum_attrs;
189+
let doc_str = format!("Container for all the [`{name}`](self) function calls.");
190+
attrs.push(parse_quote!(#[doc = #doc_str]));
191+
attrs.push(parse_quote!(#[derive(Clone)]));
192+
let enum_expander = CallLikeExpander { cx, contract_name: name.clone(), extra_methods };
193+
enum_expander.expand(ToExpand::Functions(&functions), attrs)
194+
});
195+
193196
let mod_descr_doc = (docs && docs_str(&mod_attrs).trim().is_empty())
194197
.then(|| mk_doc("Module containing a contract's types and functions."));
195198
let mod_iface_doc = (docs && !docs_str(&mod_attrs).contains("```solidity\n"))

crates/sol-types/tests/derives.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Comprehensive test for contract-level derives applying to all generated types.
2+
//! Tests all_derives and extra_derives on contracts with events and errors.
3+
4+
use alloy_primitives::{Address, U256};
5+
use alloy_sol_types::sol;
6+
use std::{collections::HashSet, hash::Hash};
7+
8+
#[test]
9+
fn test_all_derives() {
10+
sol! {
11+
#[sol(all_derives)]
12+
contract AllDerivesContract {
13+
function transfer(address to, uint256 amount) external returns (bool);
14+
event Transfer(address indexed from, address indexed to, uint256 value);
15+
error InsufficientBalance(uint256 requested, uint256 available);
16+
}
17+
}
18+
19+
use AllDerivesContract::*;
20+
21+
let event1 = Transfer { from: Address::ZERO, to: Address::ZERO, value: U256::from(50) };
22+
let event2 = Transfer { from: Address::ZERO, to: Address::ZERO, value: U256::from(50) };
23+
let events_enum1 = AllDerivesContractEvents::Transfer(event1);
24+
let events_enum2 = AllDerivesContractEvents::Transfer(event2);
25+
26+
let error1 = InsufficientBalance { requested: U256::from(100), available: U256::from(50) };
27+
let error2 = InsufficientBalance { requested: U256::from(100), available: U256::from(50) };
28+
let errors_enum1 = AllDerivesContractErrors::InsufficientBalance(error1);
29+
let errors_enum2 = AllDerivesContractErrors::InsufficientBalance(error2);
30+
31+
// Test PartialEq and Debug
32+
assert_eq!(errors_enum1, errors_enum2);
33+
assert_eq!(events_enum1, events_enum2);
34+
35+
// Test Hash and Eq derives
36+
let mut events_set = HashSet::new();
37+
events_set.insert(events_enum1);
38+
events_set.insert(events_enum2);
39+
// Should not increase size since they're equal
40+
assert_eq!(events_set.len(), 1);
41+
42+
let mut errors_set = HashSet::new();
43+
errors_set.insert(errors_enum1);
44+
errors_set.insert(errors_enum2);
45+
// Should not increase size since they're equal
46+
assert_eq!(errors_set.len(), 1);
47+
}
48+
49+
#[test]
50+
fn test_extra_derives() {
51+
sol! {
52+
#[sol(extra_derives(PartialEq, Eq, Hash, Debug))]
53+
contract ExtraDerivesContract {
54+
function transfer(address to, uint256 amount) external returns (bool);
55+
event Transfer(address indexed from, address indexed to, uint256 value);
56+
error InsufficientBalance(uint256 requested, uint256 available);
57+
}
58+
}
59+
60+
use ExtraDerivesContract::*;
61+
62+
let event1 = Transfer { from: Address::ZERO, to: Address::ZERO, value: U256::from(50) };
63+
let event2 = Transfer { from: Address::ZERO, to: Address::ZERO, value: U256::from(50) };
64+
let events_enum1 = ExtraDerivesContractEvents::Transfer(event1);
65+
let events_enum2 = ExtraDerivesContractEvents::Transfer(event2);
66+
67+
let error1 = InsufficientBalance { requested: U256::from(100), available: U256::from(50) };
68+
let error2 = InsufficientBalance { requested: U256::from(100), available: U256::from(50) };
69+
let errors_enum1 = ExtraDerivesContractErrors::InsufficientBalance(error1);
70+
let errors_enum2 = ExtraDerivesContractErrors::InsufficientBalance(error2);
71+
72+
// Test PartialEq and Debug
73+
assert_eq!(errors_enum1, errors_enum2);
74+
assert_eq!(events_enum1, events_enum2);
75+
76+
// Test Hash and Eq derives
77+
let mut events_set = HashSet::new();
78+
events_set.insert(events_enum1);
79+
events_set.insert(events_enum2);
80+
// Should not increase size since they're equal
81+
assert_eq!(events_set.len(), 1);
82+
83+
let mut errors_set = HashSet::new();
84+
errors_set.insert(errors_enum1);
85+
errors_set.insert(errors_enum2);
86+
// Should not increase size since they're equal
87+
assert_eq!(errors_set.len(), 1);
88+
}

0 commit comments

Comments
 (0)