typed-quote 0.1.1

A fully typed quote!() alternative for both proc-macro and proc-macro2
Documentation
use crate::{Either, Span};

use super::*;

#[cfg(any(feature = "proc-macro", feature = "proc-macro2"))]
macro_rules! either {
    ($v:expr, |$var:pat_param|$out:expr) => {
        match $v {
            Either::A($var) => $out,
            Either::B($var) => $out,
        }
    };
    ($v:expr, $f:expr) => {
        either!($v, |v| $f(v))
    };
}

macro_rules! either_map {
    ($v:expr, |$var:pat_param|$out:expr) => {
        match $v {
            Either::A($var) => Either::A($out),
            Either::B($var) => Either::B($out),
        }
    };
    ($v:expr, $f:expr) => {
        either_map!($v, |v| $f(v))
    };
}

impl<A: MaybeSpan, B: MaybeSpan> sealed::MaybeSpan for Either<A, B> {}
impl<A: MaybeSpan, B: MaybeSpan> MaybeSpan for Either<A, B> {
    #[cfg(feature = "proc-macro")]
    fn into_span_or_call_site(self) -> proc_macro::Span {
        either!(self, MaybeSpan::into_span_or_call_site)
    }
    #[cfg(feature = "proc-macro")]
    fn make_punct(self, punct: proc_macro::Punct) -> proc_macro::Punct {
        either!(self, |v| v.make_punct(punct))
    }
    #[cfg(feature = "proc-macro")]
    fn make_group(self, g: proc_macro::Group) -> proc_macro::Group {
        either!(self, |v| v.make_group(g))
    }
    #[cfg(feature = "proc-macro")]
    fn make_literal(self, literal: proc_macro::Literal) -> proc_macro::Literal {
        either!(self, |v| v.make_literal(literal))
    }

    #[cfg(feature = "proc-macro2")]
    fn into_span2_or_call_site(self) -> proc_macro2::Span {
        either!(self, MaybeSpan::into_span2_or_call_site)
    }
    #[cfg(feature = "proc-macro2")]
    fn make_punct2(self, punct: proc_macro2::Punct) -> proc_macro2::Punct {
        either!(self, |v| v.make_punct2(punct))
    }
    #[cfg(feature = "proc-macro2")]
    fn make_group2(self, g: proc_macro2::Group) -> proc_macro2::Group {
        either!(self, |v| v.make_group2(g))
    }
    #[cfg(feature = "proc-macro2")]
    fn make_literal2(self, literal: proc_macro2::Literal) -> proc_macro2::Literal {
        either!(self, |v| v.make_literal2(literal))
    }

    type Span = Either<A::Span, B::Span>;
    fn try_into_span(self) -> Option<Self::Span> {
        match self {
            Either::A(this) => this.try_into_span().map(Either::A),
            Either::B(this) => this.try_into_span().map(Either::B),
        }
    }

    type WithDefaultSpan<S: Span> = Either<A::WithDefaultSpan<S>, B::WithDefaultSpan<S>>;
    fn with_default_span<S: Span>(self, span: S) -> Self::WithDefaultSpan<S> {
        either_map!(self, |v| v.with_default_span(span))
    }

    type WithReplacedSpan<S: Span> = Either<A::WithReplacedSpan<S>, B::WithReplacedSpan<S>>;
    fn with_replaced_span<S: Span>(self, span: S) -> Self::WithReplacedSpan<S> {
        either_map!(self, |v| v.with_replaced_span(span))
    }
}

#[cfg(any(feature = "proc-macro", feature = "proc-macro2"))]
const _: () = {
    use crate::replace_span_of::ReplaceSpanOf;

    impl<A: ReplaceSpanOf<T>, B: ReplaceSpanOf<T>, T: IntoTokens + WithSpan> ReplaceSpanOf<T>
        for Either<A, B>
    {
        type ReplaceSpanOf = Either<A::ReplaceSpanOf, B::ReplaceSpanOf>;

        fn replace_span_of(self, t: T) -> Self::ReplaceSpanOf {
            either_map!(self, |v| v.replace_span_of(t))
        }
    }
};

impl<A: Span, B: Span> sealed::Span for Either<A, B> {}
impl<A: Span, B: Span> Span for Either<A, B> {}

impl<A: IntoTokenTree, B: IntoTokenTree> sealed::IntoTokenTree for Either<A, B> {}
impl<A: IntoTokenTree, B: IntoTokenTree> IntoTokenTree for Either<A, B> {
    crate::impl_into_token_tree!(|self| either!(self, IntoST::into_st));
}

impl<A: ToTokenTree, B: ToTokenTree> sealed::ToTokenTree for Either<A, B> {}
impl<A: ToTokenTree, B: ToTokenTree> ToTokenTree for Either<A, B> {
    crate::impl_to_token_tree!(|self| either!(self, IntoST::into_st));
}

impl<A: IntoTokens, B: IntoTokens> sealed::IntoTokens for Either<A, B> {}
impl<A: IntoTokens, B: IntoTokens> IntoTokens for Either<A, B> {
    crate::impl_into_tokens!(
        |self, ts| either!(self, |v| () = (v, ts).into_st()),
        either!(self, IntoST::into_st),
    );
}

impl<A: ToTokens, B: ToTokens> sealed::ToTokens for Either<A, B> {}
impl<A: ToTokens, B: ToTokens> ToTokens for Either<A, B> {
    crate::impl_to_tokens!(
        |self, ts| either!(self, |v| () = (v, ts).into_st()),
        either!(self, IntoST::into_st),
    );
}

impl<A: WithSpan, B: WithSpan> sealed::WithSpan for Either<A, B> {}
impl<A: WithSpan, B: WithSpan> WithSpan for Either<A, B> {
    type WithDefaultSpan<S: Span> = Either<A::WithDefaultSpan<S>, B::WithDefaultSpan<S>>;

    fn with_default_span<S: Span>(self, span: S) -> Self::WithDefaultSpan<S> {
        either_map!(self, |v| v.with_default_span(span))
    }

    type WithReplacedSpan<S: Span> = Either<A::WithReplacedSpan<S>, B::WithReplacedSpan<S>>;

    fn with_replaced_span<S: Span>(self, span: S) -> Self::WithReplacedSpan<S> {
        either_map!(self, |v| v.with_replaced_span(span))
    }
}

impl<A: RefWithSpan, B: RefWithSpan> sealed::RefWithSpan for Either<A, B> {}
impl<A: RefWithSpan, B: RefWithSpan> RefWithSpan for Either<A, B> {
    type RefWithDefaultSpan<'a, S: Span>
        = Either<A::RefWithDefaultSpan<'a, S>, B::RefWithDefaultSpan<'a, S>>
    where
        Self: 'a;

    fn ref_with_default_span<S: Span>(&self, span: S) -> Self::RefWithDefaultSpan<'_, S> {
        either_map!(self, |v| v.ref_with_default_span(span))
    }

    type RefWithReplacedSpan<'a, S: Span>
        = Either<A::RefWithReplacedSpan<'a, S>, B::RefWithReplacedSpan<'a, S>>
    where
        Self: 'a;

    fn ref_with_replaced_span<S: Span>(&self, span: S) -> Self::RefWithReplacedSpan<'_, S> {
        either_map!(self, |v| v.ref_with_replaced_span(span))
    }
}