Skip to content

Commit

Permalink
fix(sol-macro): pass attributes to all generated items (#340)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes authored Oct 6, 2023
1 parent 66373d8 commit 5b4fc67
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 13 deletions.
14 changes: 12 additions & 2 deletions crates/sol-macro/src/attr.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![allow(dead_code)]

use heck::{ToKebabCase, ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
use proc_macro2::TokenStream;
use quote::quote;
Expand All @@ -10,12 +12,20 @@ pub fn mk_doc(s: impl quote::ToTokens) -> TokenStream {
quote!(#[doc = #s])
}

pub fn is_doc(attr: &Attribute) -> bool {
attr.path().is_ident("doc")
}

pub fn is_derive(attr: &Attribute) -> bool {
attr.path().is_ident("derive")
}

pub fn docs(attrs: &[Attribute]) -> impl Iterator<Item = &Attribute> {
attrs.iter().filter(|attr| attr.path().is_ident("doc"))
attrs.iter().filter(|a| is_doc(a))
}

pub fn derives(attrs: &[Attribute]) -> impl Iterator<Item = &Attribute> {
attrs.iter().filter(|attr| attr.path().is_ident("derive"))
attrs.iter().filter(|a| is_derive(a))
}

pub fn derives_mapped(attrs: &[Attribute]) -> impl Iterator<Item = Path> + '_ {
Expand Down
23 changes: 15 additions & 8 deletions crates/sol-macro/src/expand/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,42 +53,49 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, contract: &ItemContract) -> Result<TokenS
let mut events = Vec::with_capacity(contract.body.len());

let mut item_tokens = TokenStream::new();
let d_attrs: Vec<Attribute> = attr::derives(&attrs).cloned().collect();
let (mod_attrs, item_attrs): (Vec<_>, _) =
attrs.into_iter().partition(|a| a.path().is_ident("doc"));

for item in body {
match item {
Item::Function(function) if function.name.is_some() => functions.push(function),
Item::Error(error) => errors.push(error),
Item::Event(event) => events.push(event),
_ => {}
}
if !d_attrs.is_empty() {
item_tokens.extend(quote!(#(#d_attrs)*));

if item.attrs().is_none() || item_attrs.is_empty() {
// avoid cloning item if we don't have to
item_tokens.extend(cx.expand_item(item)?);
} else {
// prepend `item_attrs` to `item.attrs`
let mut item = item.clone();
item.attrs_mut().unwrap().splice(0..0, item_attrs.clone());
item_tokens.extend(cx.expand_item(&item)?);
}
item_tokens.extend(cx.expand_item(item)?);
}

let functions_enum = (!functions.is_empty()).then(|| {
let mut attrs = d_attrs.clone();
let mut attrs = item_attrs.clone();
let doc_str = format!("Container for all the [`{name}`](self) function calls.");
attrs.push(parse_quote!(#[doc = #doc_str]));
CallLikeExpander::from_functions(cx, name, functions).expand(attrs, extra_methods)
});

let errors_enum = (!errors.is_empty()).then(|| {
let mut attrs = d_attrs.clone();
let mut attrs = item_attrs.clone();
let doc_str = format!("Container for all the [`{name}`](self) custom errors.");
attrs.push(parse_quote!(#[doc = #doc_str]));
CallLikeExpander::from_errors(cx, name, errors).expand(attrs, extra_methods)
});

let events_enum = (!events.is_empty()).then(|| {
let mut attrs = d_attrs;
let mut attrs = item_attrs;
let doc_str = format!("Container for all the [`{name}`](self) events.");
attrs.push(parse_quote!(#[doc = #doc_str]));
CallLikeExpander::from_events(cx, name, events).expand_event(attrs, extra_methods)
});

let mod_attrs = attr::docs(&attrs);
let mod_docs =
docs.then(|| attr::mk_doc("Module containing a contract's types and functions."));
let tokens = quote! {
Expand Down
29 changes: 26 additions & 3 deletions crates/syn-solidity/src/item/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,16 +205,39 @@ impl Item {
}
}

fn replace_attrs(&mut self, src: Vec<Attribute>) -> Vec<Attribute> {
pub fn attrs(&self) -> Option<&Vec<Attribute>> {
match self {
Self::Contract(ItemContract { attrs, .. })
| Self::Function(ItemFunction { attrs, .. })
| Self::Enum(ItemEnum { attrs, .. })
| Self::Error(ItemError { attrs, .. })
| Self::Event(ItemEvent { attrs, .. })
| Self::Struct(ItemStruct { attrs, .. })
| Self::Udt(ItemUdt { attrs, .. })
| Self::Variable(VariableDefinition { attrs, .. }) => Some(attrs),
Self::Import(_) | Self::Pragma(_) | Self::Using(_) => None,
}
}

pub fn attrs_mut(&mut self) -> Option<&mut Vec<Attribute>> {
match self {
Self::Contract(ItemContract { attrs, .. })
| Self::Function(ItemFunction { attrs, .. })
| Self::Enum(ItemEnum { attrs, .. })
| Self::Error(ItemError { attrs, .. })
| Self::Event(ItemEvent { attrs, .. })
| Self::Struct(ItemStruct { attrs, .. })
| Self::Udt(ItemUdt { attrs, .. }) => std::mem::replace(attrs, src),
_ => vec![],
| Self::Udt(ItemUdt { attrs, .. })
| Self::Variable(VariableDefinition { attrs, .. }) => Some(attrs),
Self::Import(_) | Self::Pragma(_) | Self::Using(_) => None,
}
}

fn replace_attrs(&mut self, src: Vec<Attribute>) -> Vec<Attribute> {
if let Some(attrs) = self.attrs_mut() {
std::mem::replace(attrs, src)
} else {
Vec::new()
}
}
}
2 changes: 2 additions & 0 deletions crates/syn-solidity/src/variable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ impl VariableDeclaration {

#[derive(Clone)]
pub struct VariableDefinition {
pub attrs: Vec<Attribute>,
pub ty: Type,
pub attributes: VariableAttributes,
pub name: SolIdent,
Expand Down Expand Up @@ -142,6 +143,7 @@ impl fmt::Debug for VariableDefinition {
impl Parse for VariableDefinition {
fn parse(input: ParseStream<'_>) -> Result<Self> {
Ok(Self {
attrs: Attribute::parse_outer(input)?,
ty: input.parse()?,
attributes: input.parse()?,
name: input.parse()?,
Expand Down

0 comments on commit 5b4fc67

Please sign in to comment.