Skip to content

Commit 3633222

Browse files
Make the new IDL features explicit (otter-sec#2582)
1 parent 6002493 commit 3633222

5 files changed

Lines changed: 32 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ The minor version will be incremented upon a breaking change and the patch versi
3131
### Breaking
3232

3333
- syn: `idl` feature has been replaced with `idl-build`, `idl-parse` and `idl-types` features ([#2011](https://github.com/coral-xyz/anchor/pull/2011)).
34+
- syn: IDL `parse` method now returns `Result<Idl>` instead of `Result<Option<Idl>>` ([#2582](https://github.com/coral-xyz/anchor/pull/2582)).
3435

3536
## [0.28.0] - 2023-06-09
3637

cli/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2292,7 +2292,6 @@ fn generate_idl_parse(
22922292
safety_checks: bool,
22932293
) -> Result<Idl> {
22942294
anchor_syn::idl::parse::file::parse(path, version, seeds_feature, no_docs, safety_checks)
2295-
.and_then(|maybe_idl| maybe_idl.ok_or_else(|| anyhow!("Failed to parse IDL")))
22962295
}
22972296

22982297
/// Generate IDL with the build method.

lang/syn/Cargo.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@ rust-version = "1.60"
99
edition = "2021"
1010

1111
[features]
12-
allow-missing-optionals = []
13-
init-if-needed = []
14-
idl-build = []
15-
idl-parse = []
16-
idl-types = []
17-
hash = []
1812
default = []
13+
allow-missing-optionals = []
1914
anchor-debug = []
20-
seeds = []
2115
event-cpi = []
16+
hash = []
17+
idl-build = ["idl-parse", "idl-types"]
18+
idl-parse = ["idl-types"]
19+
idl-types = []
20+
init-if-needed = []
21+
seeds = []
2222

2323
[dependencies]
2424
anyhow = "1"
2525
bs58 = "0.5"
2626
heck = "0.3"
27-
proc-macro2 = { version = "1", features=["span-locations"]}
27+
proc-macro2 = { version = "1", features = ["span-locations"] }
2828
quote = "1"
2929
serde = { version = "1", features = ["derive"] }
3030
serde_json = "1"

lang/syn/src/idl/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#[cfg(feature = "idl-build")]
22
pub mod build;
3-
#[cfg(any(feature = "idl-parse", feature = "idl-build"))]
3+
4+
#[cfg(feature = "idl-parse")]
45
pub mod parse;
5-
#[cfg(any(feature = "idl-types", feature = "idl-build", feature = "idl-parse"))]
6+
7+
#[cfg(feature = "idl-types")]
68
pub mod types;

lang/syn/src/idl/parse/file.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::parser::context::CrateContext;
33
use crate::parser::{self, accounts, docs, error, program};
44
use crate::Ty;
55
use crate::{AccountField, AccountsStruct};
6+
use anyhow::anyhow;
67
use anyhow::Result;
78
use heck::MixedCase;
89
use quote::ToTokens;
@@ -19,28 +20,25 @@ const DERIVE_NAME: &str = "Accounts";
1920
// TODO: share this with `anchor_lang` crate.
2021
const ERROR_CODE_OFFSET: u32 = 6000;
2122

22-
// Parse an entire interface file.
23+
/// Parse an entire interface file.
2324
pub fn parse(
2425
path: impl AsRef<Path>,
2526
version: String,
2627
seeds_feature: bool,
2728
no_docs: bool,
2829
safety_checks: bool,
29-
) -> Result<Option<Idl>> {
30+
) -> Result<Idl> {
3031
let ctx = CrateContext::parse(path)?;
3132
if safety_checks {
3233
ctx.safety_checks()?;
3334
}
3435

35-
let program_mod = match parse_program_mod(&ctx) {
36-
None => return Ok(None),
37-
Some(m) => m,
38-
};
39-
let mut p = program::parse(program_mod)?;
36+
let program_mod = parse_program_mod(&ctx)?;
37+
let mut program = program::parse(program_mod)?;
4038

4139
if no_docs {
42-
p.docs = None;
43-
for ix in &mut p.ixs {
40+
program.docs = None;
41+
for ix in &mut program.ixs {
4442
ix.docs = None;
4543
}
4644
}
@@ -59,7 +57,7 @@ pub fn parse(
5957
.collect::<Vec<IdlErrorCode>>()
6058
});
6159

62-
let instructions = p
60+
let instructions = program
6361
.ixs
6462
.iter()
6563
.map(|ix| {
@@ -157,10 +155,10 @@ pub fn parse(
157155
.map(|c: &&syn::ItemConst| to_idl_const(c))
158156
.collect::<Vec<IdlConst>>();
159157

160-
Ok(Some(Idl {
158+
Ok(Idl {
161159
version,
162-
name: p.name.to_string(),
163-
docs: p.docs.clone(),
160+
name: program.name.to_string(),
161+
docs: program.docs.clone(),
164162
instructions,
165163
types,
166164
accounts,
@@ -172,11 +170,11 @@ pub fn parse(
172170
errors: error_codes,
173171
metadata: None,
174172
constants,
175-
}))
173+
})
176174
}
177175

178-
// Parse the main program mod.
179-
fn parse_program_mod(ctx: &CrateContext) -> Option<syn::ItemMod> {
176+
/// Parse the main program mod.
177+
fn parse_program_mod(ctx: &CrateContext) -> Result<syn::ItemMod> {
180178
let root = ctx.root_module();
181179
let mods = root
182180
.items()
@@ -195,10 +193,12 @@ fn parse_program_mod(ctx: &CrateContext) -> Option<syn::ItemMod> {
195193
_ => None,
196194
})
197195
.collect::<Vec<_>>();
198-
if mods.len() != 1 {
199-
return None;
196+
197+
match mods.len() {
198+
0 => Err(anyhow!("Program module not found")),
199+
1 => Ok(mods[0].clone()),
200+
_ => Err(anyhow!("Multiple program modules are not allowed")),
200201
}
201-
Some(mods[0].clone())
202202
}
203203

204204
fn parse_error_enum(ctx: &CrateContext) -> Option<syn::ItemEnum> {

0 commit comments

Comments
 (0)