seesaw_macros/
lib.rs

1use proc_macro2::{Span, TokenStream};
2use quote::ToTokens as _;
3use syn::{
4    parse::Nothing, parse_macro_input, token, AttrStyle, Attribute, ImplItem, ItemImpl, Meta, Path,
5    Token,
6};
7
8/// Accept an `impl` block, and add a `#[no_mangle]` attribute to each of the member
9#[proc_macro_attribute]
10pub fn no_mangle(
11    attr: proc_macro::TokenStream,
12    item: proc_macro::TokenStream,
13) -> proc_macro::TokenStream {
14    let config = parse_macro_input!(attr as Nothing);
15    let item = parse_macro_input!(item as ItemImpl);
16    expand(config, item)
17        .unwrap_or_else(syn::Error::into_compile_error)
18        .into()
19}
20
21fn expand(_: Nothing, mut item: ItemImpl) -> syn::Result<TokenStream> {
22    let span = Span::call_site();
23    for item in &mut item.items {
24        if let ImplItem::Fn(it) = item {
25            if !it.attrs.iter().any(|it| it.path().is_ident("no_mangle")) {
26                it.attrs.push(Attribute {
27                    pound_token: Token![#](span),
28                    style: AttrStyle::Outer,
29                    bracket_token: token::Bracket(span),
30                    meta: Meta::Path(Path::from(syn::Ident::new("no_mangle", span))),
31                });
32            }
33        }
34    }
35    Ok(item.into_token_stream())
36}