use syn::parse::{Parse, ParseStream}; use syn::spanned::Spanned; use syn::{braced, Ident, ItemImpl, Path, Type, TypePath, WhereClause}; pub struct MockInput { pub mock: Ident, pub mocked_trait: Path, pub item_impl: ItemImpl, } impl Parse for MockInput { fn parse(input: ParseStream) -> Result { let mock = input.parse::()?; let _generics = input.parse::>()?; let _braced_content; let _brace = braced!(_braced_content in input); let item_impl = input.parse::()?; let Some((_, mocked_trait, _)) = &item_impl.trait_ else { return Err(syn::Error::new(item_impl.impl_token.span, "Impl must be of a trait")); }; if !matches!( item_impl.self_ty.as_ref(), Type::Path(TypePath { qself: None, path }) if path.is_ident(&mock) ) { return Err(syn::Error::new( item_impl.self_ty.span(), "Expected this to be the mock", )); } Ok(Self { mock, mocked_trait: mocked_trait.clone(), item_impl, }) } }