Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sol-macro): add docs to generated items #321

Merged
merged 2 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions crates/sol-macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
syn-solidity = { workspace = true, features = ["visit", "visit-mut"] }

dunce = "1"
heck = "0.4"
proc-macro2.workspace = true
quote.workspace = true
syn = { workspace = true, features = ["extra-traits"] }

dunce = "1"
heck = "0.4"
tiny-keccak = { workspace = true, features = ["keccak"] }
hex.workspace = true

# json
alloy-json-abi = { workspace = true, optional = true }
Expand Down
10 changes: 10 additions & 0 deletions crates/sol-macro/src/attr.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
use heck::{ToKebabCase, ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
use proc_macro2::TokenStream;
use quote::quote;
use syn::{punctuated::Punctuated, Attribute, Error, LitBool, LitStr, Path, Result, Token};

const DUPLICATE_ERROR: &str = "duplicate attribute";
const UNKNOWN_ERROR: &str = "unknown `sol` attribute";

pub fn mk_doc(s: impl quote::ToTokens) -> TokenStream {
quote!(#[doc = #s])
}

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

pub fn has_docs(attrs: &[Attribute]) -> bool {
docs(attrs).next().is_some()
}

pub fn derives(attrs: &[Attribute]) -> impl Iterator<Item = &Attribute> {
attrs.iter().filter(|attr| attr.path().is_ident("derive"))
}
Expand Down
9 changes: 6 additions & 3 deletions crates/sol-macro/src/expand/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,30 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, contract: &ItemContract) -> Result<TokenS

let functions_enum = (!functions.is_empty()).then(|| {
let mut attrs = d_attrs.clone();
let doc_str = format!("Container for all the `{name}` function calls.");
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 doc_str = format!("Container for all the `{name}` custom errors.");
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 doc_str = format!("Container for all the `{name}` events.");
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 = (!attr::has_docs(&attrs))
.then(|| attr::mk_doc("Module containing a contract's types and functions."));
let tokens = quote! {
#mod_docs
#(#mod_attrs)*
#[allow(non_camel_case_types, non_snake_case, clippy::style)]
pub mod #name {
Expand Down
8 changes: 8 additions & 0 deletions crates/sol-macro/src/expand/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! [`ItemError`] expansion.

use super::{expand_fields, expand_from_into_tuples, ty::expand_tokenize_func, ExpCtxt};
use crate::attr;
use ast::ItemError;
use proc_macro2::TokenStream;
use quote::quote;
Expand Down Expand Up @@ -36,7 +37,14 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, error: &ItemError) -> Result<TokenStream>

let converts = expand_from_into_tuples(&name.0, params);
let fields = expand_fields(params);
let doc = (!attr::has_docs(&attrs)).then(|| {
let selector = hex::encode_prefixed(selector.array);
attr::mk_doc(format!(
"Custom error with signature `{signature}` and selector `{selector}`."
))
});
let tokens = quote! {
#doc
#(#attrs)*
#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone)]
Expand Down
8 changes: 8 additions & 0 deletions crates/sol-macro/src/expand/event.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! [`ItemEvent`] expansion.

use super::{anon_name, expand_tuple_types, expand_type, ty, ExpCtxt};
use crate::attr;
use ast::{EventParameter, ItemEvent, SolIdent, Spanned};
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned};
Expand Down Expand Up @@ -104,7 +105,14 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, event: &ItemEvent) -> Result<TokenStream>
.enumerate()
.map(|(i, assign)| quote!(out[#i] = #assign;));

let doc = (!attr::has_docs(&attrs)).then(|| {
let selector = hex::encode_prefixed(selector.array);
attr::mk_doc(format!(
"Event with signature `{signature}` and selector `{selector}`."
))
});
let tokens = quote! {
#doc
#(#attrs)*
#[allow(non_camel_case_types, non_snake_case, clippy::style)]
pub struct #name {
Expand Down
15 changes: 15 additions & 0 deletions crates/sol-macro/src/expand/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use super::{
expand_fields, expand_from_into_tuples, expand_tuple_types, ty::expand_tokenize_func, ExpCtxt,
};
use crate::attr;
use ast::ItemFunction;
use proc_macro2::TokenStream;
use quote::quote;
Expand Down Expand Up @@ -66,14 +67,28 @@ pub(super) fn expand(cx: &ExpCtxt<'_>, function: &ItemFunction) -> Result<TokenS
let selector = crate::utils::selector(&signature);
let tokenize_impl = expand_tokenize_func(arguments.iter());

let call_doc = (!attr::has_docs(attrs)).then(|| {
let selector = hex::encode_prefixed(selector.array);
attr::mk_doc(format!(
"Function with signature `{signature}` and selector `0x{selector}`."
))
});
let return_doc = (!attr::has_docs(&return_attrs)).then(|| {
attr::mk_doc(format!(
"Container type for the return parameters of the [`{signature}`]({call_name}) function."
))
});

let tokens = quote! {
#call_doc
#(#call_attrs)*
#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone)]
pub struct #call_name {
#(#call_fields),*
}

#return_doc
#(#return_attrs)*
#[allow(non_camel_case_types, non_snake_case)]
#[derive(Clone)]
Expand Down