Skip to content

Commit

Permalink
idl instruction: add create account macro attr
Browse files Browse the repository at this point in the history
  • Loading branch information
ngundotra committed Oct 31, 2022
1 parent a5bd471 commit 097150b
Show file tree
Hide file tree
Showing 16 changed files with 437 additions and 78 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"version": "",
"name": "",
"instructions": [
{
"name": "Create",
"accounts": [
{
"name": "from",
"isMut": true,
"isSigner": true,
"desc": "Payer of the transaction"
},
{
"name": "to",
"isMut": true,
"isSigner": false,
"desc": "The deterministically defined 'state' account being created via `create_account_with_seed`"
},
{
"name": "base",
"isMut": false,
"isSigner": false,
"desc": "The program-derived-address signing off on the account creation. Seeds = &[] + bump seed."
},
{
"name": "systemProgram",
"isMut": false,
"isSigner": false,
"desc": "The system program"
},
{
"name": "program",
"isMut": false,
"isSigner": false,
"desc": "The program whose state is being constructed"
}
],
"args": [
{
"name": "dataLen",
"type": "u64"
}
],
"discriminant": {
"type": "u8",
"value": 0
}
}
],
"metadata": {
"origin": "shank"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[derive(ShankInstruction)]
pub enum Instruction {
#[idl_instruction(Create)]
Create,
}
17 changes: 17 additions & 0 deletions shank-idl/tests/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,23 @@ fn instruction_from_single_file_with_multiple_args() {
assert_eq!(idl, expected_idl);
}

#[test]
fn instruction_from_single_file_with_idl_instructions() {
let file = fixtures_dir()
.join("single_file")
.join("create_idl_instructions.rs");
let idl = parse_file(&file, &ParseIdlConfig::optional_program_address())
.expect("Parsing should not fail")
.expect("File contains IDL");

let expected_idl: Idl = serde_json::from_str(include_str!(
"./fixtures/instructions/single_file/create_idl_instructions.json"
))
.unwrap();

assert_eq!(idl, expected_idl);
}

#[test]
fn instruction_from_single_file_with_optional_account() {
let file = fixtures_dir()
Expand Down
2 changes: 1 addition & 1 deletion shank-macro-impl/src/converters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ use syn::Error as ParseError;
pub fn parse_error_into<T: Into<ParseError>>(parse_err: T) -> Error {
let parse_err: ParseError = parse_err.into();
Error::new(parse_err)
.context(format!("[ParseError] Run `cargo build` or `cargo check` in the program crate root for more details."))
.context("[ParseError] Run `cargo build` or `cargo check` in the program crate root for more details.".to_string())
}
2 changes: 1 addition & 1 deletion shank-macro-impl/src/custom_type/custom_type_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ impl DetectCustomTypeConfig {
saw_include = self.include_derives.contains(&derive);
}
}
return saw_include;
saw_include
}
}
7 changes: 3 additions & 4 deletions shank-macro-impl/src/error/program_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl ProgramError {
|x| x.clone(),
);
Self::parse_account_error_args(
&nested,
nested,
&ident,
variant_ident,
variant_discriminant,
Expand Down Expand Up @@ -101,8 +101,7 @@ impl TryFrom<&ParsedEnum> for ProgramErrors {
.collect::<ParseResult<Vec<Option<ProgramError>>>>()?;
let program_errors = program_errors
.into_iter()
.filter(Option::is_some)
.map(Option::unwrap)
.flatten()
.collect::<Vec<ProgramError>>();

Ok(ProgramErrors(program_errors))
Expand Down Expand Up @@ -130,7 +129,7 @@ impl ProgramError {
"shank expects no more than one #[error]s per variant",
))
} else {
Ok(program_errors.to_owned().first().map(|x| x.clone()))
Ok(program_errors.first().cloned())
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions shank-macro-impl/src/error/this_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ pub fn extract_this_errors<'a>(
.iter()
.map(ProgramErrors::try_from)
.collect::<ParseResult<Vec<ProgramErrors>>>()?
.into_iter()
.map(|x| x.0)
.flatten()
.into_iter().flat_map(|x| x.0)
.collect::<Vec<ProgramError>>();
Ok(program_errors)
}
53 changes: 22 additions & 31 deletions shank-macro-impl/src/instruction/account_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::convert::TryFrom;

use proc_macro2::Span;
use syn::{
punctuated::Punctuated, Attribute, Error as ParseError, Ident, Lit, Meta,
MetaList, MetaNameValue, NestedMeta, Result as ParseResult, Token,
punctuated::Punctuated, Attribute, Error as ParseError, Ident, Lit, Meta, MetaList,
MetaNameValue, NestedMeta, Result as ParseResult, Token,
};

