Hi,
I am doing procedural macro workshop by dtolnay. In the first project where we are supposed to generate builder patterns for a given struct, I am able to solve till
test 5.. You can find all tests here.
In test 6, we have an optional argument, which I am unable to understand where to start solving. Till test 5, the program I wrote is
extern crate proc_macro;
use proc_macro2::{Ident, Span};
use proc_macro::TokenStream;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
use syn::{
parse_macro_input, parse_quote, Data, DataStruct, DeriveInput, Fields, GenericParam, Generics,
Index, Field
};
#[proc_macro_derive(Builder)]
pub fn derive(input: TokenStream) -> TokenStream {
// Parse the input tokens into a syntax tree.
let ast = parse_macro_input!(input as DeriveInput);
// get the field name and types
// This is taken from https://github.com/dtolnay/syn/issues/516
let fields = match &ast.data {
Data::Struct(DataStruct {
fields: Fields::Named(fields),
..
}) => &fields.named,
_ => panic!("expected a struct with named fields"),
};
let field_name = fields.iter().map(|field| &field.ident);
let field_type = fields.iter().map(|field| &field.ty);
let field_name_1 = fields.iter().map(|field| &field.ident);
let field_type_1 = fields.iter().map(|field| &field.ty);
let field_name_2 = fields.iter().map(|field| &field.ident);
let field_type_2 = fields.iter().map(|field| &field.ty);
let builder_name = Ident::new(
&format!("{}Builder", ast.ident.to_string().to_owned()),
Span::call_site(),
);
// Used in the quasi-quotation below as `#name`.
let name = ast.ident;
// // Add a bound `T: HeapSize` to every type parameter T.
// let generics = add_trait_bounds(input.generics);
// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
// // // Generate an expression to sum up the heap size of each field.
// let sum = heap_size_sum(&input.data);
let expanded = quote! {
// The generated impl.
impl #name {
fn builder() -> #builder_name{
#builder_name {
executable: None,
args: None,
env: None,
current_dir: None,
}
}
}
pub struct #builder_name{
#(
#field_name: Option<#field_type>,
)*
}
impl #builder_name{
#(
fn #field_name_1(&mut self, #field_name_1: #field_type_1) -> &mut Self{
self.#field_name_1 = Some(#field_name_1);
self
}
)*
pub fn build(&mut self) -> Result<#name, String> {
Ok(#name{
#(
#field_name_2: self.#field_name_2.as_ref().unwrap().clone(),
)*
})
}
}
};
// Hand the output tokens back to the compiler.
let output = proc_macro::TokenStream::from(expanded);
// eprintln!("INPUT: {:#?}", output);
output
}
Any help.