danielhenrymantilla/macro_rules_attribute-rs

Problem with Doc Comments

Closed this issue · 2 comments

It looks like this library breaks when you add outer doc comments to an annotated function. Inner doc comments seem to work fine though.

Example

macro_rules! nom_parser {
    ($visibility:vis fn $name:ident<$input_lifetime:lifetime>($input:ident : Input) -> $Out:ty $body:block) => {
        $visibility fn $name<$input_lifetime, E>($input: &$input_lifetime str) -> IResult<&$input_lifetime str, $Out, E>
        where
            E: ParseError<&$input_lifetime str>
        {
            $body
        }
    };
}

// Function without doc comments works fine!
#[macro_rules_attribute(nom_parser!)]
fn comment<'i>(i: Input) -> &'i str {
    let (i, _) = tag("--")(i)?;
    let (i, content) = take_till(|ch| ch == '\n')(i)?;
    if content.starts_with(' ') {
        Ok((i, &content[1..]))
    } else {
        Ok((i, content))
    }
}

/// NOT OK!
#[macro_rules_attribute(nom_parser!)]
fn ws1<'i>(i: Input) -> &'i str {
    recognize(many1(alt((multispace1, comment))))(i)
}

#[macro_rules_attribute(nom_parser!)]
fn ws0<'i>(i: Input) -> &'i str {
    //! THIS IS OK THOUGH!
    alt((ws1, multispace0))(i)
}

The ws1 function gives the following error:

error: no rules expected the token `#`
  --> libaffix/src/parser/mod.rs:61:1
   |
37 | macro_rules! nom_parser {
   | ----------------------- when calling this macro
...
61 | #[macro_rules_attribute(nom_parser!)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no rules expected this token in macro call

error: an inner attribute is not permitted in this context
  |
  = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them.

I'll just use inner doc comments for now.

Doc comments are seen by macros as [doc = "..."] attributes (#[ for outer, and #![ for inner ones).

So adding $( #[$meta:meta] )* at the top of your rule, before $visibility:vis (and then expanding to $(#[$meta])* to avoid losing the doc comments) should solve it, at least when the (outer) doc comment is located after #[macro_rules_attribute(...)]

  • EDIT: it also seems to work with a doc-comment located before the #[macro_rules_attribute(...)]

Oh! That fixed the problem! Thanks!