From cad868a052152de9c338caa06300340c096d7f58 Mon Sep 17 00:00:00 2001 From: acheron <98934430+acheroncrypto@users.noreply.github.com> Date: Sat, 29 Jul 2023 23:49:17 +0200 Subject: [PATCH] Make the new IDL features explicit (#2582) --- CHANGELOG.md | 1 + cli/src/lib.rs | 1 - lang/syn/Cargo.toml | 16 +++++++------- lang/syn/src/idl/mod.rs | 6 ++++-- lang/syn/src/idl/parse/file.rs | 38 +++++++++++++++++----------------- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7db9defdf8..cc1e16b572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ The minor version will be incremented upon a breaking change and the patch versi ### Breaking - syn: `idl` feature has been replaced with `idl-build`, `idl-parse` and `idl-types` features ([#2011](https://github.com/coral-xyz/anchor/pull/2011)). +- syn: IDL `parse` method now returns `Result` instead of `Result>` ([#2582](https://github.com/coral-xyz/anchor/pull/2582)). ## [0.28.0] - 2023-06-09 diff --git a/cli/src/lib.rs b/cli/src/lib.rs index c529de27be..51883583f8 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -2292,7 +2292,6 @@ fn generate_idl_parse( safety_checks: bool, ) -> Result { anchor_syn::idl::parse::file::parse(path, version, seeds_feature, no_docs, safety_checks) - .and_then(|maybe_idl| maybe_idl.ok_or_else(|| anyhow!("Failed to parse IDL"))) } /// Generate IDL with the build method. diff --git a/lang/syn/Cargo.toml b/lang/syn/Cargo.toml index 7c281d67f7..6fe638c4c3 100644 --- a/lang/syn/Cargo.toml +++ b/lang/syn/Cargo.toml @@ -9,22 +9,22 @@ rust-version = "1.60" edition = "2021" [features] -allow-missing-optionals = [] -init-if-needed = [] -idl-build = [] -idl-parse = [] -idl-types = [] -hash = [] default = [] +allow-missing-optionals = [] anchor-debug = [] -seeds = [] event-cpi = [] +hash = [] +idl-build = ["idl-parse", "idl-types"] +idl-parse = ["idl-types"] +idl-types = [] +init-if-needed = [] +seeds = [] [dependencies] anyhow = "1" bs58 = "0.5" heck = "0.3" -proc-macro2 = { version = "1", features=["span-locations"]} +proc-macro2 = { version = "1", features = ["span-locations"] } quote = "1" serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/lang/syn/src/idl/mod.rs b/lang/syn/src/idl/mod.rs index dce34bb5b0..3cd27cc4f8 100644 --- a/lang/syn/src/idl/mod.rs +++ b/lang/syn/src/idl/mod.rs @@ -1,6 +1,8 @@ #[cfg(feature = "idl-build")] pub mod build; -#[cfg(any(feature = "idl-parse", feature = "idl-build"))] + +#[cfg(feature = "idl-parse")] pub mod parse; -#[cfg(any(feature = "idl-types", feature = "idl-build", feature = "idl-parse"))] + +#[cfg(feature = "idl-types")] pub mod types; diff --git a/lang/syn/src/idl/parse/file.rs b/lang/syn/src/idl/parse/file.rs index f874b37df8..3a2b331762 100644 --- a/lang/syn/src/idl/parse/file.rs +++ b/lang/syn/src/idl/parse/file.rs @@ -3,6 +3,7 @@ use crate::parser::context::CrateContext; use crate::parser::{self, accounts, docs, error, program}; use crate::Ty; use crate::{AccountField, AccountsStruct}; +use anyhow::anyhow; use anyhow::Result; use heck::MixedCase; use quote::ToTokens; @@ -19,28 +20,25 @@ const DERIVE_NAME: &str = "Accounts"; // TODO: share this with `anchor_lang` crate. const ERROR_CODE_OFFSET: u32 = 6000; -// Parse an entire interface file. +/// Parse an entire interface file. pub fn parse( path: impl AsRef, version: String, seeds_feature: bool, no_docs: bool, safety_checks: bool, -) -> Result> { +) -> Result { let ctx = CrateContext::parse(path)?; if safety_checks { ctx.safety_checks()?; } - let program_mod = match parse_program_mod(&ctx) { - None => return Ok(None), - Some(m) => m, - }; - let mut p = program::parse(program_mod)?; + let program_mod = parse_program_mod(&ctx)?; + let mut program = program::parse(program_mod)?; if no_docs { - p.docs = None; - for ix in &mut p.ixs { + program.docs = None; + for ix in &mut program.ixs { ix.docs = None; } } @@ -59,7 +57,7 @@ pub fn parse( .collect::>() }); - let instructions = p + let instructions = program .ixs .iter() .map(|ix| { @@ -157,10 +155,10 @@ pub fn parse( .map(|c: &&syn::ItemConst| to_idl_const(c)) .collect::>(); - Ok(Some(Idl { + Ok(Idl { version, - name: p.name.to_string(), - docs: p.docs.clone(), + name: program.name.to_string(), + docs: program.docs.clone(), instructions, types, accounts, @@ -172,11 +170,11 @@ pub fn parse( errors: error_codes, metadata: None, constants, - })) + }) } -// Parse the main program mod. -fn parse_program_mod(ctx: &CrateContext) -> Option { +/// Parse the main program mod. +fn parse_program_mod(ctx: &CrateContext) -> Result { let root = ctx.root_module(); let mods = root .items() @@ -195,10 +193,12 @@ fn parse_program_mod(ctx: &CrateContext) -> Option { _ => None, }) .collect::>(); - if mods.len() != 1 { - return None; + + match mods.len() { + 0 => Err(anyhow!("Program module not found")), + 1 => Ok(mods[0].clone()), + _ => Err(anyhow!("Multiple program modules are not allowed")), } - Some(mods[0].clone()) } fn parse_error_enum(ctx: &CrateContext) -> Option {