1extern crate proc_macro;
7use proc_macro::TokenStream;
8
9#[rustversion::since(1.51)]
10macro_rules! iter {
11 ($span:expr => $($tt:tt)*) => {
12 quote::quote_spanned! { $span => [ $($tt)* ] }
13 };
14}
15#[rustversion::before(1.51)]
16macro_rules! iter {
17 ($span:expr => $($tt:tt)*) => {
18 quote::quote_spanned! { $span => ::std::vec![ $($tt)* ] }
19 };
20}
21
22mod helpers;
23mod question;
24
25use question::*;
26use syn::{parse::Parse, parse_macro_input, Token};
27
28#[proc_macro]
29pub fn questions(item: TokenStream) -> TokenStream {
30 let p = parse_macro_input!(item as Questions);
31
32 let questions = p.questions.into_iter();
33
34 if p.inline {
35 iter! { proc_macro2::Span::call_site() => #(#questions),* }
36 } else {
37 quote::quote! { ::std::vec![ #(#questions),* ] }
38 }
39 .into()
40}
41
42struct Questions {
43 inline: bool,
44 questions: syn::punctuated::Punctuated<Question, Token![,]>,
45}
46
47impl Parse for Questions {
48 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
49 let inline = input
50 .step(|c| match c.ident() {
51 Some((ident, c)) if ident == "inline" => Ok(((), c)),
52 _ => Err(c.error("no inline")),
53 })
54 .is_ok();
55
56 Ok(Self {
57 inline,
58 questions: input.parse_terminated(Question::parse, Token![,])?,
59 })
60 }
61}