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::{graph::CodegenGraph, naming::SchemaIdent};
8
9pub struct CodegenTypesModule<'a> {
11 graph: &'a CodegenGraph<'a>,
12}
13
14impl<'a> CodegenTypesModule<'a> {
15 pub fn new(graph: &'a CodegenGraph<'a>) -> Self {
16 Self { graph }
17 }
18}
19
20impl ToTokens for CodegenTypesModule<'_> {
21 fn to_tokens(&self, tokens: &mut TokenStream) {
22 let mut mods = Vec::new();
23 let mut uses = Vec::new();
24
25 for view in self.graph.schemas() {
26 let resources: BTreeSet<_> = view.used_by().map(|op| op.resource()).collect();
27 let Some(cfg_attr) = cfg_attr(&resources) else {
28 continue;
29 };
30
31 let ext = view.extensions();
32 let info = ext.get::<SchemaIdent>().unwrap();
33 let module = info.module();
34 mods.push(quote! {
35 #cfg_attr
36 pub mod #module;
37 });
38
39 let ty = info.ty();
40 uses.push(quote! {
41 #cfg_attr
42 pub use #module::#ty;
43 });
44 }
45
46 tokens.append_all(quote! {
47 #(#mods)*
48
49 #(#uses)*
50 });
51 }
52}
53
54impl IntoCode for CodegenTypesModule<'_> {
55 type Code = (&'static str, TokenStream);
56
57 fn into_code(self) -> Self::Code {
58 ("src/types/mod.rs", self.into_token_stream())
59 }
60}
61
62fn cfg_attr(resources: &BTreeSet<&str>) -> Option<TokenStream> {
65 let mut features = resources.iter().peekable();
66 let first = features.next()?;
67 Some(match features.next() {
68 Some(next) => {
69 let rest = features.map(|f| quote! { feature = #f });
70 quote! { #[cfg(any(feature = #first, feature = #next, #(#rest),*))] }
71 }
72 None => quote! { #[cfg(feature = #first)] },
73 })
74}