Skip to content

Commit

Permalink
Added Custom derive macro (#15)
Browse files Browse the repository at this point in the history
This allows using `#[custom(...)]` in macro_rules derive

#9

---------

Co-authored-by: Daniel Henry-Mantilla <daniel.henry.mantilla@gmail.com>
  • Loading branch information
ModProg and danielhenrymantilla authored May 10, 2023
1 parent 181640c commit 6cd193f
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 36 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "macro_rules_attribute"
version = "0.1.3" # Keep in sync
version = "0.1.4" # Keep in sync
authors = ["Daniel Henry-Mantilla <daniel.henry.mantilla@gmail.com>"]
edition = "2018"

Expand All @@ -19,7 +19,7 @@ readme = "README.md"
paste.version = "1.0.7"

[dependencies.macro_rules_attribute-proc_macro]
version = "0.1.3" # Keep in sync
version = "0.1.4" # Keep in sync
path = "src/proc_macro"

[features]
Expand Down
12 changes: 12 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ pub use ::macro_rules_attribute_proc_macro::macro_rules_attribute as apply;
/// This, as with any `#[derive(...)]`, **does not consume** the item it
/// decorates: instead, it only generates code on top of it.
///
/// Also derives [`Custom`] to allow using `#[custom(...)]` and `#[derive_args(...)]`
/// as derive helpers.
///
/// ## Examples
///
/// ### Implementing `Into<Int>` for a given `#[repr(Int)]` `enum`:
Expand Down Expand Up @@ -516,8 +519,17 @@ fn main ()
/// This is achieved thanks to **checking for the presence of a terminating `!`
/// (or lack thereof)** to determine whether the given derive macro is a classic
/// procedural macro one or a `macro_rules!` one.
///
/// Also derives [`Custom`] to allow using `#[custom(...)]` and `#[derive_args(...)]`
/// as derive helpers.
pub use ::macro_rules_attribute_proc_macro::derive;

/// No-op macro that is automatically derived with [`derive`] or [`macro_rules_derive`]
/// to allow using the `#[custom(...)]` and `#[derive_args(...)]` attribute.
///
/// See <https://github.com/danielhenrymantilla/macro_rules_attribute-rs/issues/9> for more info.
pub use ::macro_rules_attribute_proc_macro::Custom;

attribute_alias! {
#[apply(this_macro_is_private!)] =
#[doc(hidden)]
Expand Down
2 changes: 1 addition & 1 deletion src/proc_macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ path = "mod.rs"

[package]
name = "macro_rules_attribute-proc_macro"
version = "0.1.3" # Keep in sync
version = "0.1.4" # Keep in sync
authors = ["Daniel Henry-Mantilla <daniel.henry.mantilla@gmail.com>"]
edition = "2018"

Expand Down
68 changes: 37 additions & 31 deletions src/proc_macro/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ fn macro_rules_derive (
})
.flat_map(|attr| macro_rules_attribute_impl(attr, input.clone()))
);
ret.extend(real_derive(ts!(::macro_rules_attribute::Custom)));
ret.extend(input);
#[cfg(feature = "verbose-expansions")]
eprintln!("{}", ret);
Expand All @@ -87,29 +88,6 @@ fn derive (
{
let attrs = attrs.vec();

fn real_derive (
derives: TokenStream,
) -> TokenStream
{
// `#[::core::prelude::v1::derive( #derives )]`
TokenStream::from_iter([
TT::Punct(Punct::new('#', Spacing::Alone)),
TT::Group(Group::new(
Delimiter::Bracket,
{
let mut ts: TokenStream = ts!(
::core::prelude::v1::derive
);
ts.extend([TT::Group(Group::new(
Delimiter::Parenthesis,
derives,
))]);
ts
},
))
])
}

// any `path::to::Macro!` in the derive list?
if attrs.iter().any(is_punct('!')).not() {
// This is a good old derive.
Expand Down Expand Up @@ -164,21 +142,49 @@ fn derive (
attrs_banged(true).for_each(|attr| {
ret.extend(macro_rules_attribute_impl(attr, input.clone()))
});
if attrs_banged(false).any(|_| true) {
ret.extend(real_derive(
attrs_banged(false)
.flat_map(|attr| attr.iter().cloned().chain(ts!(,)))
.collect()
,
));
}
ret.extend(real_derive(
attrs_banged(false)
.flat_map(|attr| attr.iter().cloned().chain(ts!(,)))
.chain(ts!(::macro_rules_attribute::Custom,))
.collect()
,
));
ret.extend(input);

#[cfg(feature = "verbose-expansions")]
eprintln!("{}", ret);
ret
}

#[proc_macro_derive(Custom, attributes(custom, derive_args))] pub
fn custom(_:TokenStream) -> TokenStream {
TokenStream::new()
}

fn real_derive (
derives: TokenStream,
) -> TokenStream
{
// `#[::core::prelude::v1::derive( #derives )]`
TokenStream::from_iter([
TT::Punct(Punct::new('#', Spacing::Alone)),
TT::Group(Group::new(
Delimiter::Bracket,
{
let mut ts: TokenStream = ts!(
::core::prelude::v1::derive
);
ts.extend([TT::Group(Group::new(
Delimiter::Parenthesis,
derives,
))]);
ts
},
))
])
}


#[::core::prelude::v1::derive(Clone, Copy)]
struct PathIsBangTerminated(bool);

Expand Down
20 changes: 20 additions & 0 deletions tests/custom_derive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#[macro_use]
extern crate macro_rules_attribute;

derive_alias! {
#[derive(Nothing!)] = #[derive()];
}

#[derive(Nothing!)]
#[custom(hello)]
struct Foo {
#[derive_args("test")]
x: i32,
}

#[macro_rules_derive(Nothing)]
#[custom(hello)]
struct Bar {
#[derive_args("test")]
x: i32,
}

0 comments on commit 6cd193f

Please sign in to comment.