This is what I'm trying to do. But the outcome is really buggy.
I'll skip the MyEnumVariantGen
custom Iterator
part, 'cause the macro expansion doesn't work as expected even without it.
This is a minimal demo of the proc macro crate:
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Variant};
#[proc_macro_attribute]
pub fn gen_variants(_: TokenStream, input: TokenStream) -> TokenStream {
let mut ast: DeriveInput = parse_macro_input!(input);
if let Data::Enum(ref mut data_enum) = ast.data {
if !data_enum.variants.is_empty(){
return quote! {
compile_error!("This macro can only be used with empty enums");
}
.into()
}
data_enum.variants.extend::<[Variant; 3]>([
syn::parse_quote! { A = 101 },
syn::parse_quote! { B = 102 },
syn::parse_quote! { C = 103 },
]);
quote! {
#ast
}
} else {
quote! {
compile_error!("This macro can only be used with enums");
}
}
.into()
}
(I'm not familiar with proc macros, this is based on Copilot generated code)
And in the main crate:
#[gen_variants]
enum MyEnum {}
Problem #1
IDE (RustRover, to be specific) doesn't recognize the generated variants.
In fact, it doesn't recognize the manipulated enum at all:
So of course IDE wouldn't help me generate the match arms.
However, this code actually compiles and works.
Problem #2
RustRover isn't the only one who fails to cooperate. The Debug derive macro fails to cover the macro-generated variants too:
So the problem is, the compiler clearly recognized the altered enum definition, but a lot of other components in the toolchain didn't.
Would the situation be improved in the near future?
P.S.
Could you give me a hint on how that can be done?