use {
crate::{constraints::Constraint, context::Context},
syn::spanned::Spanned,
};
fn check_program_prerequisite(context: &Context, program: &str) -> Result<(), syn::Error> {
let has_system_program = context
.accounts
.iter()
.any(|acc| acc.ty.ident == "Program" && acc.inner_ty == program);
if !has_system_program {
return Err(syn::Error::new(
context.item_struct.span(),
format!("One constraint requires including the `Program<{program}>` account."),
));
}
Ok(())
}
pub fn cross_checks(context: &Context) -> Result<(), syn::Error> {
for acc in &context.accounts {
if acc
.constraints
.0
.iter()
.any(|c| matches!(c, Constraint::Init(_) | Constraint::InitIfNeeded(_)))
{
check_program_prerequisite(context, "System")?;
if acc.inner_ty == "Mint" || acc.inner_ty == "TokenAccount" {
check_program_prerequisite(context, "TokenProgram")?;
if acc
.constraints
.0
.iter()
.any(|c| matches!(c, Constraint::AssociatedToken(_)))
{
check_program_prerequisite(context, "AtaTokenProgram")?;
}
}
}
}
Ok(())
}