use crate::{
used_proc_macro::{
Span, TokenStream, TokenTree
},
parsing_shared::{out_ident, out_parenthesized, panicking_parse_macro_invocation, parse_paren_args},
splitting_generics::{PostGenericsParser, SplitGenerics},
mmatches,
};
use core::{
iter::once,
mem,
};
use alloc::string::ToString;
struct ImplHeader {
type_: TokenStream,
type_span: Span,
trait_: Option<TokenStream>,
trait_span: Span,
location: ParseLocation,
}
impl PostGenericsParser for ImplHeader {
fn consume_token(&mut self, sg: &SplitGenerics, tt: TokenTree) {
match self.location {
ParseLocation::BeforeStart => {
self.location = if mmatches!(&tt, TokenTree::Ident(i) if i.to_string() == "dyn" ) {
ParseLocation::IgnoreFor
} else {
ParseLocation::Started
};
},
ParseLocation::Started => {
if mmatches!(&tt, TokenTree::Ident(i) if i.to_string() == "for" ) {
self.trait_span = self.type_span;
self.trait_ = Some(mem::replace(&mut self.type_, TokenStream::new()));
self.location = ParseLocation::IgnoreFor;
return;
}
}
ParseLocation::IgnoreFor => {}
}
self.type_span = sg.last_span();
self.type_.extend(once(tt));
}
fn write_tokens(self, ts: &mut TokenStream) {
if let Some(trait_) = self.trait_ {
out_ident("trait", self.trait_span, ts);
out_parenthesized(trait_, self.trait_span, ts);
}
out_ident("type", self.type_span, ts);
out_parenthesized(self.type_, self.type_span, ts);
}
}
pub(crate) fn split_impl(ts: TokenStream) -> TokenStream {
let mut ts = ts.into_iter();
let macro_invoc = panicking_parse_macro_invocation(&mut ts);
let parsed_tt = ts.next().expect("expected more tokens");
let mut parsing = parse_paren_args(&parsed_tt);
let mut out = TokenStream::new();
let mut attrs = TokenStream::new();
let mut attrs_span = Span::call_site();
let mut qualifiers = TokenStream::new();
let mut qualifiers_span = Span::call_site();
let mut which_one = &mut attrs;
let mut which_span = &mut attrs_span;
while let Some(tt) = parsing.peek() {
if let TokenTree::Ident(ident) = tt {
if ident.to_string() == "impl" {
parsing.next();
break
} else {
which_one = &mut qualifiers;
which_span = &mut qualifiers_span;
}
}
*which_span = tt.span();
which_one.extend(parsing.next());
}
out_parenthesized(attrs, attrs_span, &mut out);
out_parenthesized(qualifiers, qualifiers_span, &mut out);
SplitGenerics::some_consumed(parsing).split_generics(macro_invoc, out, ImplHeader{
type_: TokenStream::new(),
type_span: Span::call_site(),
trait_: None,
trait_span: Span::call_site(),
location: ParseLocation::BeforeStart,
})
}
enum ParseLocation {
BeforeStart,
Started,
IgnoreFor,
}