ferment_sys/lang/objc/
mod.rs

1pub(crate) mod composer;
2pub(crate) mod composers;
3pub(crate) mod constants;
4pub(crate) mod conversion;
5pub(crate) mod fermentate;
6pub(crate) mod presentation;
7#[allow(unused)]
8pub(crate) mod writer;
9mod xcproj;
10pub(crate) mod presentable;
11mod composable;
12mod formatter;
13mod dictionary;
14
15use std::fmt::{Display, Formatter};
16use quote::{quote, ToTokens};
17use syn::__private::TokenStream2;
18use syn::{Generics, Item, Lifetime, Type};
19use crate::error;
20use crate::lang::{CrateTreeConsumer, PresentableSpecification, Specification};
21use crate::lang::objc::composers::AttrWrapper;
22use crate::lang::objc::fermentate::InterfaceImplementation;
23use crate::lang::objc::presentable::TypeContext;
24use crate::tree::{CrateTree, ScopeTree, ScopeTreeItem};
25
26pub use fermentate::Fermentate as ObjCFermentate;
27#[cfg(feature = "objc")]
28pub use writer::Writer as ObjCWriter;
29#[cfg(feature = "objc")]
30pub use xcproj::Config as XCodeConfig;
31use crate::ast::{Depunctuated, SemiPunctuated};
32use crate::composable::CfgAttributes;
33use crate::composer::{SourceComposable, GenericComposer, MaybeComposer, SourceAccessible, SourceFermentable};
34use crate::conversion::expand_attributes;
35use crate::ext::Resolve;
36use crate::presentable::{Expression, ScopeContextPresentable};
37use crate::presentation::{FFIVariable, Name};
38
39pub trait ObjCSpecification:
40    PresentableSpecification<ObjCFermentate,
41        Attr=AttrWrapper,
42        Gen=Option<Generics>,
43        Interface=InterfaceImplementation,
44        TYC=TypeContext,
45        Expr=Expression<ObjCFermentate, Self>,
46        Name=Name<ObjCFermentate, Self>,
47        Var=FFIVariable<ObjCFermentate, Self, TokenStream2>
48    > where <Self::Expr as ScopeContextPresentable>::Presentation: ToTokens,
49            Type: Resolve<Self::Var> {}
50
51impl<SPEC> Specification<ObjCFermentate> for SPEC where SPEC: ObjCSpecification {
52    type Attr = AttrWrapper;
53    type Gen = Option<Generics>;
54    type Lt = Vec<Lifetime>;
55    type TYC = TypeContext;
56    type Interface = InterfaceImplementation;
57    type Expr = Expression<ObjCFermentate, SPEC>;
58    type Var = FFIVariable<ObjCFermentate, SPEC, TokenStream2>;
59    type Name = Name<ObjCFermentate, SPEC>;
60}
61
62
63#[derive(Debug, Clone)]
64pub struct Config {
65    pub xcode: XCodeConfig,
66    // pub targets: [&'static str; 5]
67}
68
69impl Config {
70    pub fn new(xcode: XCodeConfig) -> Self {
71        Self {
72            xcode,
73            // targets: APPLE_TARGETS
74        }
75    }
76    pub fn class_prefix(&self) -> &str {
77        &self.xcode.class_prefix
78    }
79}
80
81
82impl Display for Config {
83    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84        f.write_fmt(format_args!("[objc::Config]\n\txcode: {}", self.xcode))
85    }
86}
87
88impl CrateTreeConsumer for Config {
89    fn generate(&self, _crate_tree: &CrateTree) -> Result<(), error::Error> {
90        // let ff = ObjectPresentation::Interface { name: Name::Index(0), c_type: quote!(), properties: SemiPunctuated::new() };
91        // println!("objc:: {}", ff.to_token_stream());
92        Ok(())
93        // unimplemented!("{:?}", crate_tree)
94
95    }
96}
97
98
99// #[derive(Clone, Debug)]
100// pub enum CategoryKind {
101//     C,
102//     Rust,
103//     Args
104// }
105// impl ToTokens for CategoryKind {
106//     fn to_tokens(&self, tokens: &mut TokenStream2) {
107//         match self {
108//             CategoryKind::C => quote!(C),
109//             CategoryKind::Rust => quote!(Rust),
110//             CategoryKind::Args => quote!(Args),
111//         }.to_tokens(tokens)
112//     }
113// }
114
115impl ObjCSpecification for ScopeTree {}
116impl ObjCSpecification for CrateTree {}
117impl SourceFermentable<ObjCFermentate> for CrateTree {
118    fn ferment(&self) -> ObjCFermentate {
119        let Self { attrs: _, crates, generics_tree: ScopeTree { imported, .. }} = self;
120        let source = self.source_ref();
121        let reg_conversions = Depunctuated::from_iter(crates.iter().map(SourceFermentable::<ObjCFermentate>::ferment));
122        let _generic_imports = SemiPunctuated::from_iter(imported.iter().cloned());
123        let global = source.context
124            .read()
125            .unwrap();
126        let config = global.config.maybe_objc_config().unwrap();
127        let prefix = config.class_prefix();
128        let generic_conversions = Depunctuated::from_iter(
129            global.refined_mixins
130                .iter()
131                .filter_map(|(mixin, attrs)| {
132                    let attrs = expand_attributes(attrs);
133                    let ty_context = TypeContext::mixin(mixin, prefix, attrs.cfg_attributes());
134                    GenericComposer::<ObjCFermentate, CrateTree>::new(mixin, attrs, ty_context, self.context())
135                })
136                .flat_map(|composer| composer.borrow().compose(&source)));
137        let custom_conversions = Depunctuated::from_iter(
138            global.custom
139                .inner
140                .iter()
141                .map(|(_scope_chain, _type_chain)| {
142                    quote!()
143                    // CustomComposer::<ObjCFermentate, CrateTree>::new()
144                    // let attrs = expand_attributes(attrs);
145                    // let ty_context = TypeContext::mixin(mixin, prefix, attrs.cfg_attributes());
146                    // GenericComposer::<ObjCFermentate, CrateTree>::new(mixin, attrs, ty_context, self.context())
147                }));
148                // .flat_map(|composer| composer.borrow().compose(&source)));
149
150        // println!("CrateTree:: OBJC: {}", reg_conversions.to_token_stream());
151
152        ObjCFermentate::TokenStream(quote! {
153            #reg_conversions
154            #generic_conversions
155            #custom_conversions
156        })
157    }
158}
159
160impl SourceFermentable<ObjCFermentate> for ScopeTree {
161    fn ferment(&self) -> ObjCFermentate {
162        // let source = self.source_ref();
163        let mut fermentate = Depunctuated::<ObjCFermentate>::new();
164        self.exported
165            .values()
166            .for_each(|item| match item {
167                ScopeTreeItem::Item { item, scope, scope_context } =>
168                    if let Some(composer) = <Item as MaybeComposer<ObjCFermentate, ScopeTree>>::maybe_composer(item, scope, scope_context) {
169                        fermentate.push(composer.ferment())
170                    },
171                ScopeTreeItem::Tree { tree} =>
172                    fermentate.push(tree.ferment())
173            });
174        //println!("OBJC SCOPE FERMENTATE: {}", fermentate.to_token_stream());
175//         if !fermentate.is_empty() {
176//             let ctx = source.context.read().unwrap();
177//             let rename = ctx.config.current_crate.ident();
178//             let mut imports = SemiPunctuated::from_iter([
179//                 create_item_use_with_tree(UseTree::Rename(UseRename { ident: format_ident!("crate"), as_token: Default::default(), rename }))
180//             ]);
181//             imports.extend(SemiPunctuated::from_iter(self.imported.iter().cloned()));
182//             let name = if self.scope.is_crate_root() {
183//                 self.scope.crate_ident_ref().to_token_stream()
184//             } else {
185//                 self.scope.head().to_token_stream()
186//             };
187//             // Depunctuated::from_iter([RustFermentate::mod_with(self.attrs.cfg_attributes(), name, imports, fermentate)])
188//             Depunctuated::new()
189//         } else {
190//             Depunctuated::new()
191//         }
192        ObjCFermentate::TokenStream(fermentate.to_token_stream())
193    }
194}