Help in attribute macro

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

#[proc_macro_attribute]
pub fn get(_: TokenStream, input: TokenStream) -> TokenStream {
    let func = parse_macro_input!(input as ItemFn);
    let body = &func.block;
    // println!("{:?}", body.brace_token.span);
    // println!("{}", quote! {#body});
    let main = quote! {
      fn billionaire() -> String
        #body
      fn bi(){
        billionaire()
      }
      bi()
    };
    // println!("{}", quote! {#main});
    TokenStream::from(main)
}

#[get]
fn zuck() -> String {
    let billionaire = String::from("billionaires");
    billionaire
}

missing fn or struct for function or struct definition

What are you trying to achieve? Given your attribute macro, the code below expands to the following:

fn billionaire() -> String {
    let billionaire = String::from("billionaires");
    billionaire
}

fn bi(){
    billionaire()
}

bi()

bi() is not a valid item so you get a compilation error as expected. If you intended for it to be a call to the function bi then you'll have to put the bi() inside a function body.

I need to return the

fn zuck() -> String {
    let billionaire = String::from("billionaires");
    billionaire
}

billionaire value and customize inside function
like
let billionaire_value = billionaire();

Could you provide an example of the code you expect applying the get macro?

example of the what the use

    let main = quote! {
      fn billionaire() -> String
        #body
      let billionaire = billionaire();
      let value = format!("llama {}",billionaire);
      value
    };

Sorry I don't understand what you're saying. The example also doesn't look like the expected output but rather what you tried in your macro.

Anyway I'm gonna take a guess:

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

#[proc_macro_attribute]
pub fn get(_: TokenStream, input: TokenStream) -> TokenStream {
    let func = parse_macro_input!(input as ItemFn);
    let name = &func.sig.ident;
    let body = &func.block;

    let main = quote! {
        fn #name() -> String {
            fn billionaire() -> String #body
            let billionaire = billionaire();
            let value = format!("llama {}",billionaire);
            value
        }
    };

    TokenStream::from(main)
}

This wraps the code you wrote in a function with the same name as the one on which you apply the macro. So for example this code:

#[get]
fn zuck() -> String {
    let billionaire = String::from("billionaires");
    billionaire
}

Will result in:

fn zuck() -> String {
    fn billionaire() -> String {
        let billionaire = String::from("billionaires");
        billionaire
    }
    let billionaire = billionaire();
    let value = format!("llama {}",billionaire);
    value
}
3 Likes

that this the solution
then how to call the #name function