Help with proc macros

Hi,
I have a question if the following scenario is possible with proc_macro_attribute, proc_macro_derive or proc_macro:
I have the following trait:

pub trait Handle {
  fn handle(&self, method: &str);
}

Then I want to use a proc_macro_derive to implement the trait to an arbitrary struct.
Additional, there should be a proc_macro_attribute, which change the implementation of the Handle trait.
For examples:

#[derive(Handle)]
pub struct Item1 {
    ...
}

impl Item1 {
  #[handle]
  pub fn method_1() {
    ...
  }

  #[handle]
  pub fn method_2() {
    ...
  }
}

Should be transformed to:

pub struct Item1 {
    ...
}

impl Handle for Item1 {
    pub fn handle(&self, method: &str) {
      match method {
        "method_1" => {   // This arm was added because the method_1 have a #[handle]
          self.method_1();  
        },
        "method_2" => {   // This arm was added because the method_2 have a #[handle]
          self.method_2();  
        }
        _ => {
          ...
        }
      }
    }
  }
}

impl Item1 {
  #[handle]
  pub fn method_1() {
    ...
  }

  #[handle]
  pub fn method_2() {
    ...
  }
}

You can see that the implementation of Handle depends if the struct have methods with the proc_macro_attribute handle?
Is this in rust even possible?

Thank you for your help.

proc macros can’t see other attributes in the crate while they are being processed. You could move the #[handle] attribute to be on Item1 like so

#[derive(Handle)]
#[handle(method_1, method_2)]
pub struct Item1 { ... }

impl Item1 {
    fn method_1(&self) {}

    fn method_2(&self) {}
}

So the #[handle(method_1, method_2)] is a proc_macro_attribute? Do you have any example Code for this?

You can see other attributes when you make your proc_macro_derive.

You can register your custom attribute like so, note the attributes(handler)

#[proc_macro_derive(Handler, attributes(handler))]
fn handler_impl(..) -> .. { .. }

Then you can use Struct syn::DeriveInput::attrs to find your custom attribute and parse it from there.

1 Like

Thank you. It worked.