ploidy_codegen_rust/
types.rs1use std::collections::BTreeSet;
2
3use ploidy_core::{codegen::IntoCode, ir::View};
4use proc_macro2::TokenStream;
5use quote::{ToTokens, TokenStreamExt, quote};
6
7use super::{
8 graph::CodegenGraph,
9 naming::{CodegenIdent, CodegenIdentUsage},
10};
11
12pub struct CodegenTypesModule<'a> {
14 graph: &'a CodegenGraph<'a>,
15}
16
17impl<'a> CodegenTypesModule<'a> {
18 pub fn new(graph: &'a CodegenGraph<'a>) -> Self {
19 Self { graph }
20 }
21}
22
23impl ToTokens for CodegenTypesModule<'_> {
24 fn to_tokens(&self, tokens: &mut TokenStream) {
25 let mut mods = Vec::new();
26 let mut uses = Vec::new();
27
28 for view in self.graph.schemas() {
29 let resources: BTreeSet<_> = view.used_by().map(|op| op.resource()).collect();
30 let Some(cfg_attr) = cfg_attr(&resources) else {
31 continue;
32 };
33
34 let ext = view.extensions();
35 let ident = ext.get::<CodegenIdent>().unwrap();
36 let mod_name = CodegenIdentUsage::Module(&ident);
37 mods.push(quote! {
38 #cfg_attr
39 pub mod #mod_name;
40 });
41
42 let ty_name = CodegenIdentUsage::Type(&ident);
43 uses.push(quote! {
44 #cfg_attr
45 pub use #mod_name::#ty_name;
46 });
47 }
48
49 tokens.append_all(quote! {
50 #(#mods)*
51
52 #(#uses)*
53 });
54 }
55}
56
57impl IntoCode for CodegenTypesModule<'_> {
58 type Code = (&'static str, TokenStream);
59
60 fn into_code(self) -> Self::Code {
61 ("src/types/mod.rs", self.into_token_stream())
62 }
63}
64
65fn cfg_attr(resources: &BTreeSet<&str>) -> Option<TokenStream> {
68 let mut features = resources.iter().peekable();
69 let first = features.next()?;
70 Some(match features.next() {
71 Some(next) => {
72 let rest = features.map(|f| quote! { feature = #f });
73 quote! { #[cfg(any(feature = #first, feature = #next, #(#rest),*))] }
74 }
75 None => quote! { #[cfg(feature = #first)] },
76 })
77}