Browse Source

lang: Fix parsing for bytes literals in the IDL (#2261)

* lang: Fix parsing of some constants

* Fix lint + changelog
Jean Marchand 2 years ago
parent
commit
b107cbe94f
4 changed files with 60 additions and 5 deletions
  1. 1 0
      CHANGELOG.md
  2. 36 5
      lang/syn/src/idl/file.rs
  3. 4 0
      tests/misc/programs/misc/src/lib.rs
  4. 19 0
      tests/misc/tests/misc/misc.ts

+ 1 - 0
CHANGELOG.md

@@ -31,6 +31,7 @@ The minor version will be incremented upon a breaking change and the patch versi
 
 ### Fixes
 
+* lang: Fix parsing for bytes literals in the IDL. ([#2261](https://github.com/coral-xyz/anchor/pull/2261))
 * lang: Fix IDL `seed` generation for byte string literals. ([#2125](https://github.com/coral-xyz/anchor/pull/2125))
 * ts: Update seeds inference to allow nested user defined structs within the seeds ([#2198](https://github.com/coral-xyz/anchor/pull/2198))
 

+ 36 - 5
lang/syn/src/idl/file.rs

@@ -8,6 +8,10 @@ use heck::MixedCase;
 use quote::ToTokens;
 use std::collections::{HashMap, HashSet};
 use std::path::Path;
+use syn::{
+    Expr, ExprLit, ItemConst,
+    Lit::{Byte, ByteStr},
+};
 
 const DERIVE_NAME: &str = "Accounts";
 // TODO: share this with `anchor_lang` crate.
@@ -281,11 +285,7 @@ pub fn parse(
 
     let constants = parse_consts(&ctx)
         .iter()
-        .map(|c: &&syn::ItemConst| IdlConst {
-            name: c.ident.to_string(),
-            ty: c.ty.to_token_stream().to_string().parse().unwrap(),
-            value: c.expr.to_token_stream().to_string().parse().unwrap(),
-        })
+        .map(|c: &&syn::ItemConst| to_idl_const(c))
         .collect::<Vec<IdlConst>>();
 
     Ok(Some(Idl {
@@ -615,6 +615,37 @@ fn to_idl_type(ctx: &CrateContext, ty: &syn::Type) -> IdlType {
     tts_string.parse().unwrap()
 }
 
+// TODO parse other issues
+fn to_idl_const(item: &ItemConst) -> IdlConst {
+    let name = item.ident.to_string();
+
+    if let Expr::Lit(ExprLit { lit, .. }) = &*item.expr {
+        match lit {
+            ByteStr(lit_byte_str) => {
+                return IdlConst {
+                    name,
+                    ty: IdlType::Bytes,
+                    value: format!("{:?}", lit_byte_str.value()),
+                }
+            }
+            Byte(lit_byte) => {
+                return IdlConst {
+                    name,
+                    ty: IdlType::U8,
+                    value: lit_byte.value().to_string(),
+                }
+            }
+            _ => (),
+        }
+    }
+
+    IdlConst {
+        name,
+        ty: item.ty.to_token_stream().to_string().parse().unwrap(),
+        value: item.expr.to_token_stream().to_string().parse().unwrap(),
+    }
+}
+
 fn idl_accounts(
     ctx: &CrateContext,
     accounts: &AccountsStruct,

+ 4 - 0
tests/misc/programs/misc/src/lib.rs

@@ -17,6 +17,10 @@ declare_id!("3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh");
 pub const BASE: u128 = 1_000_000;
 #[constant]
 pub const DECIMALS: u8 = 6;
+#[constant]
+pub const BYTES_STR: &[u8] = b"test";
+#[constant]
+pub const BYTE_STR: u8 = b't';
 pub const NO_IDL: u16 = 55;
 
 #[program]

+ 19 - 0
tests/misc/tests/misc/misc.ts

@@ -1105,6 +1105,25 @@ describe("misc", () => {
     );
   });
 
+  it("Should include BYTES_STR const in IDL", async () => {
+    assert.isDefined(
+      miscIdl.constants.find(
+        (c) =>
+          c.name === "BYTES_STR" &&
+          c.type === "bytes" &&
+          c.value === "[116, 101, 115, 116]"
+      )
+    );
+  });
+
+  it("Should include BYTE_STR const in IDL", async () => {
+    assert.isDefined(
+      miscIdl.constants.find(
+        (c) => c.name === "BYTE_STR" && c.type === "u8" && c.value === "116"
+      )
+    );
+  });
+
   it("Should not include NO_IDL const in IDL", async () => {
     assert.isUndefined(miscIdl.constants.find((c) => c.name === "NO_IDL"));
   });