const IX_ACCOUNT: &str = "account";
Expand Down Expand Up @@ -34,9 +34,7 @@ impl InstructionAccount {
}
}

pub fn from_account_attr(
attr: &Attribute,
) -> ParseResult<InstructionAccount> {
pub fn from_account_attr(attr: &Attribute) -> ParseResult<InstructionAccount> {
let meta = &attr.parse_meta()?;

match meta {
Expand All @@ -45,7 +43,7 @@ impl InstructionAccount {
|| Ident::new("attr_ident", Span::call_site()),
|x| x.clone(),
);
Self::parse_account_attr_args(ident, &nested)
Self::parse_account_attr_args(ident, nested)
}
Meta::Path(_) | Meta::NameValue(_) => Err(ParseError::new_spanned(
attr,
Expand Down Expand Up @@ -73,9 +71,7 @@ impl InstructionAccount {
let mut optional = false;

for meta in nested {
if let Some((ident, name, value)) =
string_assign_from_nested_meta(meta)?
{
if let Some((ident, name, value)) = string_assign_from_nested_meta(meta)? {
// name/desc
match name.as_str() {
"desc" | "description" => desc = Some(value),
Expand All @@ -86,14 +82,14 @@ impl InstructionAccount {
))
}
"name" => account_name = Some(value),
_ => return Err(ParseError::new_spanned(
ident,
"Only desc/description or name can be assigned strings",
)),
_ => {
return Err(ParseError::new_spanned(
ident,
"Only desc/description or name can be assigned strings",
))
}
};
} else if let Some((ident, name)) =
identifier_from_nested_meta(meta)
{
} else if let Some((ident, name)) = identifier_from_nested_meta(meta) {
// signer, writable, optional ...
match name.as_str() {
"signer" | "sign" | "sig" | "s" => signer = true,
Expand Down Expand Up @@ -133,9 +129,7 @@ impl InstructionAccount {
desc,
optional,
}),
None => {
Err(ParseError::new_spanned(nested, "Missing account name"))
}
None => Err(ParseError::new_spanned(nested, "Missing account name")),
}
}
}
Expand All @@ -145,7 +139,7 @@ impl TryFrom<&[Attribute]> for InstructionAccounts {

fn try_from(attrs: &[Attribute]) -> ParseResult<Self> {
let accounts = attrs
.into_iter()
.iter()
.filter_map(InstructionAccount::is_account_attr)
.map(InstructionAccount::from_account_attr)
.collect::<ParseResult<Vec<InstructionAccount>>>()?;
Expand Down Expand Up @@ -176,14 +170,15 @@ fn string_assign_from_nested_meta(
nested_meta: &NestedMeta,
) -> ParseResult<Option<(Ident, String, String)>> {
match nested_meta {
NestedMeta::Meta(Meta::NameValue(MetaNameValue {
path, lit, ..
})) => {
NestedMeta::Meta(Meta::NameValue(MetaNameValue { path, lit, .. })) => {
let ident = path.get_ident();
if let Some(ident) = ident {
let token = match lit {
let token = match lit {
Lit::Str(lit) => Ok(lit.value()),
_ => Err(ParseError::new_spanned(ident, "#[account(desc)] arg needs to be assigning to a string")),
_ => Err(ParseError::new_spanned(
ident,
"#[account(desc)] arg needs to be assigning to a string",
)),
}?;
Ok(Some((ident.clone(), ident.to_string(), token)))
} else {
Expand All @@ -194,14 +189,10 @@ fn string_assign_from_nested_meta(
}
}

fn identifier_from_nested_meta(
nested_meta: &NestedMeta,
) -> Option<(Ident, String)> {
pub fn identifier_from_nested_meta(nested_meta: &NestedMeta) -> Option<(Ident, String)> {
match nested_meta {
NestedMeta::Meta(meta) => match meta {
Meta::Path(_) => {
meta.path().get_ident().map(|x| (x.clone(), x.to_string()))
}
Meta::Path(_) => meta.path().get_ident().map(|x| (x.clone(), x.to_string())),
// ignore named values and lists
_ => None,
},
Expand Down
8 changes: 4 additions & 4 deletions shank-macro-impl/src/instruction/account_attrs_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl From<&InstructionAccount> for InstructionAccountWithoutIdent {
writable: *writable,
signer: *signer,
desc: desc.clone(),
optional: optional.clone(),
optional: *optional,
}
}
}
Expand Down Expand Up @@ -320,10 +320,10 @@ fn account_multiple_attrs() {
InstructionAccountWithoutIdent {
index: None,
name: name.clone(),
writable: writable.clone(),
signer: signer.clone(),
writable: *writable,
signer: *signer,
desc: desc.clone(),
optional: optional.clone(),
optional: *optional,
}
},
)
Expand Down
Loading

0 comments on commit 097150b

Please sign in to comment.