Skip to content

Commit 04b079c

Browse files
committed
lang: Handle invalid camel case ident more gracefully
1 parent 219023e commit 04b079c

File tree

4 files changed

+42
-16
lines changed

4 files changed

+42
-16
lines changed

lang/syn/src/codegen/program/common.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::IxArg;
2+
use anyhow::Result;
23
use heck::CamelCase;
34
use quote::quote;
45

@@ -23,11 +24,11 @@ pub fn gen_discriminator(namespace: &str, name: impl ToString) -> proc_macro2::T
2324
format!("&{discriminator:?}").parse().unwrap()
2425
}
2526

26-
pub fn generate_ix_variant(name: &str, args: &[IxArg]) -> proc_macro2::TokenStream {
27+
pub fn generate_ix_variant(name: &str, args: &[IxArg]) -> Result<proc_macro2::TokenStream> {
2728
let ix_arg_names: Vec<&syn::Ident> = args.iter().map(|arg| &arg.name).collect();
28-
let ix_name_camel = generate_ix_variant_name(name);
29+
let ix_name_camel = generate_ix_variant_name(name)?;
2930

30-
if args.is_empty() {
31+
let variant = if args.is_empty() {
3132
quote! {
3233
#ix_name_camel
3334
}
@@ -37,10 +38,10 @@ pub fn generate_ix_variant(name: &str, args: &[IxArg]) -> proc_macro2::TokenStre
3738
#(#ix_arg_names),*
3839
}
3940
}
40-
}
41+
};
42+
Ok(variant)
4143
}
4244

43-
pub fn generate_ix_variant_name(name: &str) -> proc_macro2::TokenStream {
44-
let n = name.to_camel_case();
45-
n.parse().unwrap()
45+
pub fn generate_ix_variant_name(name: &str) -> Result<syn::Ident> {
46+
Ok(syn::parse_str(&name.to_camel_case())?)
4647
}

lang/syn/src/codegen/program/cpi.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,21 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
1313
let cpi_method = {
1414
let name = &ix.raw_method.sig.ident;
1515
let name_str = name.to_string();
16-
let ix_variant = generate_ix_variant(&name_str, &ix.args);
16+
let ix_variant = match generate_ix_variant(&name_str, &ix.args) {
17+
Ok(v) => v,
18+
Err(e) => {
19+
let err = e.to_string();
20+
return quote! { compile_error!(concat!("error generating ix variant: `", #err, "`")) };
21+
}
22+
};
1723
let method_name = &ix.ident;
1824
let args: Vec<&syn::PatType> = ix.args.iter().map(|arg| &arg.raw_arg).collect();
19-
let discriminator = {
20-
let name = generate_ix_variant_name(&name_str);
21-
quote! { <instruction::#name as anchor_lang::Discriminator>::DISCRIMINATOR }
25+
let discriminator = match generate_ix_variant_name(&name_str) {
26+
Ok(name) => quote! { <instruction::#name as anchor_lang::Discriminator>::DISCRIMINATOR },
27+
Err(e) => {
28+
let err = e.to_string();
29+
return quote! { compile_error!(concat!("error generating ix variant name: `", #err, "`")) };
30+
}
2231
};
2332
let ret_type = &ix.returns.ty.to_token_stream();
2433
let ix_cfgs = &ix.cfgs;

lang/syn/src/codegen/program/handlers.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,21 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
9999
let ix_arg_names: Vec<&syn::Ident> = ix.args.iter().map(|arg| &arg.name).collect();
100100
let ix_method_name = &ix.raw_method.sig.ident;
101101
let ix_method_name_str = ix_method_name.to_string();
102-
let ix_name = generate_ix_variant_name(&ix_method_name_str);
103-
let variant_arm = generate_ix_variant(&ix_method_name_str, &ix.args);
102+
let ix_name = match generate_ix_variant_name(&ix_method_name_str) {
103+
Ok(name) => quote! { <instruction::#name as anchor_lang::Discriminator>::DISCRIMINATOR },
104+
Err(e) => {
105+
let err = e.to_string();
106+
return quote! { compile_error!(concat!("error generating ix variant name: `", #err, "`")) };
107+
}
108+
};
109+
let variant_arm = match generate_ix_variant(&ix_method_name_str, &ix.args) {
110+
Ok(v) => v,
111+
Err(e) => {
112+
let err = e.to_string();
113+
return quote! { compile_error!(concat!("error generating ix variant arm: `", #err, "`")) };
114+
}
115+
};
116+
104117
let ix_name_log = format!("Instruction: {ix_name}");
105118
let anchor = &ix.anchor_ident;
106119
let ret_type = &ix.returns.ty.to_token_stream();

lang/syn/src/codegen/program/instruction.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::codegen::program::common::*;
22
use crate::parser;
33
use crate::Program;
44
use heck::CamelCase;
5-
use quote::quote;
5+
use quote::{quote, quote_spanned};
66

77
pub fn generate(program: &Program) -> proc_macro2::TokenStream {
88
let variants: Vec<proc_macro2::TokenStream> = program
@@ -11,8 +11,11 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
1111
.map(|ix| {
1212
let name = &ix.raw_method.sig.ident.to_string();
1313
let ix_cfgs = &ix.cfgs;
14-
let ix_name_camel =
15-
proc_macro2::Ident::new(&name.to_camel_case(), ix.raw_method.sig.ident.span());
14+
let Ok(ix_name_camel) = syn::parse_str::<syn::Ident>(&name.to_camel_case()) else {
15+
return quote_spanned! { ix.raw_method.sig.ident.span()=>
16+
compile_error!("failed to parse ix method name after conversion to camelCase");
17+
};
18+
};
1619
let raw_args: Vec<proc_macro2::TokenStream> = ix
1720
.args
1821
.iter()

0 commit comments

Comments
 (0)