ferment_sys/lang/objc/
mod.rs1pub(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 }
68
69impl Config {
70 pub fn new(xcode: XCodeConfig) -> Self {
71 Self {
72 xcode,
73 }
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 Ok(())
93 }
96}
97
98
99impl 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 }));
148 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 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 ObjCFermentate::TokenStream(fermentate.to_token_stream())
193 }
194}