use proc_macro_crate::{FoundCrate, crate_name};
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote};
use syn::Token;
use syn::parse::{Parse, ParseStream};
use syn::token::Brace;
use syn::{
Attribute, Field, FnArg, Ident, ImplItemFn, Pat, Type, Visibility, braced,
parse_macro_input, parse_quote,
};
mod kw {
syn::custom_keyword!(class);
}
#[derive(Debug, Clone)]
struct OverrideItem {
_override_token: Token![override],
override_class: Type,
_brace_token: Brace,
items: Vec<ImplItemFn>,
}
fn correct_priv_vis(vis: Visibility) -> Visibility {
match vis {
Visibility::Public(p) => Visibility::Public(p),
Visibility::Restricted(mut restricted) => {
if restricted.path.segments.get(0) != Some(&parse_quote!(crate)) {
restricted.path.segments.insert(0, parse_quote!(super));
}
Visibility::Restricted(restricted)
}
Visibility::Inherited => {
parse_quote!(pub(super))
}
}
}
impl Parse for OverrideItem {
fn parse(input: ParseStream) -> syn::Result<Self> {
let content;
let override_token = input.parse()?;
let override_class = input.parse()?;
let brace_token = braced!(content in input);
let mut items = Vec::new();
while !content.is_empty() {
let mut item: ImplItemFn = content.parse()?;
item.vis = correct_priv_vis(item.vis);
items.push(item);
}
Ok(OverrideItem {
_override_token: override_token,
override_class,
_brace_token: brace_token,
items,
})
}
}
#[derive(Debug, Clone)]
enum ClassItem {
Field {
field: Field,
_semi_token: Token![;],
},
ImplItemFn(ImplItemFn),
OverrideItem(OverrideItem),
}
impl Parse for ClassItem {
fn parse(input: ParseStream) -> syn::Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(Token![override]) {
return Ok(ClassItem::OverrideItem(OverrideItem::parse(input)?));
}
let begin = input.fork();
let _attrs = input.call(Attribute::parse_outer)?;
let _vis: Visibility = begin.parse()?;
let lookahead = begin.lookahead1();
if lookahead.peek(Token![fn]) || lookahead.peek(Token![unsafe]) {
return Ok(ClassItem::ImplItemFn(ImplItemFn::parse(input)?));
}
let mut field = Field::parse_named(input)?;
field.vis = correct_priv_vis(field.vis);
let semi_token = input.parse()?;
Ok(ClassItem::Field {
field,
_semi_token: semi_token,
})
}
}
#[derive(Debug, Clone)]
struct SuperclassInput {
_colon_token: Token![:],
ty: Type,
}
impl Parse for SuperclassInput {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(SuperclassInput {
_colon_token: input.parse()?,
ty: input.parse()?,
})
}
}
#[derive(Debug, Clone)]
struct ClassInput {
vis: Visibility,
_class_token: kw::class,
ident: Ident,
superclass: Option<SuperclassInput>,
_brace_token: Brace,
items: Vec<ClassItem>,
}
impl Parse for ClassInput {
fn parse(input: ParseStream) -> syn::Result<Self> {
let content;
let vis = input.parse()?;
let class_token = input.parse()?;
let ident = input.parse()?;
let lookahead = input.lookahead1();
let superclass = if lookahead.peek(Token![:]) {
Some(input.parse()?)
} else {
None
};
let brace_token = braced!(content in input);
let mut items = Vec::new();
while !content.is_empty() {
items.push(content.parse()?);
}
Ok(ClassInput {
vis,
_class_token: class_token,
ident,
superclass,
_brace_token: brace_token,
items,
})
}
}
#[derive(Debug, Clone)]
struct CrateAlias {
_crate_token: Token![crate],
_as_token: Token![as],
ident: Ident,
_semi_token: Token![;],
}
impl Parse for CrateAlias {
fn parse(input: ParseStream) -> syn::Result<Self> {
Ok(CrateAlias {
_crate_token: input.parse()?,
_as_token: input.parse()?,
ident: input.parse()?,
_semi_token: input.parse()?,
})
}
}
struct ClassInputs {
crate_alias: Option<CrateAlias>,
inputs: Vec<ClassInput>,
}
impl Parse for ClassInputs {
fn parse(input: ParseStream) -> syn::Result<Self> {
let lookahead = input.lookahead1();
let crate_alias = if lookahead.peek(Token![crate]) {
Some(input.parse()?)
} else {
None
};
let mut inputs = Vec::new();
while !input.is_empty() {
inputs.push(input.parse()?);
}
Ok(ClassInputs {
crate_alias,
inputs,
})
}
}
fn plusplus() -> proc_macro2::TokenStream {
let found_crate = crate_name("plusplus").expect("plusplus is present in `Cargo.toml`");
match found_crate {
FoundCrate::Itself => quote!(crate),
FoundCrate::Name(name) => {
let ident = Ident::new(&name, Span::call_site());
quote!( #ident )
}
}
}
fn cast_class_ptr(
plusplus: &proc_macro2::TokenStream,
from: &Type,
to: &Type,
expr: impl Into<proc_macro2::TokenStream>,
) -> proc_macro2::TokenStream {
let expr = expr.into();
quote! {{
let t: &#from = #expr;
let self_size = std::mem::size_of_val(t);
let target_size = std::mem::size_of::<#to<#plusplus::InConstruction>>();
assert!(self_size >= target_size);
let array_size = self_size - target_size;
let target_ptr = std::ptr::slice_from_raw_parts(t as *const #from as *const u8, array_size);
let target_ref = &*(target_ptr as *const #to);
assert_eq!(self_size, std::mem::size_of_val(target_ref));
target_ref
}}
}
fn cast_class_ptr_mut(
plusplus: &TokenStream,
from: &Type,
to: &Type,
expr: impl Into<TokenStream>,
) -> TokenStream {
let expr = expr.into();
quote! {{
let t: &mut #from = #expr;
let self_size = std::mem::size_of_val(t);
let target_size = std::mem::size_of::<#to<#plusplus::InConstruction>>();
assert!(self_size >= target_size);
let array_size = self_size - target_size;
let target_ptr = std::ptr::slice_from_raw_parts_mut(t as *mut #from as *mut u8, array_size);
let target_ref = &mut *(target_ptr as *mut #to);
assert_eq!(self_size, std::mem::size_of_val(target_ref));
target_ref
}}
}
#[derive(Debug, Clone)]
struct FuncInfo {
func: ImplItemFn,
name: Ident,
vtbl_name: Ident,
sig: TokenStream,
args: Vec<Box<Pat>>,
mut_self: bool,
}
fn get_func_sig(class_name: &Type, f: &ImplItemFn) -> FuncInfo {
let func_name = &f.sig.ident;
let mut inputs = f.sig.inputs.clone();
let mut mut_self = false;
if let Some(FnArg::Receiver(rx)) = &f.sig.inputs.get(0) {
let receiver = &mut inputs[0];
if rx.mutability.is_some() {
*receiver = FnArg::Typed(parse_quote!(this: &mut #class_name));
} else {
*receiver = FnArg::Typed(parse_quote!(this: &#class_name));
}
mut_self = rx.mutability.is_some();
};
let output = &f.sig.output;
let func_sig = quote! {
(#inputs) #output
};
let vtbl_name = format_ident!("fn_{func_name}");
let func_args = inputs
.into_iter()
.skip(1)
.map(|arg| match arg {
FnArg::Receiver(_) => unreachable!(),
FnArg::Typed(arg) => arg.pat,
})
.collect::<Vec<_>>();
FuncInfo {
func: f.clone(),
name: func_name.clone(),
vtbl_name,
sig: func_sig,
args: func_args,
mut_self,
}
}
struct ClassData {
plusplus: TokenStream,
class_name: Ident,
class_type: Type,
class_mod_name: Ident,
vtbl_ident: Ident,
class_vis: Visibility,
fields: Vec<Field>,
constructors: Vec<FuncInfo>,
member_funcs: Vec<FuncInfo>,
overrides: Vec<OverrideItem>,
override_funcs: Vec<FuncInfo>,
superclass_type: Option<Type>,
mod_superclass_type: Option<Type>,
}
impl ClassData {
fn from_input(input: ClassInput, crate_alias: Option<&CrateAlias>) -> ClassData {
let ClassInput {
vis: class_vis,
_class_token: _,
ident: class_name,
superclass,
_brace_token: _,
items: class_items,
} = input;
let mut fields = Vec::new();
let mut constructors = Vec::new();
let mut member_funcs = Vec::new();
let mut overrides = Vec::new();
let mut override_funcs = Vec::new();
let class_type: Type = parse_quote!(#class_name);
for item in class_items {
match item {
ClassItem::Field { field, .. } => fields.push(field),
ClassItem::ImplItemFn(func) => {
if let Some(FnArg::Receiver(_)) = func.sig.inputs.get(0) {
member_funcs.push(get_func_sig(&class_type, &func))
} else {
constructors.push(get_func_sig(&class_type, &func));
}
}
ClassItem::OverrideItem(override_item) => {
override_funcs.extend(override_item.items.iter().map(|f| get_func_sig(&class_type, &f)));
overrides.push(override_item);
}
}
}
let class_mod_name = format_ident!("plusplus__class_{}", class_name.to_string().to_lowercase());
let plusplus = if let Some(alias) = crate_alias {
let alias = &alias.ident;
quote!(#alias)
} else {
plusplus()
};
let superclass_type = superclass.map(|sc| sc.ty);
let mod_superclass_type = match superclass_type.clone() {
Some(Type::Path(mut type_path)) => {
if type_path.path.segments.get(0) != Some(&parse_quote!(crate)) {
type_path.path.segments.insert(0, parse_quote!(super));
}
Some(Type::Path(type_path))
}
ty => ty
};
ClassData {
plusplus,
vtbl_ident: format_ident!("{}Vtbl", class_name),
class_vis,
class_name,
class_type,
class_mod_name,
fields,
constructors,
member_funcs,
overrides,
override_funcs,
superclass_type,
mod_superclass_type,
}
}
fn has_superclass(&self) -> bool {
self.superclass_type.is_some()
}
fn gen_mod_vtbl_struct(&self) -> TokenStream {
let vtbl_ident = &self.vtbl_ident;
let class_name = &self.class_name;
let mut vtbl_func_names = Vec::new();
let mut func_sigs = Vec::new();
let mut my_func_names = Vec::new();
for f in self.member_funcs.iter() {
let FuncInfo {
func: ImplItemFn{ .. },
name: func_name,
vtbl_name,
sig: func_sig,
args: _,
mut_self: _,
} = f;
vtbl_func_names.push(vtbl_name);
func_sigs.push(func_sig);
let my_func_name = format_ident!("my_{func_name}");
my_func_names.push(my_func_name);
}
let vtbl_drop_field: Option<_>;
let vtbl_drop_func: Option<_>;
let vtbl_drop_set: Option<_>;
if !self.has_superclass() {
vtbl_drop_field = Some(quote! {
pub manually_drop: unsafe fn(*mut #class_name),
});
vtbl_drop_func = Some(quote! {
unsafe fn manually_drop(this: *mut #class_name) {
unsafe{ std::ptr::drop_in_place(this) }
}
});
vtbl_drop_set = Some(quote! {
manually_drop,
});
} else {
vtbl_drop_field = None;
vtbl_drop_func = None;
vtbl_drop_set = None;
};
quote! {
#[doc(hidden)]
pub struct #vtbl_ident {
#vtbl_drop_field
#(pub #vtbl_func_names: fn #func_sigs,)*
}
impl #vtbl_ident {
const BASE: Self = {
#vtbl_drop_func
Self {
#vtbl_drop_set
#(#vtbl_func_names: #class_name::#my_func_names,)*
}
};
}
}
}
fn gen_fn_set_vtbls(&self) -> TokenStream {
let plusplus = &self.plusplus;
let class_name = &self.class_name;
let set_vtbls = self.overrides.iter().map(|ovr| {
let ovr_class = &ovr.override_class;
let ovr_class = match ovr_class.clone() {
Type::Path(mut type_path) => {
type_path.path.segments.insert(0, parse_quote!(super));
Type::Path(type_path)
}
ty => ty
};
let mut ol_func_names = Vec::new();
let mut ol_func_sigs = Vec::new();
let mut ol_func_self_call_impls = Vec::new();
for f in &ovr.items {
let FuncInfo {
func: _,
name: func_name,
vtbl_name,
sig: func_sig,
args: func_args,
mut_self,
} = get_func_sig(&ovr_class, f);
ol_func_names.push(vtbl_name);
ol_func_sigs.push(func_sig);
let func_name = format_ident!("my_{}", func_name);
let self_call = if mut_self {
let cast_mut = cast_class_ptr_mut(
&plusplus,
&ovr_class,
&self.class_type,
quote! {this},
);
quote! {
let this: &mut #class_name = unsafe{ #cast_mut };
this.#func_name(#(#func_args,)*)
}
} else {
let cast = cast_class_ptr(&plusplus, &ovr_class, &self.class_type, quote! {this});
quote! {
let this: &#class_name = unsafe{ #cast };
this.#func_name(#(#func_args,)*)
}
};
ol_func_self_call_impls.push(self_call);
}
quote! {{
let this: &mut #ovr_class = &mut *(unsafe{ self.to_constructed() });
#(
fn #ol_func_names #ol_func_sigs {
#ol_func_self_call_impls
}
unsafe{ this.plusplus__vtbl_mut().#ol_func_names = #ol_func_names };
)*
}}
});
let root_type: Type = parse_quote!(<#class_name as #plusplus::Class>::RootClass);
let cast_root_to_self =
cast_class_ptr_mut(&plusplus, &root_type, &self.class_type, quote!(ref_mut));
let root_type = &root_type;
let set_subclass = self.has_superclass().then(|| quote!{
unsafe{ self.superclass.plusplus__set_subclass(<#class_name as #plusplus::Class>::TYPE_ID) };
{
unsafe fn manually_drop(this: *mut #root_type) {
let ref_mut = unsafe{ &mut *this };
let this = unsafe{ #cast_root_to_self };
unsafe{ std::ptr::drop_in_place(this) };
}
let root_vtbl = unsafe{ <#class_name as #plusplus::Class>::root_class_mut(self.to_constructed()).plusplus__vtbl_mut() };
root_vtbl.manually_drop = manually_drop;
}
});
quote! {
fn plusplus__set_vtbls(&mut self) {
#set_subclass
#(#set_vtbls)*
}
}
}
fn gen_mod_class_struct(&self) -> TokenStream {
let plusplus = &self.plusplus;
let superclass_field = self.mod_superclass_type.as_ref().map(|sc_type| {
quote! {
superclass: #sc_type<#plusplus::InConstruction>,
}
});
let superclass_field = superclass_field.as_ref();
let superclass_bound = self.mod_superclass_type.as_ref().map(|sc_ident| quote!{
where #sc_ident: #plusplus::Class
});
let class_struct_vis = correct_priv_vis(self.class_vis.clone());
let vtbl_ident = &self.vtbl_ident;
let class_name = &self.class_name;
let fields = &self.fields;
let init_superclass_field = superclass_field.map(|f| quote!(pub #f));
let init_fields = self.fields.iter().cloned().map(|f| Field {
vis: Visibility::Public(parse_quote!(pub)),
..f
});
quote! {
#[repr(C)]
#class_struct_vis struct #class_name<C: ?Sized + #plusplus::ClassMemory = #plusplus::Constructed>
#superclass_bound
{
#superclass_field
vtbl: #vtbl_ident,
subclass_id: Option<std::any::TypeId>,
#(#fields,)*
memory: C,
}
pub struct PlusPlus__InitClass {
#init_superclass_field
#(#init_fields,)*
}
}
}
fn gen_superclass_casters(&self) -> Option<TokenStream> {
let Some(sc_type) = self.superclass_type.as_ref() else {
return None;
};
let class_name = &self.class_name;
let deref_upcast = cast_class_ptr(&self.plusplus, &self.class_type, sc_type, quote! {self});
let deref_upcast_mut = cast_class_ptr_mut(
&self.plusplus,
&self.class_type,
sc_type,
quote! {self},
);
let ref_downcast = cast_class_ptr(&self.plusplus, sc_type, &self.class_type, quote! {self});
let ref_downcast_mut = cast_class_ptr_mut(
&self.plusplus,
sc_type,
&self.class_type,
quote! {self},
);
let plusplus = &self.plusplus;
Some(quote! {
impl std::ops::Deref for #class_name {
type Target = #sc_type;
fn deref(&self) -> &Self::Target {
unsafe { #deref_upcast }
}
}
impl std::ops::DerefMut for #class_name {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { #deref_upcast_mut }
}
}
impl<'a> #plusplus::Downcast<#class_name> for &'a #sc_type {
type Wrapped = &'a #class_name;
fn downcast(self) -> Result<&'a #class_name, Self> {
use #plusplus::Class;
let subclass_type_id = <#class_name as #plusplus::Class>::TYPE_ID;
if self.subclass_id() == Some(subclass_type_id) {
Ok(unsafe{ #ref_downcast })
} else {
Err(self)
}
}
}
impl<'a> #plusplus::Downcast<#class_name> for &'a mut #sc_type {
type Wrapped = &'a mut #class_name;
fn downcast(self) -> Result<&'a mut #class_name, Self> {
use #plusplus::Class;
let subclass_type_id = <#class_name as #plusplus::Class>::TYPE_ID;
if self.subclass_id() == Some(subclass_type_id) {
Ok(unsafe{ #ref_downcast_mut })
} else {
Err(self)
}
}
}
})
}
fn gen_mod_impl_class_trait(&self) -> TokenStream {
let plusplus = &self.plusplus;
let class_name = &self.class_name;
let root_class = self.mod_superclass_type
.as_ref()
.map(|sc_ident| quote! { <#sc_ident as #plusplus::Class>::RootClass })
.unwrap_or_else(|| quote! { #class_name });
quote! {
unsafe impl #plusplus::Class for #class_name {
const TYPE_ID: std::any::TypeId = std::any::TypeId::of::<#class_name>();
type RootClass = #root_class;
fn subclass_id(&self) -> Option<std::any::TypeId> {
self.subclass_id
}
fn root_class(&self) -> &Self::RootClass {
self
}
fn root_class_mut(&mut self) -> &mut Self::RootClass {
self
}
unsafe fn manually_drop(slot: &mut std::mem::ManuallyDrop<Self>) {
let as_root_class = slot.root_class_mut();
let manual_drop_fn = unsafe{ as_root_class.plusplus__vtbl_mut().manually_drop };
unsafe{ manual_drop_fn(as_root_class); }
}
}
}
}
fn gen_mod_class_impl(&self) -> TokenStream {
let class_name = &self.class_name;
let vtbl_ident = &self.vtbl_ident;
let mut call_vtbl_impls = Vec::new();
for f in self.member_funcs.iter() {
let FuncInfo {
func: ImplItemFn{ vis, sig, ..},
name: _,
vtbl_name,
sig: _,
args: func_args,
mut_self: _,
} = f;
let vis = correct_priv_vis(vis.clone());
let call_vtbl = quote! {
#vis #sig {
(self.vtbl.#vtbl_name)(self, #(#func_args,)*)
}
};
call_vtbl_impls.push(call_vtbl);
}
let mut my_func_impls = Vec::new();
let mut super_func_impls = Vec::new();
for (f, is_override) in self.member_funcs
.iter().cloned()
.map(|f| (f, false))
.chain(self.override_funcs.iter().cloned().map(|f| (f, true)))
{
let FuncInfo {
func: ImplItemFn {
attrs: _,
vis,
defaultness: _,
sig,
block,
},
name: func_name,
vtbl_name: _,
sig: _,
args: func_args,
mut_self,
} = f;
let my_impl_name = format_ident!("my_{}", func_name);
let mut my_impl_sig = sig.clone();
my_impl_sig.ident = my_impl_name.clone();
my_func_impls.push(quote! {
#vis #my_impl_sig {
#block
}
});
if is_override {
let super_impl_name = format_ident!("super_{}", func_name);
let mut super_impl_sig = sig.clone();
super_impl_sig.ident = super_impl_name.clone();
let super_impl_block = if mut_self {
quote! {
self.plusplus__super_mut().#my_impl_name(#(#func_args)*)
}
} else {
quote! {
self.plusplus__super_ref().#my_impl_name(#(#func_args)*)
}
};
super_func_impls.push(quote! {
#vis #super_impl_sig {
#super_impl_block
}
});
}
}
let superclass_getters = self.mod_superclass_type.as_ref().map(|sc_ident| {
quote! {
fn plusplus__super_ref(&self) -> &#sc_ident {
self
}
fn plusplus__super_mut(&mut self) -> &mut #sc_ident {
self
}
}
});
quote!{
impl #class_name {
#(#call_vtbl_impls)*
#(#super_func_impls)*
#superclass_getters
#[doc(hidden)]
pub unsafe fn plusplus__vtbl_mut(&mut self) -> &mut #vtbl_ident {
&mut self.vtbl
}
}
}
}
fn gen_mod_in_construction_class_impl(&self) -> TokenStream {
let plusplus = &self.plusplus;
let class_name = &self.class_name;
let vtbl_ident = &self.vtbl_ident;
let set_vtbl_func = self.gen_fn_set_vtbls();
let class_vis = correct_priv_vis(self.class_vis.clone());
let superclass_field = self.has_superclass().then(|| quote!{superclass: init.superclass,});
let fields = self.fields.iter().map(|f| &f.ident).collect::<Vec<_>>();
quote!{
impl #class_name<#plusplus::InConstruction> {
#set_vtbl_func
pub(super) fn plusplus__new_from_init(init: PlusPlus__InitClass) -> Self {
let mut this = Self {
vtbl: #vtbl_ident::BASE,
memory: #plusplus::InConstruction::default(),
subclass_id: None,
#superclass_field
#(#fields: init.#fields,)*
};
this.plusplus__set_vtbls();
this
}
#[doc(hidden)]
pub unsafe fn plusplus__set_subclass(&mut self, subclass_id: std::any::TypeId) {
self.subclass_id = Some(subclass_id);
}
pub unsafe fn to_constructed(&mut self) -> &mut #class_name {
unsafe{ &mut *(std::ptr::slice_from_raw_parts_mut::<u8>(self as *mut _ as *mut u8, 0) as *mut #class_name) }
}
#class_vis fn finish(self: #class_name<#plusplus::InConstruction>) -> #plusplus::ClassBox<#class_name> {
let boxed = Box::new(self);
let leaked = Box::leak(boxed);
let constructed = unsafe{ leaked.to_constructed() };
unsafe{ #plusplus::ClassBox::from_raw(constructed) }
}
}
}
}
fn gen_init_class_macro(&self) -> TokenStream {
let plusplus = &self.plusplus;
let class_name = &self.class_name;
let class_mod_name = &self.class_mod_name;
quote! {
macro_rules! init_class {
($($tt:tt)*) => {{
#class_name::<#plusplus::InConstruction>::plusplus__new_from_init(#class_mod_name::PlusPlus__InitClass {
$($tt)*
})
}}
}
}
}
fn gen_class_impl(&self) -> TokenStream {
let class_name = &self.class_name;
let mut my_func_impls = Vec::new();
for f in self.member_funcs
.iter().cloned()
.chain(self.override_funcs.iter().cloned())
{
let FuncInfo {
func: ImplItemFn {
attrs: _,
vis,
defaultness: _,
sig,
block,
},
name: func_name,
vtbl_name: _,
sig: _,
args: _,
mut_self: _,
} = f;
let my_impl_name = format_ident!("my_{}", func_name);
let mut my_impl_sig = sig.clone();
my_impl_sig.ident = my_impl_name.clone();
my_func_impls.push(quote! {
#vis #my_impl_sig {
#block
}
});
}
let init_class_macro = self.gen_init_class_macro();
let mut constructor_impls = Vec::new();
for c in self.constructors.iter() {
let ImplItemFn {
attrs,
vis,
defaultness,
sig,
block,
} = &c.func;
let vis = correct_priv_vis(vis.clone());
constructor_impls.push(quote! {
#(#attrs)* #vis #defaultness #sig {
#init_class_macro
#block
}
});
}
quote!{
impl #class_name {
#(#constructor_impls)*
#(#my_func_impls)*
}
}
}
fn gen_class(&self) -> TokenStream {
let class_vis = &self.class_vis;
let class_name = &self.class_name;
let class_mod_name = &self.class_mod_name;
let mod_vtbl_struct = self.gen_mod_vtbl_struct();
let mod_class_struct = self.gen_mod_class_struct();
let mod_impl_class_trait = self.gen_mod_impl_class_trait();
let superclass_cast = self.gen_superclass_casters();
let mod_class_impl = self.gen_mod_class_impl();
let mod_in_construction_class_impl = self.gen_mod_in_construction_class_impl();
let class_impl = self.gen_class_impl();
quote! {
#class_vis use #class_mod_name::#class_name;
mod #class_mod_name {
use super::*;
#mod_vtbl_struct
#mod_class_struct
#mod_class_impl
#mod_impl_class_trait
#mod_in_construction_class_impl
}
#class_impl
#superclass_cast
}
}
}
#[proc_macro]
pub fn class(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
let inputs = parse_macro_input!(tokens as ClassInputs);
let class_data = inputs.inputs.into_iter().map(|input| ClassData::from_input(input, inputs.crate_alias.as_ref()).gen_class());
let output = quote!{
#(#class_data)*
};
output.into()
}