When I try to run the function:
parse_nested_meta on this structure:
#[TestMacro]
pub struct TestStruct {
#[button(
field_one = "test",
field_two = "field 2",
field_three = "field 3",
field_four = "very long field 4",
field_five = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat"
)]
pub my_element: u32,
}
I am getting the following error:
Got error while parsing meta: Error("expected ,")
Full code
```rust
use syn::DeriveInput;
use quote::quote;
pub fn generate(input: DeriveInput) -> proc_macro2::TokenStream {
if let syn::Data::Struct(s) = &input.data {
let mut ret = quote! {};
for field in &s.fields {
for attr in &field.attrs {
if attr.path().is_ident("button") {
attr.parse_nested_meta(|meta| {
let path_name = meta.path.get_ident().unwrap().to_string();
println!("Path name: {path_name}");
ret.extend(quote! {
println!("Path: {}", #path_name);
});
println!("NEXT");
Ok(())
}).expect("Got error while parsing meta");
}
}
}
quote! {
fn random_func() {
#ret
}
}
} else {
panic!("TestMacro is only available for struct");
}
}
#[cfg(test)]
mod test {
use super::generate;
use prettyplease::unparse;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{parse_quote, DeriveInput, File, Item, ItemMod};
#[test]
fn test_generation() {
let input: DeriveInput = parse_quote! {
#[TestMacro]
pub struct TestStruct {
#[button(
field_one = "test",
field_two = "field 2",
field_three = "field 3",
field_four = "very long field 4",
field_five = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat"
)]
pub my_element: u32,
}
};
let result: TokenStream = generate(input);
let wrapped_code = quote! {
mod dummy {
#result
}
};
// Convert the TokenStream to a syntax tree and then format it
let syntax_tree: ItemMod =
syn::parse2(wrapped_code).expect("Failed to parse TokenStream as ItemMod");
let file = File {
shebang: None,
attrs: Vec::new(),
items: vec![Item::Mod(syntax_tree)],
};
let formatted_code = unparse(&file);
// Print the formatted code
println!("{}", formatted_code);
// Panic to keep the output visible
panic!();
}
}
```
Cargo.toml
```toml
[package]
name = "telegram-button-maccro"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]
syn = { version = "2.0", features = ["full", "extra-traits"] }
quote = "1.0"
proc-macro2 = "1.0"
[dev-dependencies]
prettyplease = "0.2"
```
cargo test
```log
Compiling telegram-button-maccro v0.1.0 (/home/nicolas/Documents/projects2/poc/telegram-button-maccro)
Finished test [unoptimized + debuginfo] target(s) in 0.48s
Running unittests src/lib.rs (target/debug/deps/telegram_button_maccro-b1f06e26b47677b2)
running 1 test
test generate::test::test_generation ... FAILED
failures:
---- generate::test::test_generation stdout ----
Path name: field_one
NEXT
thread 'generate::test::test_generation' panicked at src/generate.rs:19:24:
Got error while parsing meta: Error("expected `,`")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
generate::test::test_generation
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
error: test failed, to rerun pass `--lib`
```
EDIT: After looking at #1426 I realized that I needed to actually extract the values:
Generate function fixed
```rust
pub fn generate(input: DeriveInput) -> proc_macro2::TokenStream {
if let syn::Data::Struct(s) = &input.data {
let mut ret = quote! {};
for field in &s.fields {
for attr in &field.attrs {
if attr.path().is_ident("button") {
attr.parse_nested_meta(|meta| {
let path_name = meta.path.get_ident().unwrap().to_string();
println!("Path name: {path_name}");
let value = meta.value()?;
let s: LitStr = value.parse()?;
let val = s.value();
ret.extend(quote! {
println!("Path: {} with val {}", #path_name, #val);
});
println!("NEXT");
Ok(())
}).expect("Got error while parsing meta");
}
}
}
quote! {
fn random_func() {
#ret
}
}
} else {
panic!("TestMacro is only available for struct");
}
}
```
When we are using parse_nested_meta we actually must parse all of the "sub-meta" also otherwise we get an error.
Is it possible to have a macro or something that allow us to "ignore all" sub-meta when we don't need them?
Hello,
When I try to run the function:
parse_nested_meta
on this structure:I am getting the following error: Got error while parsing meta: Error("expected
,
")Full code
```rust use syn::DeriveInput; use quote::quote; pub fn generate(input: DeriveInput) -> proc_macro2::TokenStream { if let syn::Data::Struct(s) = &input.data { let mut ret = quote! {}; for field in &s.fields { for attr in &field.attrs { if attr.path().is_ident("button") { attr.parse_nested_meta(|meta| { let path_name = meta.path.get_ident().unwrap().to_string(); println!("Path name: {path_name}"); ret.extend(quote! { println!("Path: {}", #path_name); }); println!("NEXT"); Ok(()) }).expect("Got error while parsing meta"); } } } quote! { fn random_func() { #ret } } } else { panic!("TestMacro is only available for struct"); } } #[cfg(test)] mod test { use super::generate; use prettyplease::unparse; use proc_macro2::TokenStream; use quote::quote; use syn::{parse_quote, DeriveInput, File, Item, ItemMod}; #[test] fn test_generation() { let input: DeriveInput = parse_quote! { #[TestMacro] pub struct TestStruct { #[button( field_one = "test", field_two = "field 2", field_three = "field 3", field_four = "very long field 4", field_five = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat" )] pub my_element: u32, } }; let result: TokenStream = generate(input); let wrapped_code = quote! { mod dummy { #result } }; // Convert the TokenStream to a syntax tree and then format it let syntax_tree: ItemMod = syn::parse2(wrapped_code).expect("Failed to parse TokenStream as ItemMod"); let file = File { shebang: None, attrs: Vec::new(), items: vec![Item::Mod(syntax_tree)], }; let formatted_code = unparse(&file); // Print the formatted code println!("{}", formatted_code); // Panic to keep the output visible panic!(); } } ```Cargo.toml
```toml [package] name = "telegram-button-maccro" version = "0.1.0" edition = "2021" [lib] proc-macro = true [dependencies] syn = { version = "2.0", features = ["full", "extra-traits"] } quote = "1.0" proc-macro2 = "1.0" [dev-dependencies] prettyplease = "0.2" ```cargo test
```log Compiling telegram-button-maccro v0.1.0 (/home/nicolas/Documents/projects2/poc/telegram-button-maccro) Finished test [unoptimized + debuginfo] target(s) in 0.48s Running unittests src/lib.rs (target/debug/deps/telegram_button_maccro-b1f06e26b47677b2) running 1 test test generate::test::test_generation ... FAILED failures: ---- generate::test::test_generation stdout ---- Path name: field_one NEXT thread 'generate::test::test_generation' panicked at src/generate.rs:19:24: Got error while parsing meta: Error("expected `,`") note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: generate::test::test_generation test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--lib` ```EDIT: After looking at #1426 I realized that I needed to actually extract the values:
Generate function fixed
```rust pub fn generate(input: DeriveInput) -> proc_macro2::TokenStream { if let syn::Data::Struct(s) = &input.data { let mut ret = quote! {}; for field in &s.fields { for attr in &field.attrs { if attr.path().is_ident("button") { attr.parse_nested_meta(|meta| { let path_name = meta.path.get_ident().unwrap().to_string(); println!("Path name: {path_name}"); let value = meta.value()?; let s: LitStr = value.parse()?; let val = s.value(); ret.extend(quote! { println!("Path: {} with val {}", #path_name, #val); }); println!("NEXT"); Ok(()) }).expect("Got error while parsing meta"); } } } quote! { fn random_func() { #ret } } } else { panic!("TestMacro is only available for struct"); } } ```When we are using
parse_nested_meta
we actually must parse all of the "sub-meta" also otherwise we get an error.Is it possible to have a macro or something that allow us to "ignore all" sub-meta when we don't need them?