Support for @rust-attr on enums

This commit is contained in:
Olivier Goffart 2023-06-19 19:19:11 +02:00 committed by Olivier Goffart
parent a84aa70cd0
commit fdec5960bd
8 changed files with 136 additions and 103 deletions

View file

@ -7,13 +7,13 @@
extern crate proc_macro;
use core::iter::IntoIterator;
use core::str::FromStr;
use proc_macro::{TokenStream, TokenTree};
use proc_macro::{Delimiter, TokenStream, TokenTree};
fn error(e: &str) -> String {
format!("::core::compile_error!{{\"{}\"}}", e)
}
fn generate_test(fn_name: &str, doc: &str) -> String {
fn generate_test(fn_name: &str, doc: &str, extra_args: usize) -> String {
if fn_name.is_empty() {
return error("Could not parse function name");
}
@ -61,12 +61,14 @@ fn generate_test(fn_name: &str, doc: &str) -> String {
if line.is_empty() {
continue;
}
tests += &format!(r#"
#[test] fn parser_test_{fn}_{i}()
let follow_args = ", Default::default()".repeat(extra_args);
tests += &format!(
r#"
#[test] fn parser_test_{fn_name}_{i}()
{{
let mut diag = Default::default();
let mut p = DefaultParser::new("{source}", &mut diag);
{fn}(&mut p);
let mut p = DefaultParser::new("{line}", &mut diag);
{fn_name}(&mut p{follow_args});
let has_error = p.diags.has_error();
//#[cfg(feature = "display-diagnostics")]
//p.diags.print();
@ -74,7 +76,8 @@ fn generate_test(fn_name: &str, doc: &str) -> String {
assert_eq!(p.cursor, p.tokens.len());
{verify}
}}
"#, fn = fn_name, i = i, source = line, verify = verify)
"#,
)
}
tests
}
@ -87,6 +90,7 @@ pub fn parser_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
let mut item = item.into_iter();
let mut fn_name = String::new();
let mut extra_args = 0;
// Extract the doc comment.
// Bail out once we find a token that does not fit the doc comment pattern
@ -146,9 +150,32 @@ pub fn parser_test(_attr: TokenStream, item: TokenStream) -> TokenStream {
}
}
let test_function = TokenStream::from_str(&generate_test(&fn_name, &doc)).unwrap_or_else(|e| {
TokenStream::from_str(&error(&format!("Lex error in generated test: {:?}", e))).unwrap()
});
loop {
match item.next() {
None => break,
Some(TokenTree::Group(g)) if g.delimiter() == Delimiter::Parenthesis => {
let mut had_coma = false;
for tt in g.stream().into_iter() {
match tt {
TokenTree::Punct(p) if p.as_char() == ',' => {
had_coma = true;
}
TokenTree::Punct(p) if p.as_char() == ':' && had_coma => {
extra_args += 1;
had_coma = false;
}
_ => {}
}
}
}
_ => (),
}
}
let test_function = TokenStream::from_str(&generate_test(&fn_name, &doc, extra_args))
.unwrap_or_else(|e| {
TokenStream::from_str(&error(&format!("Lex error in generated test: {:?}", e))).unwrap()
});
result.extend(test_function);
result