dodo_bindgen_codegen/
class.rs1use std::collections::BTreeMap;
2
3use crate::util::*;
4use crate::{FfiFunction, FfiType, TsMethod, TsModule};
5use dodo_bindgen_rust_ir::ItemImpl;
6use proc_macro2::TokenStream;
7use syn::Ident;
8
9use super::fn_::ItemFnExt as _;
10
11#[derive(Clone, Debug)]
12pub struct TsClass {
13 pub methods: Vec<TsMethod>,
14}
15
16#[derive(Clone, Debug, Default)]
17pub struct ClassDefs {
18 pub store: BTreeMap<Ident, TsClass>,
19}
20
21pub trait ItemImplExt {
22 fn unwrap(self, module: &mut TsModule);
23}
24
25impl ItemImplExt for ItemImpl {
26 fn unwrap(self, module: &mut TsModule) {
27 let mut methods = Vec::new();
28 for item in self.items {
29 let method = item.unwrap(module);
30 methods.push(method);
31 }
32
33 if let Some(ts_class) = module.class_defs.store.get_mut(&self.self_ty) {
34 ts_class.methods.append(&mut methods);
35 } else {
36 module.ffi_lib.interface.push_fn(FfiFunction {
37 ident: format_ident!("__{}__drop", &self.self_ty.to_string()),
38 inputs: vec![FfiType::Pointer],
39 output: FfiType::Void,
40 non_blocking: false,
41 });
42 module
43 .class_defs
44 .store
45 .insert(self.self_ty, TsClass { methods });
46 }
47 }
48}
49
50impl ToTokens for ClassDefs {
51 fn to_tokens(&self, tokens: &mut TokenStream) {
52 for (ident, TsClass { methods }) in &self.store {
53 let mut _methods = Vec::new();
54 for method in methods {
55 let method = method.print();
56 _methods.push(method);
57 }
58
59 tokens.extend(quote! {
60 export class #ident extends RustPrototype<#ident> {
61 #(#_methods)*
62 }
63 });
64 }
65 }
66}
67
68#[cfg(test)]
73mod tests {
74 use super::*;
75 use crate::{TsFormat, TsModule};
76 use dodo_bindgen_rust_ir::{parse_quote, prettify};
77
78 macro_rules! test_transform {
79 ($($tt:tt)*) => {
80 println!("[rust source]\n{}", prettify!(stringify!($($tt)*)));
81
82 let source = parse_quote!(ItemImpl, $($tt)*);
83
84 let mut export = source.clone();
85 export.transform();
86 println!("[rust wrapper]\n{}", prettify!(export.to_token_stream().to_string().as_str()));
87
88 let mut module = TsModule::default();
89 source.unwrap(&mut module);
90
91 let ffi_lib = TsFormat::format(module.ffi_lib.to_token_stream().to_string());
92 println!("[ts ffi]\n{}", ffi_lib);
93
94 let class_defs = TsFormat::format(module.class_defs.to_token_stream().to_string());
95 println!("[ts mod]\n{}", class_defs);
96 };
97 }
98
99 #[test]
100 fn test_print() {
101 test_transform!(
102 impl CustomType {
103 fn test_fn(&self) {}
104 }
105 );
106 }
107}