Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

SSL mock_function.rs

  Sprache: Rust
 

// vim: tw=80
use super::*;

use quote::ToTokens;

/// Convert a trait object reference into a reference to a Boxed trait
///
/// # Returns
///
/// Returns `true` if it was necessary to box the type.
fn dedynify(ty: &mut Type) -> bool {
    if let Type::Reference(ref mut tr) = ty {
        if let Type::TraitObject(ref tto) = tr.elem.as_ref() {
            if let Some(lt) = &tr.lifetime {
                if lt.ident == "static" {
                    // For methods that return 'static references, the user can
                    // usually actually supply one, unlike nonstatic references.
                    // dedynify is unneeded and harmful in such cases.
                    //
                    // But we do need to add parens to prevent parsing errors
                    // when methods like returning add a `+ Send` to the output
                    // type.
                    *tr.elem = parse2(quote!((#tto))).unwrap();
                    return false;
                }
            }

            *tr.elem = parse2(quote!(Box<#tto>)).unwrap();
            return true;
        }
    }
    false
}

/// Convert a special reference type like "&str" into a reference to its owned
/// type like "&String".
fn destrify(ty: &mut Type) {
    if let Type::Reference(ref mut tr) = ty {
        if let Some(lt) = &tr.lifetime {
            if lt.ident == "static" {
                // For methods that return 'static references, the user can
                // usually actually supply one, unlike nonstatic references.
                // destrify is unneeded and harmful in such cases.
                return;
            }
        }

        let path_ty: TypePath = parse2(quote!(Path)).unwrap();
        let pathbuf_ty: Type = parse2(quote!(::std::path::PathBuf)).unwrap();

        let str_ty: TypePath = parse2(quote!(str)).unwrap();
        let string_ty: Type = parse2(quote!(::std::string::String)).unwrap();

        let cstr_ty: TypePath = parse2(quote!(CStr)).unwrap();
        let cstring_ty: Type = parse2(quote!(::std::ffi::CString)).unwrap();

        let osstr_ty: TypePath = parse2(quote!(OsStr)).unwrap();
        let osstring_ty: Type = parse2(quote!(::std::ffi::OsString)).unwrap();

        match tr.elem.as_ref() {
            Type::Path(ref path) if *path == cstr_ty =>
                *tr.elem = cstring_ty,
            Type::Path(ref path) if *path == osstr_ty =>
                *tr.elem = osstring_ty,
            Type::Path(ref path) if *path == path_ty =>
                *tr.elem = pathbuf_ty,
            Type::Path(ref path) if *path == str_ty =>
                *tr.elem = string_ty,
            Type::Slice(ts) => {
                let inner = (*ts.elem).clone();
                let mut segments = Punctuated::new();
                segments.push(format_ident!("std").into());
                segments.push(format_ident!("vec").into());
                let mut v: PathSegment = format_ident!("Vec").into();
                let mut abga_args = Punctuated::new();
                abga_args.push(GenericArgument::Type(inner));
                v.arguments = PathArguments::AngleBracketed(
                    AngleBracketedGenericArguments {
                        colon2_token: None,
                        lt_token: Token![<](Span::call_site()),
                        args: abga_args,
                        gt_token: Token![>](Span::call_site()),
                    }
                );
                segments.push(v);

                *tr.elem = Type::Path(TypePath {
                    qself: None,
                    path: Path {
                        leading_colon: Some(Token![::](Span::call_site())),
                        segments
                    }
                });
            },
            _ => (), // Nothing to do
        };
    }
}

/// Return the owned version of the input.
fn ownify(ty: &Type) -> Type {
    if let Type::Reference(ref tr) = &ty {
        if tr.lifetime.as_ref().map_or(false, |lt| lt.ident == "static")
        {
            // Just a static expectation
            ty.clone()
        } else {
            *tr.elem.clone()
        }
    } else {
        ty.clone()
    }
}

/// Add Send + Sync to a where clause
fn send_syncify(wc: &mut Option<WhereClause>, bounded_ty: Type) {
    let mut bounds = Punctuated::new();
    bounds.push(TypeParamBound::Trait(TraitBound {
        paren_token: None,
        modifier: TraitBoundModifier::None,
        lifetimes: None,
        path: Path::from(format_ident!("Send"))
    }));
    bounds.push(TypeParamBound::Trait(TraitBound {
        paren_token: None,
        modifier: TraitBoundModifier::None,
        lifetimes: None,
        path: Path::from(format_ident!("Sync"))
    }));
    if wc.is_none() {
        *wc = Some(WhereClause {
            where_token: <Token![where]>::default(),
            predicates: Punctuated::new()
        });
    }
    wc.as_mut().unwrap()
    .predicates.push(
        WherePredicate::Type(
            PredicateType {
                lifetimes: None,
                bounded_ty,
                colon_token: Default::default(),
                bounds
            }
        )
    );
}

/// Build a MockFunction.
#[derive(Clone, Copy, Debug)]
pub(cratestruct Builder<'a> {
    attrs: &'a [Attribute],
    call_levels: Option<usize>,
    concretize: bool,
    levels: usize,
    parent: Option<&'a Ident>,
    sig: &'a Signature,
    struct_: Option<&'a Ident>,
    struct_generics: Option<&'a Generics>,
    trait_: Option<&'a Ident>,
    vis: &'a Visibility
}

impl<'a> Builder<'a> {
    pub fn attrs(&mut self, attrs: &'a[Attribute]) -> &mut Self {
        self.attrs = attrs;
        if attrs.iter()
            .any(is_concretize)
        {
            self.concretize = true;
        }
        self
    }

    pub fn build(self) -> MockFunction {
        let mut argnames = Vec::new();
        let mut argty = Vec::new();
        let mut is_static = true;
        let mut predexprs = Vec::new();
        let mut predty = Vec::new();
        let mut refpredty = Vec::new();

        let (mut declosured_generics, declosured_inputs, call_exprs) =
            if self.concretize {
                concretize_args(&self.sig.generics, &self.sig.inputs)
            } else {
                declosurefy(&self.sig.generics, &self.sig.inputs)
            };
        // TODO: make concretize and declosurefy work for the same function

        for fa in declosured_inputs.iter() {
            if let FnArg::Typed(pt) = fa {
                let argname = (*pt.pat).clone();
                assert!(!pat_is_self(&argname));
                let aty = supersuperfy(&pt.ty, self.levels);
                if let Type::Reference(ref tr) = aty {
                    predexprs.push(quote!(#argname));
                    predty.push((*tr.elem).clone());
                    let tr2 = Type::Reference(TypeReference {
                        and_token: tr.and_token,
                        lifetime: None,
                        mutability: None,
                        elem: tr.elem.clone()
                    });
                    refpredty.push(tr2);
                } else {
                    predexprs.push(quote!(&#argname));
                    predty.push(aty.clone());
                    let tr = TypeReference {
                        and_token: Token![&](Span::call_site()),
                        lifetime: None,
                        mutability: None,
                        elem: Box::new(aty.clone())
                    };
                    refpredty.push(Type::Reference(tr));
                };
                argnames.push(argname);
                argty.push(aty.clone());
            } else {
                is_static = false;
            }
        }
        let (output, boxed) = match self.sig.output {
            ReturnType::Default => (
                Type::Tuple(TypeTuple {
                    paren_token: token::Paren::default(),
                    elems: Punctuated::new(),
                }),
                false,
            ),
            ReturnType::Type(_, ref ty) => {
                let mut output_ty = supersuperfy(ty, self.levels);
                destrify(&mut output_ty);
                let boxed = dedynify(&mut output_ty);
                (output_ty, boxed)
            }
        };
        supersuperfy_generics(&mut declosured_generics, self.levels);
        let owned_output = ownify(&output);
        let mut return_ref = false;
        let mut return_refmut = false;
        if let Type::Reference(ref tr) = &output {
            if tr.lifetime.as_ref().map_or(true, |lt| lt.ident != "static")
            {
                if tr.mutability.is_none() {
                    return_ref = true;
                } else {
                    return_refmut = true;
                }
            }
        };
        if is_static && (return_ref || return_refmut) {
            compile_error(self.sig.span(),
                "Mockall cannot mock static methods that return non-'static references.  It's unclear what the return value's lifetime should be.");
        }
        let struct_generics = self.struct_generics.cloned()
            .unwrap_or_default();
        let (type_generics, salifetimes, srlifetimes) = split_lifetimes(
            struct_generics.clone(),
            &declosured_inputs,
            &ReturnType::Type(<Token![->]>::default(),
                              Box::new(owned_output.clone()))
        );
        let srltg = lifetimes_to_generics(&srlifetimes);
        let (call_generics, malifetimes, mrlifetimes) = split_lifetimes(
            declosured_generics,
            &declosured_inputs,
            &ReturnType::Type(<Token![->]>::default(),
                              Box::new(owned_output.clone()))
        );
        let mrltg = lifetimes_to_generics(&mrlifetimes);
        let cgenerics = merge_generics(&type_generics, &call_generics);
        let egenerics = merge_generics(
            &merge_generics(&cgenerics, &srltg),
            &mrltg);
        let alifetimes = salifetimes.into_iter()
            .collect::<HashSet<LifetimeParam>>()
            .union(&malifetimes.into_iter().collect::<HashSet<_>>())
            .cloned()
            .collect();

        let fn_params = egenerics.type_params()
            .map(|tp| tp.ident.clone())
            .collect();
        let call_levels = self.call_levels.unwrap_or(self.levels);

        MockFunction {
            alifetimes,
            argnames,
            argty,
            attrs: self.attrs.to_vec(),
            call_exprs,
            call_generics,
            call_vis: expectation_visibility(self.vis, call_levels),
            concretize: self.concretize,
            egenerics,
            cgenerics,
            fn_params,
            is_static,
            mod_ident: self.parent.unwrap_or(&Ident::new("FIXME", Span::call_site())).clone(),
            output,
            owned_output,
            boxed,
            predexprs,
            predty,
            refpredty,
            return_ref,
            return_refmut,
            sig: self.sig.clone(),
            struct_: self.struct_.cloned(),
            struct_generics,
            trait_: self.trait_.cloned(),
            type_generics,
            privmod_vis: expectation_visibility(self.vis, self.levels)
        }
    }

    /// How many levels of modules beneath the original function this one is
    /// nested.
    pub fn call_levels(&mut self, levels: usize) -> &mut Self {
        self.call_levels = Some(levels);
        self
    }

    /// How many levels of modules beneath the original function this one's
    /// private module is nested.
    pub fn levels(&mut self, levels: usize) -> &mut Self {
        self.levels = levels;
        self
    }

    /// # Arguments
    ///
    /// * sig:      The signature of the mockable function
    /// * v:        The visibility of the mockable function
    pub fn new(sig: &'a Signature, vis: &'a Visibility) -> Self {
        Builder {
            attrs: &[],
            concretize: false,
            levels: 0,
            call_levels: None,
            parent: None,
            sig,
            struct_: None,
            struct_generics: None,
            trait_: None,
            vis
        }
    }

    /// Supply the name of the parent module
    pub fn parent(&mut self, ident: &'a Ident) -> &mut Self {
        self.parent = Some(ident);
        self
    }

    /// Supply the name of the parent struct, if any
    pub fn struct_(&mut self, ident: &'a Ident) -> &mut Self {
        self.struct_= Some(ident);
        self
    }

    /// Supply the Generics of the parent struct, if any
    pub fn struct_generics(&mut self, generics: &'a Generics) -> &mut Self {
        self.struct_generics = Some(generics);
        self
    }

    /// Supply the name of the method's trait, if any
    pub fn trait_(&mut self, ident: &'a Ident) -> &mut Self {
        self.trait_ = Some(ident);
        self
    }
}

#[derive(Clone)]
pub(cratestruct MockFunction {
    /// Lifetimes of the mocked method that relate to the arguments but not the
    /// return value
    alifetimes: Punctuated<LifetimeParam, token::Comma>,
    /// Names of the method arguments
    argnames: Vec<Pat>,
    /// Types of the method arguments
    argty: Vec<Type>,
    /// any attributes on the original function, like #[inline]
    pub attrs: Vec<Attribute>,
    /// Expressions that should be used for Expectation::call's arguments
    call_exprs: Vec<TokenStream>,
    /// Generics used for the expectation call
    call_generics: Generics,
    /// Visibility of the mock function itself
    call_vis: Visibility,
    /// Are we turning generic arguments into concrete trait objects?
    concretize: bool,
    /// Generics of the Expectation object
    egenerics: Generics,
    /// Generics of the Common object
    cgenerics: Generics,
    /// The mock function's generic types as a list of types
    fn_params: Vec<Ident>,
    /// Is this for a static method or free function?
    is_static: bool,
    /// name of the function's parent module
    mod_ident: Ident,
    /// Output type of the Method, supersuperfied.
    output: Type,
    /// Owned version of the output type of the Method, supersuperfied.
    ///
    /// If the real output type is a non-'static reference, then it will differ
    /// from this field.
    owned_output: Type,
    /// True if the `owned_type` is boxed by `Box<>`.
    boxed: bool,
    /// Expressions that create the predicate arguments from the call arguments
    predexprs: Vec<TokenStream>,
    /// Types used for Predicates.  Will be almost the same as args, but every
    /// type will be a non-reference type.
    predty: Vec<Type>,
    /// Does the function return a non-'static reference?
    return_ref: bool,
    /// Does the function return a mutable reference?
    return_refmut: bool,
    /// References to every type in `predty`.
    refpredty: Vec<Type>,
    /// The signature of the mockable function
    sig: Signature,
    /// Name of the parent structure, if any
    struct_: Option<Ident>,
    /// Generics of the parent structure
    struct_generics: Generics,
    /// Name of this method's trait, if the method comes from a trait
    trait_: Option<Ident>,
    /// Type generics of the mock structure
    type_generics: Generics,
    /// Visibility of the expectation and its methods
    privmod_vis: Visibility
}

impl MockFunction {
    /// Return the mock function itself
    ///
    /// # Arguments
    ///
    /// * `modname`:    Name of the parent struct's private module
    // Supplying modname is an unfortunately hack.  Ideally MockFunction
    // wouldn't need to know that.
    pub fn call(&self, modname: Option<&Ident>) -> impl ToTokens {
        let attrs = AttrFormatter::new(&self.attrs).format();
        let call_exprs = &self.call_exprs;
        let (_, tg, _) = if self.is_method_generic() || self.is_static() {
            &self.egenerics
        } else {
            &self.call_generics
        }.split_for_impl();
        let tbf = tg.as_turbofish();
        let name = self.name();
        let desc = self.desc();
        let no_match_msg = quote!(std::format!(
            "{}: No matching expectation found"#desc));
        let sig = &self.sig;
        let (vis, dead_code) = if self.trait_.is_some() {
            (&Visibility::Inherited, quote!())
        } else {
            let dead_code = if let Visibility::Inherited = self.call_vis {
                // This private method may be a helper only used by the struct's
                // other methods, which we are mocking.  If so, the mock method
                // will be dead code.  But we can't simply eliminate it, because
                // it might also be used by other code in the same module.
                quote!(#[allow(dead_code)])
            } else {
                quote!()
            };
            (&self.call_vis, dead_code)
        };
        // Add #[no_mangle] attribute to preserve the function name
        // as-is, without mangling, for compatibility with C functions.
        let no_mangle = if let Some(ref abi) = self.sig.abi {
            if let Some(ref name) = abi.name {
                if name.value().ne("Rust") {
                    quote!(#[no_mangle])
                } else {
                    quote!()
                }
            } else {
                // This is the same as extern "C"
                quote!(#[no_mangle])
            }
        } else {
            quote!()
        };
        let substruct_obj: TokenStream = if let Some(trait_) = &self.trait_ {
            let ident = format_ident!("{}_expectations", trait_);
            quote!(#ident.)
        } else {
            quote!()
        };
        let call = if self.return_refmut {
            Ident::new("call_mut", Span::call_site())
        } else {
            Ident::new("call", Span::call_site())
        };
        let mut deref = quote!();
        if self.boxed {
            if self.return_ref {
                deref = quote!(&**);
            } else if self.return_refmut {
                deref = quote!(&mut **);
            }
        }
        if self.is_static {
            let outer_mod_path = self.outer_mod_path(modname);
            quote!(
                // Don't add a doc string.  The original is included in #attrs
                #(#attrs)*
                #dead_code
                #no_mangle
                #vis #sig {
                    use ::mockall::{ViaDebug, ViaNothing};
                    let no_match_msg = #no_match_msg;
                    #deref {
                        let __mockall_guard = #outer_mod_path::EXPECTATIONS
                            .lock().unwrap();
                        /*
                         * TODO: catch panics, then gracefully release the mutex
                         * so it won't be poisoned.  This requires bounding any
                         * generic parameters with UnwindSafe
                         */

                        /* std::panic::catch_unwind(|| */
                        __mockall_guard.#call #tbf(#(#call_exprs,)*)
                        /*)*/
                    }.expect(&no_match_msg)
                }
            )
        } else {
            quote!(
                // Don't add a doc string.  The original is included in #attrs
                #(#attrs)*
                #dead_code
                #no_mangle
                #vis #sig {
                    use ::mockall::{ViaDebug, ViaNothing};
                    let no_match_msg = #no_match_msg;
                    #deref self.#substruct_obj #name.#call #tbf(#(#call_exprs,)*)
                    .expect(&no_match_msg)
                }

            )
        }
    }

    /// Return this method's contribution to its parent's checkpoint method
    pub fn checkpoint(&self) -> impl ToTokens {
        let attrs = AttrFormatter::new(&self.attrs)
            .doc(false)
            .format();
        let inner_mod_ident = self.inner_mod_ident();
        if self.is_static {
            quote!(
                #(#attrs)*
                {
                    let __mockall_timeses = #inner_mod_ident::EXPECTATIONS.lock()
                        .unwrap()
                        .checkpoint()
                        .collect::<Vec<_>>();
                }
            )
        } else {
            let name = &self.name();
            quote!(#(#attrs)* { self.#name.checkpoint(); })
        }
    }

    /// Return a function that creates a Context object for this function
    ///
    /// # Arguments
    ///
    /// * `modname`:    Name of the parent struct's private module
    // Supplying modname is an unfortunately hack.  Ideally MockFunction
    // wouldn't need to know that.
    pub fn context_fn(&self, modname: Option<&Ident>) -> impl ToTokens {
        let attrs = AttrFormatter::new(&self.attrs)
            .doc(false)
            .format();
        let context_docstr = format!("Create a [`Context`]({}{}/struct.Context.html) for mocking the `{}` method",
            modname.map(|m| format!("{m}/")).unwrap_or_default(),
            self.inner_mod_ident(),
            self.name());
        let context_ident = format_ident!("{}_context"self.name());
        let (_, tg, _) = self.type_generics.split_for_impl();
        let outer_mod_path = self.outer_mod_path(modname);
        let v = &self.call_vis;
        quote!(
            #(#attrs)*
            #[doc = #context_docstr]
            #v fn #context_ident() -> #outer_mod_path::Context #tg
            {
                #outer_mod_path::Context::default()
            }
        )
    }

    /// Generate a code fragment that will print a description of the invocation
    fn desc(&self) -> impl ToTokens {
        let argnames = &self.argnames;
        let name = if let Some(s) = &self.struct_ {
            format!("{}::{}", s, self.sig.ident)
        } else {
            format!("{}::{}"self.mod_ident, self.sig.ident)
        };
        let fields = vec!["{:?}"; argnames.len()].join(", ");
        let fstr = format!("{name}({fields})");
        quote!(std::format!(#fstr#((&&::mockall::ArgPrinter(&#argnames)).debug_string()),*))
    }

    /// Generate code for the expect_ method
    ///
    /// # Arguments
    ///
    /// * `modname`:    Name of the parent struct's private module
    /// * `self_args`:  If supplied, these are the
    ///                 AngleBracketedGenericArguments of the self type of the
    ///                 trait impl.  e.g. The `T` in `impl Foo for Bar<T>`.
    // Supplying modname is an unfortunately hack.  Ideally MockFunction
    // wouldn't need to know that.
    pub fn expect(&self, modname: &Ident, self_args: Option<&PathArguments>)
        -> impl ToTokens
    {
        let attrs = AttrFormatter::new(&self.attrs)
            .doc(false)
            .format();
        let name = self.name();
        let expect_ident = format_ident!("expect_{}", name);
        let expectation_obj = self.expectation_obj(self_args);
        let funcname = &self.sig.ident;
        let (_, tg, _) = if self.is_method_generic() {
            &self.egenerics
        } else {
            &self.call_generics
        }.split_for_impl();
        let (ig, _, wc) = self.call_generics.split_for_impl();
        let mut wc = wc.cloned();
        if self.is_method_generic() && (self.return_ref || self.return_refmut) {
            // Add Senc + Sync, required for downcast, since Expectation
            // stores an Option<#owned_output>
            send_syncify(&mut wc, self.owned_output.clone());
        }
        let tbf = tg.as_turbofish();
        let vis = &self.call_vis;

        #[cfg(not(feature = "nightly_derive"))]
        let must_use = quote!(#[must_use =
                "Must set return value when not using the \"nightly\" feature"
            ]);
        #[cfg(feature = "nightly_derive")]
        let must_use = quote!();

        let substruct_obj = if let Some(trait_) = &self.trait_ {
            let ident = format_ident!("{trait_}_expectations");
            quote!(#ident.)
        } else {
            quote!()
        };
        let docstr = format!("Create an [`Expectation`]({}/{}/struct.Expectation.html) for mocking the `{}` method",
            modname, self.inner_mod_ident(), funcname);
        quote!(
            #must_use
            #[doc = #docstr]
            #(#attrs)*
            #vis fn #expect_ident #ig(&mut self)
               -> &mut #modname::#expectation_obj
               #wc
            {
                self.#substruct_obj #name.expect #tbf()
            }
        )
    }

    /// Return the name of this function's expecation object
    fn expectation_obj(&self, self_args: Option<&PathArguments>)
        -> impl ToTokens
    {
        let inner_mod_ident = self.inner_mod_ident();
        if let Some(PathArguments::AngleBracketed(abga)) = self_args {
            // staticize any lifetimes that might be present in the Expectation
            // object but not in the self args.  These come from the method's
            // return type.
            let mut abga2 = abga.clone();
            for _ in self.egenerics.lifetimes() {
                let lt = Lifetime::new("'static", Span::call_site());
                let la = GenericArgument::Lifetime(lt);
                abga2.args.insert(0, la);
            }
            assert!(!self.is_method_generic(),
                "specific impls with generic methods are TODO");
            quote!(#inner_mod_ident::Expectation #abga2)
        } else {
            // staticize any lifetimes.  This is necessary for methods that
            // return non-static types, because the Expectation itself must be
            // 'static.
            let segenerics = staticize(&self.egenerics);
            let (_, tg, _) = segenerics.split_for_impl();
            quote!(#inner_mod_ident::Expectation #tg)
        }
    }

    /// Return the name of this function's expecations object
    pub fn expectations_obj(&self) -> impl ToTokens {
        let inner_mod_ident = self.inner_mod_ident();
        if self.is_method_generic() {
            quote!(#inner_mod_ident::GenericExpectations)
        } else {
            quote!(#inner_mod_ident::Expectations)
        }
    }

    pub fn field_definition(&self, modname: Option<&Ident>) -> TokenStream {
        let name = self.name();
        let attrs = AttrFormatter::new(&self.attrs)
            .doc(false)
            .format();
        let expectations_obj = &self.expectations_obj();
        if self.is_method_generic() {
            quote!(#(#attrs)* #name#modname::#expectations_obj)
        } else {
            // staticize any lifetimes.  This is necessary for methods that
            // return non-static types, because the Expectation itself must be
            // 'static.
            let segenerics = staticize(&self.egenerics);
            let (_, tg, _) = segenerics.split_for_impl();
            quote!(#(#attrs)* #name#modname::#expectations_obj #tg)
        }
    }

    /// Human-readable name of the mock function
    fn funcname(&self) -> String {
        if let Some(si) = &self.struct_ {
            format!("{}::{}", si, self.name())
        } else {
            format!("{}"self.name())
        }
    }

    fn hrtb(&self) -> Option<BoundLifetimes> {
        if self.alifetimes.is_empty() {
            None
        } else {
            let lifetimes = lifetimes_to_generic_params(&self.alifetimes);
            Some(BoundLifetimes {
                lifetimes,
                lt_token: <Token![<]>::default(),
                gt_token: <Token![>]>::default(),
                .. Default::default()
            })
        }
    }

    fn is_expectation_generic(&self) -> bool {
        self.egenerics.params.iter().any(|p| {
            matches!(p, GenericParam::Type(_))
        }) || self.egenerics.where_clause.is_some()
    }

    /// Is the mock method generic (as opposed to a non-generic method of a
    /// generic mock struct)?
    pub fn is_method_generic(&self) -> bool {
        self.call_generics.params.iter().any(|p| {
            matches!(p, GenericParam::Type(_))
        }) || self.call_generics.where_clause.is_some()
    }

    fn outer_mod_path(&self, modname: Option<&Ident>) -> Path {
        let mut path = if let Some(m) = modname {
            Path::from(PathSegment::from(m.clone()))
        } else {
            Path { leading_colon: None, segments: Punctuated::new() }
        };
        path.segments.push(PathSegment::from(self.inner_mod_ident()));
        path
    }

    fn inner_mod_ident(&self) -> Ident {
        format_ident!("__{}", &self.name())
    }

    pub fn is_static(&self) -> bool {
        self.is_static
    }

    pub fn name(&self) -> &Ident {
        &self.sig.ident
    }

    /// Generate code for this function's private module
    pub fn priv_module(&self) -> impl ToTokens {
        let attrs = AttrFormatter::new(&self.attrs)
            .doc(false)
            .format();
        let common = &Common{f: self};
        let context = &Context{f: self};
        let expectation: Box<dyn ToTokens> = if self.return_ref {
            Box::new(RefExpectation{f: self})
        } else if self.return_refmut {
            Box::new(RefMutExpectation{f: self})
        } else {
            Box::new(StaticExpectation{f: self})
        };
        let expectations: Box<dyn ToTokens> = if self.return_ref {
            Box::new(RefExpectations{f: self})
        } else if self.return_refmut {
            Box::new(RefMutExpectations{f: self})
        } else {
            Box::new(StaticExpectations{f: self})
        };
        let generic_expectations = GenericExpectations{f: self};
        let guard: Box<dyn ToTokens> = if self.is_expectation_generic() {
            Box::new(GenericExpectationGuard{f: self})
        } else {
            Box::new(ConcreteExpectationGuard{f: self})
        };
        let matcher = &Matcher{f: self};
        let std_mutexguard = if self.is_static {
            quote!(use ::std::sync::MutexGuard;)
        } else {
            quote!()
        };
        let inner_mod_ident = self.inner_mod_ident();
        let rfunc: Box<dyn ToTokens> = if self.return_ref {
            Box::new(RefRfunc{f: self})
        } else if self.return_refmut {
            Box::new(RefMutRfunc{f: self})
        } else {
            Box::new(StaticRfunc{f: self})
        };
        quote!(
            #(#attrs)*
            #[allow(missing_docs)]
            #[allow(clippy::too_many_arguments)]
            pub mod #inner_mod_ident {
                use super::*;
                use ::mockall::CaseTreeExt;
                #std_mutexguard
                use ::std::{
                    boxed::Box,
                    mem,
                    ops::{DerefMut, Range},
                    sync::Mutex,
                    vec::Vec,
                };
                #rfunc
                #matcher
                #common
                #expectation
                #expectations
                #generic_expectations
                #guard
                #context
            }
        )
    }
}

/// Holds parts of the expectation that are common for all output types
struct Common<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for Common<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let argnames = &self.f.argnames;
        let predty = &self.f.predty;
        let hrtb = self.f.hrtb();
        let funcname = self.f.funcname();
        let (ig, tg, wc) = self.f.cgenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let refpredty = &self.f.refpredty;
        let with_generics_idents = (0..self.f.predty.len())
            .map(|i| format_ident!("MockallMatcher{i}"))
            .collect::<Vec<_>>();
        let with_generics = with_generics_idents.iter()
            .zip(self.f.predty.iter())
            .map(|(id, mt)|
                quote!(#id#hrtb ::mockall::Predicate<#mt> + Send + 'static, )
            ).collect::<TokenStream>();
        let with_args = self.f.argnames.iter()
            .zip(with_generics_idents.iter())
            .map(|(argname, id)| quote!(#argname#id, ))
            .collect::<TokenStream>();
        let boxed_withargs = argnames.iter()
            .map(|aa| quote!(Box::new(#aa), ))
            .collect::<TokenStream>();
        let with_method = if self.f.concretize {
            quote!(
                // No `with` method when concretizing generics
            )
        } else {
            quote!(
                fn with<#with_generics>(&mut self#with_args)
                    {
                        let mut __mockall_guard = self.matcher.lock().unwrap();
                        *__mockall_guard.deref_mut() =
                            Matcher::Pred(Box::new((#boxed_withargs)));
                    }
            )
        };

        quote!(
            /// Holds the stuff that is independent of the output type
            struct Common #ig #wc {
                matcher: Mutex<Matcher #tg>,
                seq_handle: Option<::mockall::SeqHandle>,
                times: ::mockall::Times
            }

            impl #ig std::default::Default for Common #tg #wc
            {
                fn default() -> Self {
                    Common {
                        matcher: Mutex::new(Matcher::default()),
                        seq_handle: None,
                        times: ::mockall::Times::default()
                    }
                }
            }

            impl #ig Common #tg #wc {
                fn call(&self, desc: &str) {
                    self.times.call()
                        .unwrap_or_else(|m| {
                            let desc = std::format!(
                                "{}"self.matcher.lock().unwrap());
                            panic!("{}: Expectation({}) {}"#funcname, desc,
                                m);
                        });
                    self.verify_sequence(desc);
                    if ::mockall::ExpectedCalls::TooFew != self.times.is_satisfied() {
                        self.satisfy_sequence()
                    }
                }

                fn in_sequence(&mut self, __mockall_seq: &mut ::mockall::Sequence)
                    -> &mut Self
                {
                    assert!(self.times.is_exact(),
                        "Only Expectations with an exact call count have sequences");
                    self.seq_handle = Some(__mockall_seq.next_handle());
                    self
                }

                fn is_done(&self) -> bool {
                    self.times.is_done()
                }

                #[allow(clippy::ptr_arg)]
                fn matches #lg (&self#( #argnames: &#predty, )*) -> bool {
                    self.matcher.lock().unwrap().matches(#(#argnames, )*)
                }

                /// Forbid this expectation from ever being called.
                fn never(&mut self) {
                    self.times.never();
                }

                fn satisfy_sequence(&self) {
                    if let Some(__mockall_handle) = &self.seq_handle {
                        __mockall_handle.satisfy()
                    }
                }

                /// Expect this expectation to be called any number of times
                /// contained with the given range.
                fn times<MockallR>(&mut self, __mockall_r: MockallR)
                    where MockallR: Into<::mockall::TimesRange>
                {
                    self.times.times(__mockall_r)
                }

                #with_method

                fn withf<MockallF>(&mut self, __mockall_f: MockallF)
                    where MockallF: #hrtb Fn(#( #refpredty, )*)
                                    -> bool + Send + 'static
                {
                    let mut __mockall_guard = self.matcher.lock().unwrap();
                    *__mockall_guard.deref_mut() =
                         Matcher::Func(Box::new(__mockall_f));
                }

                fn withf_st<MockallF>(&mut self, __mockall_f: MockallF)
                    where MockallF: #hrtb Fn(#( #refpredty, )*)
                                    -> bool + 'static
                {
                    let mut __mockall_guard = self.matcher.lock().unwrap();
                    *__mockall_guard.deref_mut() =
                         Matcher::FuncSt(
                             ::mockall::Fragile::new(Box::new(__mockall_f))
                        );
                }

                fn verify_sequence(&self, desc: &str) {
                    if let Some(__mockall_handle) = &self.seq_handle {
                        __mockall_handle.verify(desc)
                    }
                }
            }

            impl #ig Drop for Common #tg #wc {
                fn drop(&mut self) {
                    if !::std::thread::panicking() {
                        let desc = std::format!(
                            "{}"self.matcher.lock().unwrap());
                        match self.times.is_satisfied() {
                            ::mockall::ExpectedCalls::TooFew => {
                                panic!("{}: Expectation({}) called {} time(s) which is fewer than expected {}",
                                    #funcname,
                                    desc,
                                    self.times.count(),
                                    self.times.minimum());
                            },
                            ::mockall::ExpectedCalls::TooMany => {
                                panic!("{}: Expectation({}) called {} time(s) which is more than expected {}",
                                    #funcname,
                                    desc,
                                    self.times.count(),
                                    self.times.maximum());
                            },
                            _ => ()
                        }
                    }
                }
            }
        ).to_tokens(tokens);
    }
}

/// Generates methods that are common for all Expectation types
struct CommonExpectationMethods<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for CommonExpectationMethods<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let argnames = &self.f.argnames;
        let hrtb = self.f.hrtb();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let predty = &self.f.predty;
        let with_generics_idents = (0..self.f.predty.len())
            .map(|i| format_ident!("MockallMatcher{i}"))
            .collect::<Vec<_>>();
        let with_generics = with_generics_idents.iter()
            .zip(self.f.predty.iter())
            .map(|(id, mt)|
                quote!(#id#hrtb ::mockall::Predicate<#mt> + Send + 'static, )
            ).collect::<TokenStream>();
        let with_args = self.f.argnames.iter()
            .zip(with_generics_idents.iter())
            .map(|(argname, id)| quote!(#argname#id, ))
            .collect::<TokenStream>();
        let v = &self.f.privmod_vis;
        let with_method = if self.f.concretize {
            quote!(
                // No `with` method when concretizing generics
            )
        } else {
            quote!(
                /// Set matching criteria for this Expectation.
                ///
                /// The matching predicate can be anything implemening the
                /// [`Predicate`](../../../mockall/trait.Predicate.html) trait.  Only
                /// one matcher can be set per `Expectation` at a time.
                #v fn with<#with_generics>(&mut self#with_args) -> &mut Self
                {
                    self.common.with(#(#argnames, )*);
                    self
                }
            )
        };
        quote!(
            /// Add this expectation to a
            /// [`Sequence`](../../../mockall/struct.Sequence.html).
            #v fn in_sequence(&mut self, __mockall_seq: &mut ::mockall::Sequence)
                -> &mut Self
            {
                self.common.in_sequence(__mockall_seq);
                self
            }

            fn is_done(&self) -> bool {
                self.common.is_done()
            }

            /// Validate this expectation's matcher.
            #[allow(clippy::ptr_arg)]
            fn matches #lg (&self#(#argnames: &#predty, )*) -> bool {
                self.common.matches(#(#argnames, )*)
            }

            /// Forbid this expectation from ever being called.
            #v fn never(&mut self) -> &mut Self {
                self.common.never();
                self
            }

            /// Create a new, default, [`Expectation`](struct.Expectation.html)
            #v fn new() -> Self {
                Self::default()
            }

            /// Expect this expectation to be called exactly once.  Shortcut for
            /// [`times(1)`](#method.times).
            #v fn once(&mut self) -> &mut Self {
                self.times(1)
            }

            /// Restrict the number of times that that this method may be called.
            ///
            /// The argument may be:
            /// * A fixed number: `.times(4)`
            /// * Various types of range:
            ///   - `.times(5..10)`
            ///   - `.times(..10)`
            ///   - `.times(5..)`
            ///   - `.times(5..=10)`
            ///   - `.times(..=10)`
            /// * The wildcard: `.times(..)`
            #v fn times<MockallR>(&mut self, __mockall_r: MockallR) -> &e='color:red'>mut Self
                where MockallR: Into<::mockall::TimesRange>
            {
                self.common.times(__mockall_r);
                self
            }

            #with_method

            /// Set a matching function for this Expectation.
            ///
            /// This is equivalent to calling [`with`](#method.with) with a
            /// function argument, like `with(predicate::function(f))`.
            #v fn withf<MockallF>(&mut self, __mockall_f: MockallF) -> &e='color:red'>mut Self
                where MockallF: #hrtb Fn(#(&#predty, )*)
                                -> bool + Send + 'static
            {
                self.common.withf(__mockall_f);
                self
            }

            /// Single-threaded version of [`withf`](#method.withf).
            /// Can be used when the argument type isn't `Send`.
            #v fn withf_st<MockallF>(&mut self, __mockall_f: MockallF) -> &tyle='color:red'>mut Self
                where MockallF: #hrtb Fn(#(&#predty, )*)
                                -> bool + 'static
            {
                self.common.withf_st(__mockall_f);
                self
            }
        ).to_tokens(tokens);
    }
}

/// Holds the moethods of the Expectations object that are common for all
/// Expectation types
struct CommonExpectationsMethods<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for CommonExpectationsMethods<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let v = &self.f.privmod_vis;
        quote!(
            /// A collection of [`Expectation`](struct.Expectations.html)
            /// objects.  Users will rarely if ever use this struct directly.
            #[doc(hidden)]
            #v struct Expectations #ig ( Vec<Expectation #tg>) #wc;

            impl #ig Expectations #tg #wc {
                /// Verify that all current expectations are satisfied and clear
                /// them.
                #v fn checkpoint(&mut self) -> std::vec::Drain<Expectation #tg>
                {
                    self.0.drain(..)
                }

                /// Create a new expectation for this method.
                #v fn expect(&mut self) -> &mut Expectation #tg
                {
                    self.0.push(Expectation::default());
                    let __mockall_l = self.0.len();
                    &mut self.0[__mockall_l - 1]
                }

                #v fn new() -> Self {
                    Self::default()
                }
            }
            impl #ig Default for Expectations #tg #wc
            {
                fn default() -> Self {
                    Expectations(Vec::new())
                }
            }
        ).to_tokens(tokens);
    }
}

/// The ExpectationGuard structure for static methods with no generic types
struct ExpectationGuardCommonMethods<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for ExpectationGuardCommonMethods<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        if !self.f.is_static {
            return;
        }

        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let (_, tg, _) = self.f.egenerics.split_for_impl();
        let keyid = gen_keyid(&self.f.egenerics);
        let expectations = if self.f.is_expectation_generic() {
            quote!(self.guard
                   .store
                   .get_mut(&::mockall::Key::new::#keyid())
                   .unwrap()
                   .downcast_mut::<Expectations #tg>()
                   .unwrap())
        } else {
            quote!(self.guard)
        };
        let hrtb = self.f.hrtb();
        let output = &self.f.output;
        let predty = &self.f.predty;
        let with_generics_idents = (0..self.f.predty.len())
            .map(|i| format_ident!("MockallMatcher{i}"))
            .collect::<Vec<_>>();
        let with_generics = with_generics_idents.iter()
            .zip(self.f.predty.iter())
            .map(|(id, mt)|
                quote!(#id#hrtb ::mockall::Predicate<#mt> + Send + 'static, )
            ).collect::<TokenStream>();
        let with_args = self.f.argnames.iter()
            .zip(with_generics_idents.iter())
            .map(|(argname, id)| quote!(#argname#id, ))
            .collect::<TokenStream>();
        let v = &self.f.privmod_vis;
        let with_method = if self.f.concretize {
            quote!()
        } else {
                quote!(
                /// Just like
                /// [`Expectation::with`](struct.Expectation.html#method.with)
                #v fn with<#with_generics> (&mut self#with_args)
                    -> &mut Expectation #tg
                {
                    #expectations.0[self.i].with(#(#argnames, )*)
                }
            )
        };
        quote!(
            /// Just like
            /// [`Expectation::in_sequence`](struct.Expectation.html#method.in_sequence)
            #v fn in_sequence(&mut self,
                __mockall_seq: &mut ::mockall::Sequence)
                -> &mut Expectation #tg
            {
                #expectations.0[self.i].in_sequence(__mockall_seq)
            }

            /// Just like
            /// [`Expectation::never`](struct.Expectation.html#method.never)
            #v fn never(&mut self) -> &mut Expectation #tg {
                #expectations.0[self.i].never()
            }

            /// Just like
            /// [`Expectation::once`](struct.Expectation.html#method.once)
            #v fn once(&mut self) -> &mut Expectation #tg {
                #expectations.0[self.i].once()
            }

            /// Just like
            /// [`Expectation::return_const`](struct.Expectation.html#method.return_const)
            #v fn return_const<MockallOutput>
            (&mut self, __mockall_c: MockallOutput)
                -> &mut Expectation #tg
                where MockallOutput: Clone + Into<#output> + Send + 'static
            {
                #expectations.0[self.i].return_const(__mockall_c)
            }

            /// Just like
            /// [`Expectation::return_const_st`](struct.Expectation.html#method.return_const_st)
            #v fn return_const_st<MockallOutput>
            (&mut self, __mockall_c: MockallOutput)
                -> &mut Expectation #tg
                where MockallOutput: Clone + Into<#output> + 'static
            {
                #expectations.0[self.i].return_const_st(__mockall_c)
            }

            /// Just like
            /// [`Expectation::returning`](struct.Expectation.html#method.returning)
            #v fn returning<MockallF>(&mut self, __mockall_f: MockallF)
                -> &mut Expectation #tg
                where MockallF: #hrtb FnMut(#(#argty, )*)
                    -> #output + Send + 'static
            {
                #expectations.0[self.i].returning(__mockall_f)
            }

            /// Just like
            /// [`Expectation::return_once`](struct.Expectation.html#method.return_once)
            #v fn return_once<MockallF>(&mut self, __mockall_f: MockallF)
                -> &mut Expectation #tg
                where MockallF: #hrtb FnOnce(#(#argty, )*)
                                -> #output + Send + 'static
            {
                #expectations.0[self.i].return_once(__mockall_f)
            }

            /// Just like
            /// [`Expectation::return_once_st`](struct.Expectation.html#method.return_once_st)
            #v fn return_once_st<MockallF>(&mut self, __mockall_f: MockallF)
                -> &mut Expectation #tg
                where MockallF: #hrtb FnOnce(#(#argty, )*)
                                -> #output + 'static
            {
                #expectations.0[self.i].return_once_st(__mockall_f)
            }


            /// Just like
            /// [`Expectation::returning_st`](struct.Expectation.html#method.returning_st)
            #v fn returning_st<MockallF>(&mut self, __mockall_f: MockallF)
                -> &mut Expectation #tg
                where MockallF: #hrtb FnMut(#(#argty, )*)
                                -> #output + 'static
            {
                #expectations.0[self.i].returning_st(__mockall_f)
            }

            /// Just like
            /// [`Expectation::times`](struct.Expectation.html#method.times)
            #v fn times<MockallR>(&mut self, __mockall_r: MockallR)
                -> &mut Expectation #tg
                where MockallR: Into<::mockall::TimesRange>
            {
                #expectations.0[self.i].times(__mockall_r)
            }

            #with_method

            /// Just like
            /// [`Expectation::withf`](struct.Expectation.html#method.withf)
            #v fn withf<MockallF>(&mut self, __mockall_f: MockallF)
                -> &mut Expectation #tg
                where MockallF: #hrtb Fn(#(&#predty, )*)
                                -> bool + Send + 'static
            {
                #expectations.0[self.i].withf(__mockall_f)
            }

            /// Just like
            /// [`Expectation::withf_st`](struct.Expectation.html#method.withf_st)
            #v fn withf_st<MockallF>(&mut self, __mockall_f: MockallF)
                -> &mut Expectation #tg
                where MockallF: #hrtb Fn(#(&#predty, )*)
                                -> bool + 'static
            {
                #expectations.0[self.i].withf_st(__mockall_f)
            }
        ).to_tokens(tokens);
    }
}

/// The ExpectationGuard structure for static methods with no generic types
struct ConcreteExpectationGuard<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for ConcreteExpectationGuard<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        if !self.f.is_static {
            return;
        }

        let common_methods = ExpectationGuardCommonMethods{f: self.f};
        let (_, tg, _) = self.f.egenerics.split_for_impl();
        let ltdef = LifetimeParam::new(
            Lifetime::new("'__mockall_lt", Span::call_site())
        );
        let mut e_generics = self.f.egenerics.clone();
        e_generics.lt_token.get_or_insert(<Token![<]>::default());
        e_generics.params.push(GenericParam::Lifetime(ltdef));
        e_generics.gt_token.get_or_insert(<Token![>]>::default());
        let (e_ig, e_tg, e_wc) = e_generics.split_for_impl();
        let (ei_ig, _, _) = e_generics.split_for_impl();
        let v = &self.f.privmod_vis;
        quote!(
            ::mockall::lazy_static! {
                #[doc(hidden)]
                #v static ref EXPECTATIONS:
                    ::std::sync::Mutex<Expectations #tg> =
                    ::std::sync::Mutex::new(Expectations::new());
            }
            /// Like an [`&Expectation`](struct.Expectation.html) but
            /// protected by a Mutex guard.  Useful for mocking static
            /// methods.  Forwards accesses to an `Expectation` object.
            // We must return the MutexGuard to the caller so he can
            // configure the expectation.  But we can't bundle both the
            // guard and the &Expectation into the same structure; the
            // borrow checker won't let us.  Instead we'll record the
            // expectation's position within the Expectations vector so we
            // can proxy its methods.
            //
            // ExpectationGuard is only defined for expectations that return
            // 'static return types.
            #v struct ExpectationGuard #e_ig #e_wc {
                guard: MutexGuard<'__mockall_lt, Expectations #tg>,
                i: usize
            }

            #[allow(clippy::unused_unit)]
            impl #ei_ig ExpectationGuard #e_tg #e_wc
            {
                // Should only be called from the mockall_derive generated
                // code
                #[doc(hidden)]
                #v fn new(mut __mockall_guard: MutexGuard<'__mockall_lt, Expectations #tg>)
                    -> Self
                {
                    __mockall_guard.expect(); // Drop the &Expectation
                    let __mockall_i = __mockall_guard.0.len() - 1;
                    ExpectationGuard{guard: __mockall_guard, i: __mockall_i}
                }

                #common_methods
            }
        ).to_tokens(tokens);
    }
}

/// The ExpectationGuard structure for static methods with generic types
struct GenericExpectationGuard<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for GenericExpectationGuard<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        if !self.f.is_static {
            return;
        }

        let common_methods = ExpectationGuardCommonMethods{f: self.f};
        let (_, tg, _) = self.f.egenerics.split_for_impl();
        let keyid = gen_keyid(&self.f.egenerics);
        let ltdef = LifetimeParam::new(
            Lifetime::new("'__mockall_lt", Span::call_site())
        );
        let mut egenerics = self.f.egenerics.clone();
        egenerics.lt_token.get_or_insert(<Token![<]>::default());
        egenerics.params.push(GenericParam::Lifetime(ltdef));
        egenerics.gt_token.get_or_insert(<Token![>]>::default());
        let (e_ig, e_tg, e_wc) = egenerics.split_for_impl();
        let fn_params = &self.f.fn_params;
        let tbf = tg.as_turbofish();
        let v = &self.f.privmod_vis;
        quote!(
            ::mockall::lazy_static! {
                #v static ref EXPECTATIONS:
                    ::std::sync::Mutex<GenericExpectations> =
                    ::std::sync::Mutex::new(GenericExpectations::new());
            }
            /// Like an [`&Expectation`](struct.Expectation.html) but
            /// protected by a Mutex guard.  Useful for mocking static
            /// methods.  Forwards accesses to an `Expectation` object.
            #v struct ExpectationGuard #e_ig #e_wc{
                guard: MutexGuard<'__mockall_lt, GenericExpectations>,
                i: usize,
                _phantom: ::std::marker::PhantomData<(#(#fn_params,)*)>,
            }

            #[allow(clippy::unused_unit)]
            impl #e_ig ExpectationGuard #e_tg #e_wc
            {
                // Should only be called from the mockall_derive generated
                // code
                #[doc(hidden)]
                #v fn new(mut __mockall_guard: MutexGuard<'__mockall_lt, GenericExpectations>)
                    -> Self
                {
                    let __mockall_ee: &mut Expectations #tg =
                        __mockall_guard.store.entry(
                            ::mockall::Key::new::#keyid()
                        ).or_insert_with(||
                            Box::new(Expectations #tbf ::new()))
                        .downcast_mut()
                        .unwrap();
                    __mockall_ee.expect();    // Drop the &Expectation
                    let __mockall_i = __mockall_ee.0.len() - 1;
                    ExpectationGuard{guard: __mockall_guard, i: __mockall_i,
                        _phantom: ::std::marker::PhantomData}
                }

                #common_methods
            }
        ).to_tokens(tokens);
    }
}

/// Generates Context, which manages the context for expectations of static
/// methods.
struct Context<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for Context<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        if !self.f.is_static {
            return;
        }

        let ltdef = LifetimeParam::new(
            Lifetime::new("'__mockall_lt", Span::call_site())
        );
        let mut egenerics = self.f.egenerics.clone();
        egenerics.lt_token.get_or_insert(<Token![<]>::default());
        egenerics.params.push(GenericParam::Lifetime(ltdef));
        egenerics.gt_token.get_or_insert(<Token![>]>::default());
        let (_, e_tg, _) = egenerics.split_for_impl();
        let (ty_ig, ty_tg, ty_wc) = self.f.type_generics.split_for_impl();
        let mut meth_generics = self.f.call_generics.clone();
        let ltdef = LifetimeParam::new(
            Lifetime::new("'__mockall_lt", Span::call_site())
        );
        meth_generics.params.push(GenericParam::Lifetime(ltdef));
        let (meth_ig, _meth_tg, meth_wc) = meth_generics.split_for_impl();
        let ctx_fn_params = self.f.struct_generics.type_params()
            .map(|tp| tp.ident.clone())
            .collect::<Punctuated::<Ident, Token![,]>>();
        let v = &self.f.privmod_vis;

        #[cfg(not(feature = "nightly_derive"))]
        let must_use = quote!(#[must_use =
                "Must set return value when not using the \"nightly\" feature"
            ]);
        #[cfg(feature = "nightly_derive")]
        let must_use = quote!();

        quote!(
            /// Manages the context for expectations of static methods.
            ///
            /// Expectations on this method will be validated and cleared when
            /// the `Context` object drops.  The `Context` object does *not*
            /// provide any form of synchronization, so multiple tests that set
            /// expectations on the same static method must provide their own.
            #[must_use = "Context only serves to create expectations" ]
            #v struct Context #ty_ig #ty_wc {
                // Prevent "unused type parameter" errors
                // Surprisingly, PhantomData<Fn(generics)> is Send even if
                // generics are not, unlike PhantomData<generics>
                _phantom: ::std::marker::PhantomData<
                    Box<dyn Fn(#ctx_fn_params) + Send>
                >
            }
            impl #ty_ig Context #ty_tg #ty_wc {
                /// Verify that all current expectations for this method are
                /// satisfied and clear them.
                #v fn checkpoint(&self) {
                    Self::do_checkpoint()
                }
                #[doc(hidden)]
                #v fn do_checkpoint() {
                    let __mockall_timeses = EXPECTATIONS
                        .lock()
                        .unwrap()
                        .checkpoint()
                        .collect::<Vec<_>>();
                }

                /// Create a new expectation for this method.
                #must_use
                #v fn expect #meth_ig ( &self,) -> ExpectationGuard #e_tg
                    #meth_wc
                {
                    ExpectationGuard::new(EXPECTATIONS.lock().unwrap())
                }
            }
            impl #ty_ig Default for Context #ty_tg #ty_wc {
                fn default() -> Self {
                    Context {_phantom: std::marker::PhantomData}
                }
            }
            impl #ty_ig Drop for Context #ty_tg #ty_wc {
                fn drop(&mut self) {
                    if ::std::thread::panicking() {
                        // Drain all expectations so other tests can run with a
                        // blank slate.  But ignore errors so we don't
                        // double-panic.
                        let _ = EXPECTATIONS
                            .lock()
                            .map(|mut g| g.checkpoint().collect::<Vec<_>>());
                    } else {
                        // Verify expectations are satisfied
                        Self::do_checkpoint();
                    }
                }
            }
        ).to_tokens(tokens);
    }
}

struct Matcher<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for Matcher<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let (ig, tg, wc) = self.f.cgenerics.split_for_impl();
        let argnames = &self.f.argnames;
        let braces = argnames.iter()
            .fold(String::new(), |mut acc, _argname| {
                if acc.is_empty() {
                    acc.push_str("{}");
                } else {
                    acc.push_str(", {}");
                }
                acc
            });
        let fn_params = &self.f.fn_params;
        let hrtb = self.f.hrtb();
        let indices = (0..argnames.len())
            .map(|i| {
                syn::Index::from(i)
            }).collect::<Vec<_>>();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let pred_matches = argnames.iter().enumerate()
            .map(|(i, argname)| {
                let idx = syn::Index::from(i);
                quote!(__mockall_pred.#idx.eval(#argname),)
            }).collect::<TokenStream>();
        let preds = if self.f.concretize {
            quote!(())
        } else {
            self.f.predty.iter()
            .map(|t| quote!(Box<dyn #hrtb ::mockall::Predicate<#t> + Send>,))
            .collect::<TokenStream>()
        };
        let predty = &self.f.predty;
        let refpredty = &self.f.refpredty;
        let predmatches_body = if self.f.concretize {
            quote!()
        } else {
            quote!(Matcher::Pred(__mockall_pred) => [#pred_matches].iter().all(|__mockall_x| *__mockall_x),)
        };
        let preddbg_body = if self.f.concretize {
            quote!()
        } else {
            quote!(
                Matcher::Pred(__mockall_p) => {
                    write!(__mockall_fmt, #braces,
                        #(__mockall_p.#indices,)*)
                }
            )
        };
        quote!(
            enum Matcher #ig #wc {
                Always,
                Func(Box<dyn #hrtb Fn(#( #refpredty, )*) -> bool + Send>),
                // Version of Matcher::Func for closures that aren't Send
                FuncSt(::mockall::Fragile<Box<dyn #hrtb Fn(#( #refpredty, )*) -> bool>>),
                Pred(Box<(#preds)>),
                // Prevent "unused type parameter" errors
                // Surprisingly, PhantomData<Fn(generics)> is Send even if
                // generics are not, unlike PhantomData<generics>
                _Phantom(Box<dyn Fn(#(#fn_params,)*) + Send>)
            }
            impl #ig Matcher #tg #wc {
                #[allow(clippy::ptr_arg)]
                fn matches #lg (&self#( #argnames: &#predty, )*) -> bool {
                    match self {
                        Matcher::Always => true,
                        Matcher::Func(__mockall_f) =>
                            __mockall_f(#(#argnames, )*),
                        Matcher::FuncSt(__mockall_f) =>
                            (__mockall_f.get())(#(#argnames, )*),
                        #predmatches_body
                        _ => unreachable!()
                    }
                }
            }

            impl #ig Default for Matcher #tg #wc {
                #[allow(unused_variables)]
                fn default() -> Self {
                    Matcher::Always
                }
            }

            impl #ig ::std::fmt::Display for Matcher #tg #wc {
                fn fmt(&self, __mockall_fmt: &mut ::std::fmt::Formatter<'_>)
                    -> ::std::fmt::Result
                {
                    match self {
                        Matcher::Always => write!(__mockall_fmt, "<anything>"),
                        Matcher::Func(_) => write!(__mockall_fmt, "<function>"),
                        Matcher::FuncSt(_) => write!(__mockall_fmt, "<single threaded function>"),
                        #preddbg_body
                        _ => unreachable!(),
                    }
                }
            }
        ).to_tokens(tokens);
    }
}

struct RefRfunc<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for RefRfunc<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let fn_params = &self.f.fn_params;
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let owned_output = &self.f.owned_output;

        #[cfg(not(feature = "nightly_derive"))]
        let default_err_msg =
            "Returning default values requires the \"nightly\" feature";
        #[cfg(feature = "nightly_derive")]
        let default_err_msg =
            "Can only return default values for types that impl std::Default";

        quote!(
            enum Rfunc #ig #wc {
                Default(Option<#owned_output>),
                Const(#owned_output),
                // Prevent "unused type parameter" errors Surprisingly,
                // PhantomData<Fn(generics)> is Send even if generics are not,
                // unlike PhantomData<generics>
                _Phantom(Mutex<Box<dyn Fn(#(#fn_params,)*) + Send>>)
            }

            impl #ig  Rfunc #tg #wc {
                fn call #lg (&self)
                    -> std::result::Result<&#owned_output, &'static str>
                {
                    match self {
                        Rfunc::Default(Some(ref __mockall_o)) => {
                            ::std::result::Result::Ok(__mockall_o)
                        },
                        Rfunc::Default(None) => {
                            Err(#default_err_msg)
                        },
                        Rfunc::Const(ref __mockall_o) => {
                            ::std::result::Result::Ok(__mockall_o)
                        },
                        Rfunc::_Phantom(_) => unreachable!()
                    }
                }
            }

            impl #ig std::default::Default for Rfunc #tg #wc
            {
                fn default() -> Self {
                    use ::mockall::ReturnDefault;
                    Rfunc::Default(::mockall::DefaultReturner::<#owned_output>
                                ::maybe_return_default())
                }
            }
        ).to_tokens(tokens);
    }
}

struct RefMutRfunc<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for RefMutRfunc<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let fn_params = &self.f.fn_params;
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let owned_output = &self.f.owned_output;
        let output = &self.f.output;

        #[cfg(not(feature = "nightly_derive"))]
        let default_err_msg =
            "Returning default values requires the \"nightly\" feature";
        #[cfg(feature = "nightly_derive")]
        let default_err_msg =
            "Can only return default values for types that impl std::Default";

        quote!(
            #[allow(clippy::unused_unit)]
            enum Rfunc #ig #wc {
                Default(Option<#owned_output>),
                Mut((Box<dyn FnMut(#(#argty, )*) -> #owned_output + Send + Sync>),
                    Option<#owned_output>),
                // Version of Rfunc::Mut for closures that aren't Send
                MutSt((::mockall::Fragile<
                           Box<dyn FnMut(#(#argty, )*) -> #owned_output >>
                       ), Option<#owned_output>
                ),
                Var(#owned_output),
                // Prevent "unused type parameter" errors Surprisingly,
                // PhantomData<Fn(generics)> is Send even if generics are not,
                // unlike PhantomData<generics>
                _Phantom(Mutex<Box<dyn Fn(#(#fn_params,)*) + Send>>)
            }

            impl #ig  Rfunc #tg #wc {
                fn call_mut #lg (&mut self#(#argnames#argty, )*)
                    -> std::result::Result<#output, &'static str>
                {
                    match self {
                        Rfunc::Default(Some(ref mut __mockall_o)) => {
                            ::std::result::Result::Ok(__mockall_o)
                        },
                        Rfunc::Default(None) => {
                            Err(#default_err_msg)
                        },
                        Rfunc::Mut(ref mut __mockall_f, ref mut __mockall_o) =>
                        {
                            *__mockall_o = Some(__mockall_f(#(#argnames, )*));
                            if let Some(ref mut __mockall_o2) = __mockall_o {
                                ::std::result::Result::Ok(__mockall_o2)
                            } else {
                                unreachable!()
                            }
                        },
                        Rfunc::MutSt(ref mut __mockall_f, ref mut __mockall_o)=>
                        {
                            *__mockall_o = Some((__mockall_f.get_mut())(
                                    #(#argnames, )*)
                            );
                            if let Some(ref mut __mockall_o2) = __mockall_o {
                                ::std::result::Result::Ok(__mockall_o2)
                            } else {
                                unreachable!()
                            }
                        },
                        Rfunc::Var(ref mut __mockall_o) => {
                            ::std::result::Result::Ok(__mockall_o)
                        },
                        Rfunc::_Phantom(_) => unreachable!()
                    }
                }
            }

            impl #ig std::default::Default for Rfunc #tg #wc
            {
                fn default() -> Self {
                    use ::mockall::ReturnDefault;
                    Rfunc::Default(::mockall::DefaultReturner::<#owned_output>
                                ::maybe_return_default())
                }
            }
        ).to_tokens(tokens);
    }
}

struct StaticRfunc<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for StaticRfunc<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let fn_params = &self.f.fn_params;
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let hrtb = self.f.hrtb();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let output = &self.f.output;
        quote!(
            #[allow(clippy::unused_unit)]
            enum Rfunc #ig #wc {
                Default,
                // Indicates that a `return_once` expectation has already
                // returned
                Expired,
                Mut(Box<dyn #hrtb FnMut(#(#argty, )*) -> #output + Send>),
                // Version of Rfunc::Mut for closures that aren't Send
                MutSt(::mockall::Fragile<
                    Box<dyn #hrtb FnMut(#(#argty, )*) -> #output >>
                ),
                Once(Box<dyn #hrtb FnOnce(#(#argty, )*) -> #output + Send>),
                // Version of Rfunc::Once for closure that aren't Send
                OnceSt(::mockall::Fragile<
                    Box<dyn #hrtb FnOnce(#(#argty, )*) -> #output>>
                ),
                // Prevent "unused type parameter" errors Surprisingly,
                // PhantomData<Fn(generics)> is Send even if generics are not,
                // unlike PhantomData<generics>
                _Phantom(Box<dyn Fn(#(#fn_params,)*) + Send>)
            }

            impl #ig  Rfunc #tg #wc {
                fn call_mut #lg (&mut self#( #argnames#argty, )* )
                    -> std::result::Result<#output, &'static str>
                {
                    match self {
                        Rfunc::Default => {
                            use ::mockall::ReturnDefault;
                            ::mockall::DefaultReturner::<#output>
                                ::return_default()
                        },
                        Rfunc::Expired => {
                            Err("called twice, but it returns by move")
                        },
                        Rfunc::Mut(__mockall_f) => {
                            ::std::result::Result::Ok(__mockall_f( #(#argnames, )* ))
                        },
                        Rfunc::MutSt(__mockall_f) => {
                            ::std::result::Result::Ok((__mockall_f.get_mut())(#(#argnames,)*))
                        },
                        Rfunc::Once(_) => {
                            if let Rfunc::Once(mut __mockall_f) =
                                mem::replace(self, Rfunc::Expired) {
                                ::std::result::Result::Ok(__mockall_f( #(#argnames, )* ))
                            } else {
                                unreachable!()
                            }
                        },
                        Rfunc::OnceSt(_) => {
                            if let Rfunc::OnceSt(mut __mockall_f) =
                                mem::replace(self, Rfunc::Expired) {
                                ::std::result::Result::Ok((__mockall_f.into_inner())(#(#argnames,)*))
                            } else {
                                unreachable!()
                            }
                        },
                        Rfunc::_Phantom(_) => unreachable!()
                    }
                }
            }

            impl #ig std::default::Default for Rfunc #tg #wc
            {
                fn default() -> Self {
                    Rfunc::Default
                }
            }
        ).to_tokens(tokens);
    }
}

/// An expectation type for functions that take a &self and return a reference
struct RefExpectation<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for RefExpectation<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let common_methods = CommonExpectationMethods{f: self.f};
        let desc = self.f.desc();
        let funcname = self.f.funcname();
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();

        let (_, common_tg, _) = self.f.cgenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let output = &self.f.output;
        let owned_output = &self.f.owned_output;
        let v = &self.f.privmod_vis;
        quote!(
            /// Expectation type for methods taking a `&self` argument and
            /// returning immutable references.  This is the type returned by
            /// the `expect_*` methods.
            #v struct Expectation #ig #wc {
                common: Common #common_tg,
                rfunc: Rfunc #tg,
            }

            #[allow(clippy::unused_unit)]
            impl #ig Expectation #tg #wc {
                /// Call this [`Expectation`] as if it were the real method.
                #v fn call #lg (&self#(#argnames#argty, )*) -> #output
                {
                    use ::mockall::{ViaDebug, ViaNothing};
                    self.common.call(&#desc);
                    self.rfunc.call().unwrap_or_else(|m| {
                        let desc = std::format!(
                            "{}"self.common.matcher.lock().unwrap());
                        panic!("{}: Expectation({}) {}"#funcname, desc,
                            m);
                    })
                }

                /// Return a reference to a constant value from the `Expectation`
                #v fn return_const(&mut self, __mockall_o: #owned_output)
                    -> &mut Self
                {
                    self.rfunc = Rfunc::Const(__mockall_o);
                    self
                }

                #common_methods
            }
            impl #ig Default for Expectation #tg #wc
            {
                fn default() -> Self {
                    Expectation {
                        common: Common::default(),
                        rfunc: Rfunc::default()
                    }
                }
            }
        ).to_tokens(tokens);
    }
}

/// For methods that take &mut self and return a reference
struct RefMutExpectation<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for RefMutExpectation<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let common_methods = CommonExpectationMethods{f: self.f};
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let desc = self.f.desc();
        let funcname = self.f.funcname();
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let (_, common_tg, _) = self.f.cgenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let owned_output = &self.f.owned_output;
        let v = &self.f.privmod_vis;
        quote!(
            /// Expectation type for methods taking a `&mut self` argument and
            /// returning references.  This is the type returned by the
            /// `expect_*` methods.
            #v struct Expectation #ig #wc {
                common: Common #common_tg,
                rfunc: Rfunc #tg
            }

            #[allow(clippy::unused_unit)]
            impl #ig Expectation #tg #wc {
                /// Simulating calling the real method for this expectation
                #v fn call_mut #lg (&mut self#(#argnames#argty, )*)
                    -> &mut #owned_output
                {
                    use ::mockall::{ViaDebug, ViaNothing};
                    self.common.call(&#desc);
                    let desc = std::format!(
                        "{}"self.common.matcher.lock().unwrap());
                    self.rfunc.call_mut(#(#argnames, )*).unwrap_or_else(|m| {
                            panic!("{}: Expectation({}) {}"#funcname, desc,
                                   m);
                    })
                }

                /// Convenience method that can be used to supply a return value
                /// for a `Expectation`.  The value will be returned by mutable
                /// reference.
                #v fn return_var(&mut self, __mockall_o: #owned_output) -> &yle='color:red'>mut Self
                {
                    self.rfunc = Rfunc::Var(__mockall_o);
                    self
                }

                /// Supply a closure that the `Expectation` will use to create its
                /// return value.  The return value will be returned by mutable
                /// reference.
                #v fn returning<MockallF>(&mut self, __mockall_f: MockallF)
                    -> &mut Self
                    where MockallF: FnMut(#(#argty, )*) -> #owned_output + Send + Sync + 'static
                {
                    self.rfunc = Rfunc::Mut(Box::new(__mockall_f), None);
                    self
                }

                /// Single-threaded version of [`returning`](#method.returning).
                /// Can be used when the argument or return type isn't `Send`.
                #v fn returning_st<MockallF>(&mut self, __mockall_f: MockallF)
                    -> &mut Self
                    where MockallF: FnMut(#(#argty, )*) -> #owned_output + 'static
                {
                    self.rfunc = Rfunc::MutSt(
                        ::mockall::Fragile::new(Box::new(__mockall_f)), None);
                    self
                }

                #common_methods
            }
            impl #ig Default for Expectation #tg #wc
            {
                fn default() -> Self {
                    Expectation {
                        common: Common::default(),
                        rfunc: Rfunc::default()
                    }
                }
            }
        ).to_tokens(tokens);
    }
}

/// An expectation type for functions return a `'static` value
struct StaticExpectation<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for StaticExpectation<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let common_methods = CommonExpectationMethods{f: self.f};
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let desc = self.f.desc();
        let hrtb = self.f.hrtb();
        let funcname = self.f.funcname();
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let (_, common_tg, _) = self.f.cgenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let output = &self.f.output;
        let v = &self.f.privmod_vis;

        quote!(
            /// Expectation type for methods that return a `'static` type.
            /// This is the type returned by the `expect_*` methods.
            #v struct Expectation #ig #wc {
                common: Common #common_tg,
                rfunc: Mutex<Rfunc #tg>,
            }

            #[allow(clippy::unused_unit)]
            impl #ig Expectation #tg #wc {
                /// Call this [`Expectation`] as if it were the real method.
                #[doc(hidden)]
                #v fn call #lg (&self#(#argnames#argty, )* ) -> #output
                {
                    use ::mockall::{ViaDebug, ViaNothing};
                    self.common.call(&#desc);
                    self.rfunc.lock().unwrap().call_mut(#(#argnames, )*)
                        .unwrap_or_else(|message| {
                            let desc = std::format!(
                                "{}"self.common.matcher.lock().unwrap());
                            panic!("{}: Expectation({}) {}"#funcname, desc,
                                   message);
                        })
                }

                /// Return a constant value from the `Expectation`
                ///
                /// The output type must be `Clone`.  The compiler can't always
                /// infer the proper type to use with this method; you will
                /// usually need to specify it explicitly.  i.e.
                /// `return_const(42i32)` instead of `return_const(42)`.
                // We must use Into<#output> instead of #output because where
                // clauses don't accept equality constraints.
                // https://github.com/rust-lang/rust/issues/20041
                #[allow(unused_variables)]
                #v fn return_const<MockallOutput>(&mut self,
                    __mockall_c: MockallOutput)
                    -> &mut Self
                    where MockallOutput: Clone + Into<#output> + Send + 'static
                {
                    self.returning(move |#(#argnames, )*| __mockall_c.clone().into())
                }

                /// Single-threaded version of
                /// [`return_const`](#method.return_const).  This is useful for
                /// return types that are not `Send`.
                ///
                /// The output type must be `Clone`.  The compiler can't always
                /// infer the proper type to use with this method; you will
                /// usually need to specify it explicitly.  i.e.
                /// `return_const(42i32)` instead of `return_const(42)`.
                ///
                /// It is a runtime error to call the mock method from a
                /// different thread than the one that originally called this
                /// method.
                // We must use Into<#output> instead of #output because where
                // clauses don't accept equality constraints.
                // https://github.com/rust-lang/rust/issues/20041
                #[allow(unused_variables)]
                #v fn return_const_st<MockallOutput>(&mut self,
                    __mockall_c: MockallOutput)
                    -> &mut Self
                    where MockallOutput: Clone + Into<#output> + 'static
                {
                    self.returning_st(move |#(#argnames, )*| __mockall_c.clone().into())
                }

                /// Supply an `FnOnce` closure that will provide the return
                /// value for this Expectation.  This is useful for return types
                /// that aren't `Clone`.  It will be an error to call this
                /// method multiple times.
                #v fn return_once<MockallF>(&mut self, __mockall_f: MockallF)
                    -> &mut Self
                    where MockallF: #hrtb FnOnce(#(#argty, )*)
                                    -> #output + Send + 'static
                {
                    {
                        let mut __mockall_guard = self.rfunc.lock().unwrap();
                        *__mockall_guard.deref_mut() =
                            Rfunc::Once(Box::new(__mockall_f));
                    }
                    self
                }

                /// Single-threaded version of
                /// [`return_once`](#method.return_once).  This is useful for
                /// return types that are neither `Send` nor `Clone`.
                ///
                /// It is a runtime error to call the mock method from a
                /// different thread than the one that originally called this
                /// method.  It is also a runtime error to call the method more
                /// than once.
                #v fn return_once_st<MockallF>(&mut self, __mockall_f:
                                                  MockallF) -> &mut Self
                    where MockallF: #hrtb FnOnce(#(#argty, )*)
                                    -> #output + 'static
                {
                    {
                        let mut __mockall_guard = self.rfunc.lock().unwrap();
                        *__mockall_guard.deref_mut() = Rfunc::OnceSt(
                            ::mockall::Fragile::new(Box::new(__mockall_f)));
                    }
                    self
                }

                /// Supply a closure that will provide the return value for this
                /// `Expectation`.  The method's arguments are passed to the
                /// closure by value.
                #v fn returning<MockallF>(&mut self, __mockall_f: MockallF)
                    -> &mut Self
                    where MockallF: #hrtb FnMut(#(#argty, )*)
                                    -> #output + Send + 'static
                {
                    {
                        let mut __mockall_guard = self.rfunc.lock().unwrap();
                        *__mockall_guard.deref_mut() =
                            Rfunc::Mut(Box::new(__mockall_f));
                    }
                    self
                }

                /// Single-threaded version of [`returning`](#method.returning).
                /// Can be used when the argument or return type isn't `Send`.
                ///
                /// It is a runtime error to call the mock method from a
                /// different thread than the one that originally called this
                /// method.
                #v fn returning_st<MockallF>(&mut self, __mockall_f: MockallF)
                    -> &mut Self
                    where MockallF: #hrtb FnMut(#(#argty, )*)
                                    -> #output + 'static
                {
                    {
                        let mut __mockall_guard = self.rfunc.lock().unwrap();
                        *__mockall_guard.deref_mut() = Rfunc::MutSt(
                            ::mockall::Fragile::new(Box::new(__mockall_f)));
                    }
                    self
                }

                #common_methods
            }
            impl #ig Default for Expectation #tg #wc
            {
                fn default() -> Self {
                    Expectation {
                        common: Common::default(),
                        rfunc: Mutex::new(Rfunc::default())
                    }
                }
            }
        ).to_tokens(tokens);
    }
}

/// An collection of RefExpectation's
struct RefExpectations<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for RefExpectations<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let common_methods = CommonExpectationsMethods{f: self.f};
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let output = &self.f.output;
        let predexprs = &self.f.predexprs;
        let v = &self.f.privmod_vis;
        quote!(
            #common_methods
            impl #ig Expectations #tg #wc {
                /// Simulate calling the real method.  Every current expectation
                /// will be checked in FIFO order and the first one with
                /// matching arguments will be used.
                #v fn call #lg (&self#(#argnames#argty, )* )
                    -> Option<#output>
                {
                    self.0.iter()
                        .find(|__mockall_e|
                              __mockall_e.matches(#(#predexprs, )*) &&
                              (!__mockall_e.is_done() || self.0.len() == 1))
                        .map(move |__mockall_e|
                             __mockall_e.call(#(#argnames),*)
                        )
                }

            }
        ).to_tokens(tokens);
    }
}

/// An collection of RefMutExpectation's
struct RefMutExpectations<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for RefMutExpectations<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let common_methods = CommonExpectationsMethods{f: self.f};
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let output = &self.f.output;
        let predexprs = &self.f.predexprs;
        let v = &self.f.privmod_vis;
        quote!(
            #common_methods
            impl #ig Expectations #tg #wc {
                /// Simulate calling the real method.  Every current expectation
                /// will be checked in FIFO order and the first one with
                /// matching arguments will be used.
                #v fn call_mut #lg (&mut self#(#argnames#argty, )* )
                    -> Option<#output>
                {
                    let __mockall_n = self.0.len();
                    self.0.iter_mut()
                        .find(|__mockall_e|
                              __mockall_e.matches(#(#predexprs, )*) &&
                              (!__mockall_e.is_done() || __mockall_n == 1))
                        .map(move |__mockall_e|
                             __mockall_e.call_mut(#(#argnames, )*)
                        )
                }

            }
        ).to_tokens(tokens);
    }
}

/// An collection of Expectation's for methods returning static values
struct StaticExpectations<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for StaticExpectations<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let common_methods = CommonExpectationsMethods{f: self.f};
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let lg = lifetimes_to_generics(&self.f.alifetimes);
        let output = &self.f.output;
        let predexprs = &self.f.predexprs;
        let v = &self.f.privmod_vis;
        quote!(
            #common_methods
            impl #ig Expectations #tg #wc {
                /// Simulate calling the real method.  Every current expectation
                /// will be checked in FIFO order and the first one with
                /// matching arguments will be used.
                #v fn call #lg (&self#(#argnames#argty, )* )
                    -> Option<#output>
                {
                    self.0.iter()
                        .find(|__mockall_e|
                              __mockall_e.matches(#(#predexprs, )*) &&
                              (!__mockall_e.is_done() || self.0.len() == 1))
                        .map(move |__mockall_e|
                             __mockall_e.call(#(#argnames, )*)
                        )
                }

            }
        ).to_tokens(tokens);
    }
}

struct GenericExpectations<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for GenericExpectations<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        if ! self.f.is_expectation_generic() {
            return;
        }
        if ! self.f.is_static() && ! self.f.is_method_generic() {
            return;
        }

        let ge = StaticGenericExpectations{f: self.f};
        let v = &self.f.privmod_vis;
        quote!(
            /// A collection of [`Expectation`](struct.Expectations.html)
            /// objects for a generic method.  Users will rarely if ever use
            /// this struct directly.
            #[doc(hidden)]
            #[derive(Default)]
            #v struct GenericExpectations{
                store: std::collections::hash_map::HashMap<::mockall::Key,
                               Box<dyn ::mockall::AnyExpectations>>
            }
            impl GenericExpectations {
                /// Verify that all current expectations are satisfied and clear
                /// them.  This applies to all sets of generic parameters!
                #v fn checkpoint(&mut self) ->
                    std::collections::hash_map::Drain<::mockall::Key,
                               Box<dyn ::mockall::AnyExpectations>>
                {
                    self.store.drain()
                }

                #v fn new() -> Self {
                    Self::default()
                }
            }
            #ge
        ).to_tokens(tokens);
    }
}

/// Generates methods for GenericExpectations for methods returning static
/// values
struct StaticGenericExpectations<'a> {
    f: &'a MockFunction
}

impl<'a> ToTokens for StaticGenericExpectations<'a> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let argnames = &self.f.argnames;
        let argty = &self.f.argty;
        let (ig, tg, wc) = self.f.egenerics.split_for_impl();
        let keyid = gen_keyid(&self.f.egenerics);
        let mut any_wc = wc.cloned();
        if self.f.return_ref || self.f.return_refmut {
            // Add Senc + Sync, required for downcast, since Expectation
            // stores an Option<#owned_output>
            send_syncify(&mut any_wc, self.f.owned_output.clone());
        }
        let tbf = tg.as_turbofish();
        let output = &self.f.output;
        let v = &self.f.privmod_vis;
        let (call, get, self_, downcast) = if self.f.return_refmut {
            (format_ident!("call_mut"),
             format_ident!("get_mut"),
             quote!(&mut self),
             format_ident!("downcast_mut"))
        } else {
            (format_ident!("call"),
             format_ident!("get"),
             quote!(&self),
             format_ident!("downcast_ref"))
        };
        quote!(
            impl #ig ::mockall::AnyExpectations for Expectations #tg #any_wc {}
            impl GenericExpectations {
                /// Simulating calling the real method.
                #v fn #call #ig (#self_, #(#argnames: #argty, )* )
                    -> Option<#output> #wc
                {
                    self.store.#get(&::mockall::Key::new::#keyid())
                        .map(|__mockall_e| {
                            __mockall_e.#downcast::<Expectations #tg>()
                            .unwrap()
                            .#call(#(#argnames, )*)
                        }).flatten()
                }

                /// Create a new Expectation.
                #v fn expect #ig (&mut self) -> &mut Expectation #tg #any_wc
                {
                    self.store.entry(::mockall::Key::new::#keyid())
                        .or_insert_with(|| Box::new(Expectations #tbf::new()))
                        .downcast_mut::<Expectations #tg>()
                        .unwrap()
                        .expect()
                }
            }
        ).to_tokens(tokens)
    }
}


Messung V0.5 in Prozent
C=89 H=98 G=93

¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.50Angebot  ¤

*Eine klare Vorstellung vom Zielzustand






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

letze Version des Elbe Quellennavigators


Jenseits des Üblichen ....
    

Besucher

Besucher

Statistik
#Sources=141584
#Domains=752002