1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
mod r#trait;
mod r#type;
use better_any::TidAble;
pub use r#trait::Trait;
pub use r#type::Type;
use proc_macro2::TokenStream;
use super::{context::Context, passed_data::PassedData};
/// This indicates that some type can be turned into tokens that assert something.
/// Be aware that this only relies on rust's type checking, the code that is generated
/// is never actually meant to be executed. The generation functions in three distinct "Stages".
/// See below for more information on that.
///
///
/// The type implementing this must also be [`TidAble`], which is similar to [`Any`](std::any::Any)
/// but allows for non-'static lifetimes. The easiest way to implement it is to use the derive macro (`#[derive(Tid)]`)
///
/// # Idents
/// There is a need to ensure that there are no ident collisions among the generated code.
/// For that purpose in each stage there is a context provided, which contains some [`IdentGenerator`](crate::ident_generator::IdentGenerator).
/// Other than Idents passed into the methods by either `Self` or any parameters, use Idents generates by the IdentGenerator
/// exclusively to avoid any collisions.
///
/// # Generation "Stages"
/// ## Stage 1: Generatable
/// These tokens are generated for each type that implemets this trait once. This is the perfect place to put
/// tokens that are needed as "Setup" for any asserts.
/// ## Stage 2: Template
/// These tokens are generated for each unique instance of `Self`. You should put any tokens that should be unique
/// for each instance in here.
/// ## Stage 3: Assert
/// These tokens are generated for each unique Assert, which represent some type that is tested against `Self`.
/// No generation is actually happening until at least one assert is created for `Self`.
///
/// # Passed Data
/// There may be a need to pass data, for example generated idents, between stages. For that purpose
/// this trait provides a way to do so. See [`PassedData`](crate::passed_data::PassedData) for more information.
pub trait Generatable<'a>
where
Self: TidAble<'a>,
{
/// The type of any data passed from the `Generatable` stage to proceeding stages.
type GeneratableData: 'a;
/// The type of any data passed from the `Template` stage to proceeding stages.
type TemplateData: 'a;
/// The type with can be checked against this template.
type Assert: 'a;
/// This is the method the `Generatable` stage is composed of. Should return Tokens (if any) generated by this stage,
/// plus optionally any data passed to preceding stages.
fn generatable(context: &mut Context) -> PassedData<Self::GeneratableData>
where
Self: Sized;
/// This is the method the `Template` stage is composed of. Should return Tokens (if any) generated by this stage,
/// plus optionally any data passed to preceding stages.
fn template(
&self,
context: &mut Context,
passed: &Self::GeneratableData,
) -> PassedData<Self::TemplateData>;
/// This is the method the `Assert` stage is composed of. Should return Tokens generated by this stage.
fn assert(
&self,
_context: &mut Context,
_passed: (&Self::GeneratableData, &Self::TemplateData),
_to_assert: &Self::Assert,
) -> Option<TokenStream>;
}