anchor_syn/parser/program/
mod.rs1use {
2 crate::{parser::docs, Program},
3 syn::{
4 parse::{Error as ParseError, Result as ParseResult},
5 spanned::Spanned,
6 },
7};
8
9mod instructions;
10
11pub fn parse(program_mod: syn::ItemMod) -> ParseResult<Program> {
12 let docs = docs::parse(&program_mod.attrs);
13 let (ixs, fallback_fn) = instructions::parse(&program_mod)?;
14 Ok(Program {
15 ixs,
16 name: program_mod.ident.clone(),
17 docs,
18 program_mod,
19 fallback_fn,
20 })
21}
22
23fn ctx_accounts_ident(path_ty: &syn::PatType) -> ParseResult<proc_macro2::Ident> {
24 let p = match &*path_ty.ty {
25 syn::Type::Path(p) => &p.path,
26 _ => return Err(ParseError::new(path_ty.ty.span(), "invalid type")),
27 };
28 let segment = p
29 .segments
30 .first()
31 .ok_or_else(|| ParseError::new(p.segments.span(), "expected generic arguments here"))?;
32
33 let generic_args = match &segment.arguments {
34 syn::PathArguments::AngleBracketed(args) => args,
35 _ => return Err(ParseError::new(path_ty.span(), "missing accounts context")),
36 };
37 let generic_ty = generic_args
38 .args
39 .iter()
40 .filter_map(|arg| match arg {
41 syn::GenericArgument::Type(ty) => Some(ty),
42 _ => None,
43 })
44 .next()
45 .ok_or_else(|| ParseError::new(generic_args.span(), "expected Accounts type"))?;
46
47 let path = match generic_ty {
48 syn::Type::Path(ty_path) => &ty_path.path,
49 _ => {
50 return Err(ParseError::new(
51 generic_ty.span(),
52 "expected Accounts struct type",
53 ))
54 }
55 };
56 Ok(path.segments[0].ident.clone())
57}