Struct Macro

pub struct Macro { pub path: Path, pub bang_token: Not, pub delimiter: MacroDelimiter, pub tokens: TokenStream }

A macro invocation: println!("{}", mac).

Fields

path: Path
bang_token: Not
delimiter: MacroDelimiter
tokens: TokenStream

Implementations

impl Macro

fn parse_body<T: Parse>(&self) -> Result<T>

Parse the tokens within the macro invocation's delimiters into a syntax tree.

This is equivalent to syn::parse2::<T>(mac.tokens) except that it produces a more useful span when tokens is empty.

Example

use syn::{parse_quote, Expr, ExprLit, Ident, Lit, LitStr, Macro, Token};
use syn::ext::IdentExt;
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::punctuated::Punctuated;

// The arguments expected by libcore's format_args macro, and as a
// result most other formatting and printing macros like println.
//
//     println!("{} is {number:.prec$}", "x", prec=5, number=0.01)
struct FormatArgs {
    format_string: Expr,
    positional_args: Vec<Expr>,
    named_args: Vec<(Ident, Expr)>,
}

impl Parse for FormatArgs {
    fn parse(input: ParseStream) -> Result<Self> {
        let format_string: Expr;
        let mut positional_args = Vec::new();
        let mut named_args = Vec::new();

        format_string = input.parse()?;
        while !input.is_empty() {
            input.parse::<Token![,]>()?;
            if input.is_empty() {
                break;
            }
            if input.peek(Ident::peek_any) && input.peek2(Token![=]) {
                while !input.is_empty() {
                    let name: Ident = input.call(Ident::parse_any)?;
                    input.parse::<Token![=]>()?;
                    let value: Expr = input.parse()?;
                    named_args.push((name, value));
                    if input.is_empty() {
                        break;
                    }
                    input.parse::<Token![,]>()?;
                }
                break;
            }
            positional_args.push(input.parse()?);
        }

        Ok(FormatArgs {
            format_string,
            positional_args,
            named_args,
        })
    }
}

// Extract the first argument, the format string literal, from an
// invocation of a formatting or printing macro.
fn get_format_string(m: &Macro) -> Result<LitStr> {
    let args: FormatArgs = m.parse_body()?;
    match args.format_string {
        Expr::Lit(ExprLit { lit: Lit::Str(lit), .. }) => Ok(lit),
        other => {
            // First argument was not a string literal expression.
            // Maybe something like: println!(concat!(...), ...)
            Err(Error::new_spanned(other, "format string must be a string literal"))
        }
    }
}

fn main() {
    let invocation = parse_quote! {
        println!("{:?}", Instant::now())
    };
    let lit = get_format_string(&invocation).unwrap();
    assert_eq!(lit.value(), "{:?}");
}
fn parse_body_with<F: Parser>(&self, parser: F) -> Result<F::Output>

Parse the tokens within the macro invocation's delimiters using the given parser.

Trait Implementations

impl Clone for Macro

fn clone(&self) -> Self

impl Parse for Macro

fn parse(input: ParseStream<'_>) -> Result<Self>

impl ToTokens for Macro

fn to_tokens(&self, tokens: &mut TokenStream)

Auto Trait Implementations

impl !Send for Macro

impl !Sync for Macro

impl Freeze for Macro

impl RefUnwindSafe for Macro

impl Unpin for Macro

impl UnsafeUnpin for Macro

impl UnwindSafe for Macro

Blanket Implementations

impl<T> Any for Macro where T: 'static + ?Sized,

fn type_id(&self) -> TypeId

impl<T> Borrow<T> for Macro where T: ?Sized,

fn borrow(&self) -> &T

impl<T> BorrowMut<T> for Macro where T: ?Sized,

fn borrow_mut(&mut self) -> &mut T

impl<T> CloneToUninit for Macro where T: Clone,

unsafe fn clone_to_uninit(&self, dest: *mut u8)

impl<T> From<T> for Macro

fn from(t: T) -> T

Returns the argument unchanged.

impl<T> Spanned for Macro where T: Spanned + ?Sized,

fn span(&self) -> Span

impl<T> ToOwned for Macro where T: Clone,

type Owned = T;
fn to_owned(&self) -> T
fn clone_into(&self, target: &mut T)

impl<T, U> Into<U> for Macro where U: From<T>,

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

impl<T, U> TryFrom<U> for Macro where U: Into<T>,

type Error = never;
fn try_from(value: U) -> Result<T, never>

impl<T, U> TryInto<U> for Macro where U: TryFrom<T>,

type Error = <U as TryFrom<T>>::Error;
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>