#doctest #quote #macro #syn

quote-doctest

A simple doctest generator for quote

9 releases

0.3.2 Apr 12, 2022
0.3.1 Apr 10, 2022
0.2.2 Apr 3, 2022
0.1.2 Apr 1, 2022

#1660 in Procedural macros

21 downloads per month
Used in flexgen

MIT/Apache

84KB
1.5K SLoC

quote-doctest

Crate Docs

A simple doctest and doc comment generator for quote

Overview

Currently, quote does not support interpolation inside of comments, which means no customized doctests. This crate provides a simple mechanism to generate doctests and doc comments for inclusion in generated code.

[dependencies]
quote-doctest = "0.3"

Example

Using the doc_test macro, we can take any TokenStream and turn it into a doctest TokenStream that can be interpolated in any quote macro invocation.

The doc_comment function takes any string and turns it into one or more comments inside a TokenStream.

use quote::quote;
use quote_doctest::{doc_comment, doc_test, FormatDocTest};

fn main() {
    // Takes any `TokenStream` as input (but typically `quote` would be used)
    let test = doc_test!(quote! {
        _comment_!("Calling fibonacci with 10 returns 55");
        assert_eq!(fibonacci(10), 55);
    
        _blank_!();
        _comment_!("Calling fibonacci with 1 simply returns 1");
        assert_eq!(fibonacci(1), 1);
    }).unwrap();
  
    let comment = doc_comment("This compares fib inputs and outputs:\n\n");
  
    // Interpolates into a regular `quote` invocation
    let actual = quote! {
        #comment
        #test
        fn fibonacci(n: u64) -> u64 {
            match n {
                0 => 1,
                1 => 1,
                n => fibonacci(n - 1) + fibonacci(n - 2),
            }
        }
    };
  
    // This is what is generated:
    let expected = quote! {
        /// This compares fib inputs and outputs:
        ///
        /// ```
        /// // Calling fibonacci with 10 returns 55
        /// assert_eq!(fibonacci(10), 55);
        ///
        /// // Calling fibonacci with 1 simply returns 1
        /// assert_eq!(fibonacci(1), 1);
        /// ```
        fn fibonacci(n: u64) -> u64 {
            match n {
                0 => 1,
                1 => 1,
                n => fibonacci(n - 1) + fibonacci(n - 2),
            }
        }
    };
  
    assert_eq!(expected.format_tokens().unwrap(), actual.format_tokens().unwrap());
}

Notes

  • It leverages the rust-format crate which can use both prettyplease (default) or the system rustfmt for formatting the doctests
    • When using rustfmt, it honors the RUSTFMT environment variable if set
  • Since comments and blank lines are whitespace to the parser, marker macros are used to map out where the comments and blank lines should appear. These will be replaced by comments and blank lines respectively in the doctest (as shown in the example above)

License

This project is licensed optionally under either:

Dependencies

~1.5MB
~34K SLoC