use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
use super::Config;
use crate::defs::*;
use crate::Function;
impl Config {
pub fn emit_test_decl(&self, func: &Function) -> TokenStream {
if !self.has_test_fn() {
return TokenStream::new();
}
let test_attr = match &self.test_fn {
Some(f) => f.clone(),
None if func.is_async => [
TokenTree::Ident(Ident::new("tokio", Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("test", Span::mixed_site()))
].into_iter().collect(),
None => [
TokenTree::Ident(Ident::new("test", Span::mixed_site()))
].into_iter().collect(),
};
let mut res = vec![
TokenTree::Punct(Punct::new('#', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::Bracket, test_attr))
];
for attr in &func.attr {
res.push(TokenTree::Punct(Punct::new('#', Spacing::Alone)));
res.push(attr.clone());
}
res.into_iter().collect()
}
pub fn emit_generic(&self, _func: &Function) -> TokenStream {
[
TokenTree::Ident(Ident::new("use", Span::mixed_site())),
TokenTree::Ident(Ident::new(CRATE_NAME, Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("prelude", Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Punct(Punct::new('*', Spacing::Alone)),
TokenTree::Punct(Punct::new(';', Spacing::Alone)),
TokenTree::Ident(Ident::new("let", Span::mixed_site())),
TokenTree::Ident(Ident::new(VARNAME_CURENT_TEST, Span::mixed_site())),
TokenTree::Punct(Punct::new('=', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::Parenthesis, [
TokenTree::Punct(Punct::new('|', Spacing::Alone)),
TokenTree::Punct(Punct::new('|', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::Brace, [
TokenTree::Ident(Ident::new(CRATE_NAME, Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("Location", Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("new", Span::mixed_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
].into_iter().collect())),
].into_iter().collect())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
TokenTree::Punct(Punct::new(';', Spacing::Alone)),
].into_iter().collect()
}
pub fn emit_skip_fn(&self, func: &Function) -> TokenStream {
let Some(skip_fn) = &self.skip_fn else {
return TokenStream::new();
};
let mut inner_block = vec![
TokenTree::Ident(Ident::new(CRATE_NAME, Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("mark_skipped", Span::mixed_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, [
TokenTree::Punct(Punct::new('&', Spacing::Joint)),
TokenTree::Ident(Ident::new(VARNAME_CURENT_TEST, Span::mixed_site()))
].into_iter().collect())),
TokenTree::Punct(Punct::new(';', Spacing::Alone)),
TokenTree::Ident(Ident::new("return", Span::call_site())),
];
match &self.skip_result {
Some(r) => inner_block.extend(r.clone()),
None => inner_block.extend(func.default_return()),
}
[
TokenTree::Ident(Ident::new("if", Span::mixed_site())),
TokenTree::Punct(Punct::new('!', Spacing::Alone)),
TokenTree::Group(Group::new(Delimiter::Parenthesis, skip_fn.clone())),
TokenTree::Group(Group::new(Delimiter::Brace, TokenStream::new())),
TokenTree::Ident(Ident::new("else", Span::mixed_site())),
TokenTree::Group(Group::new(Delimiter::Brace, inner_block.into_iter().collect())),
].into_iter().collect()
}
pub fn emit_lock(&self, _func: &Function) -> TokenStream {
if self.uses.is_empty() && self.consumes.is_empty() {
return TokenStream::new();
}
let mut builder = vec![
TokenTree::Ident(Ident::new("let", Span::mixed_site())),
TokenTree::Ident(Ident::new("_resource_lock", Span::mixed_site())),
TokenTree::Punct(Punct::new('=', Spacing::Alone)),
TokenTree::Ident(Ident::new(CRATE_NAME, Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("ResourceBuilder", Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("new", Span::mixed_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
];
for u in self.uses.iter() {
builder.extend([
TokenTree::Punct(Punct::new('.', Spacing::Alone)),
TokenTree::Ident(Ident::new("uses", Span::mixed_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, u.clone()))
]);
}
for c in self.consumes.iter() {
builder.extend([
TokenTree::Punct(Punct::new('.', Spacing::Alone)),
TokenTree::Ident(Ident::new("consumes", Span::mixed_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, c.clone()))
]);
}
builder.extend([
TokenTree::Punct(Punct::new('.', Spacing::Alone)),
TokenTree::Ident(Ident::new("reserve", Span::mixed_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, [
TokenTree::Punct(Punct::new('&', Spacing::Alone)),
TokenTree::Ident(Ident::new(CRATE_NAME, Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("RESOURCES", Span::mixed_site())),
TokenTree::Punct(Punct::new(',', Spacing::Alone)),
TokenTree::Punct(Punct::new('&', Spacing::Joint)),
TokenTree::Ident(Ident::new(VARNAME_CURENT_TEST, Span::mixed_site())),
].into_iter().collect())),
TokenTree::Punct(Punct::new(';', Spacing::Joint)),
]);
builder.into_iter().collect()
}
pub fn emit_timeout(self, func: &Function) -> TokenStream {
let Some(timeout) = self.timeout else {
return func.body.clone();
};
let mut args = vec![
TokenTree::Punct(Punct::new('&', Spacing::Joint)),
TokenTree::Ident(Ident::new(VARNAME_CURENT_TEST, Span::mixed_site())),
TokenTree::Punct(Punct::new(',', Spacing::Alone)),
];
args.extend(timeout);
args.extend([
TokenTree::Punct(Punct::new(',', Spacing::Alone)),
]);
args.extend([
TokenTree::Ident(Ident::new("move", Span::mixed_site())),
TokenTree::Punct(Punct::new('|', Spacing::Alone)),
TokenTree::Punct(Punct::new('|', Spacing::Alone)),
]);
if func.is_async {
args.push(TokenTree::Ident(Ident::new("async", Span::mixed_site())));
}
args.extend(func.body.clone());
let mut res = vec![
TokenTree::Ident(Ident::new(CRATE_NAME, Span::mixed_site())),
TokenTree::Punct(Punct::new(':', Spacing::Joint)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("panic_after", Span::mixed_site())),
TokenTree::Group(Group::new(Delimiter::Parenthesis, args.into_iter().collect())),
];
if func.is_async {
res.extend([
TokenTree::Punct(Punct::new('.', Spacing::Alone)),
TokenTree::Ident(Ident::new("await", Span::mixed_site())),
]);
}
res.into_iter().collect()
}
}