crux_macros/lib.rs
1#![deny(clippy::pedantic)]
2
3mod capability;
4mod effect;
5mod effect_derive;
6mod export;
7
8use capability::capability_impl;
9use export::export_impl;
10use proc_macro::TokenStream;
11use proc_macro_error::proc_macro_error;
12use syn::{parse_macro_input, Ident, ItemEnum};
13
14/// Deprecated: use the `effect` attribute macro instead.
15///
16/// Procedural macro to derive an Effect enum, with a variant for
17/// each non-skipped capability.
18///
19/// The default name of the Effect enum is "Effect", but this can be
20/// overridden with the `name` attribute.
21///
22/// The default name of the app struct is "App", but this can be
23/// overridden with the `app` attribute.
24///
25/// No Effect variant will be generated for fields annotated with
26/// `#[effect(skip)]`.
27///
28/// e.g.
29/// ```rust
30/// # use crux_core::{Capability, render::Render, compose::Compose};
31/// # use crux_core::macros::Effect;
32/// # #[derive(Default)]
33/// # struct MyApp;
34/// # pub enum MyEvent {None}
35/// # impl crux_core::App for MyApp {
36/// # type Event = MyEvent;
37/// # type Model = ();
38/// # type ViewModel = ();
39/// # type Capabilities = MyCapabilities;
40/// # type Effect = MyEffect;
41/// # fn update(
42/// # &self,
43/// # _event: Self::Event,
44/// # _model: &mut Self::Model,
45/// # _caps: &Self::Capabilities,
46/// # ) -> crux_core::Command<MyEffect, MyEvent> {
47/// # unimplemented!()
48/// # }
49/// # fn view(&self, _model: &Self::Model) -> Self::ViewModel {
50/// # unimplemented!()
51/// # }
52/// # }
53/// #[derive(Effect)]
54/// #[effect(name = "MyEffect")]
55/// pub struct MyCapabilities {
56/// pub http: crux_http::Http<MyEvent>,
57/// pub render: Render<MyEvent>,
58/// #[effect(skip)]
59/// pub compose: Compose<MyEvent>,
60/// }
61#[proc_macro_derive(Effect, attributes(effect))]
62#[proc_macro_error]
63pub fn effect_derive(input: TokenStream) -> TokenStream {
64 effect_derive::effect_impl(&parse_macro_input!(input)).into()
65}
66
67/// Generates an effect type matching the enum definition provided,
68/// whilst supplying all the necessary decorations and additional trait implementations.
69///
70/// Use `typegen` as an argument if you want to opt in to the built-in foreign type generation.
71///
72/// e.g.
73/// ```rust
74/// # use crux_core::{Capability, render::RenderOperation, compose::Compose};
75/// # use crux_core::macros::effect;
76/// # use crux_http::protocol::HttpRequest;
77/// # #[derive(Default)]
78/// # struct MyApp;
79/// # pub enum MyEvent {None}
80/// # impl crux_core::App for MyApp {
81/// # type Event = MyEvent;
82/// # type Model = ();
83/// # type ViewModel = ();
84/// # type Capabilities = ();
85/// # type Effect = MyEffect;
86/// # fn update(
87/// # &self,
88/// # _event: Self::Event,
89/// # _model: &mut Self::Model,
90/// # _caps: &Self::Capabilities,
91/// # ) -> crux_core::Command<MyEffect, MyEvent> {
92/// # unimplemented!()
93/// # }
94/// # fn view(&self, _model: &Self::Model) -> Self::ViewModel {
95/// # unimplemented!()
96/// # }
97/// # }
98/// #[effect(typegen)]
99/// pub enum MyEffect {
100/// Render(RenderOperation),
101/// Http(HttpRequest),
102/// }
103/// ```
104#[proc_macro_attribute]
105pub fn effect(args: TokenStream, input: TokenStream) -> TokenStream {
106 let args = parse_macro_input!(args as Option<Ident>);
107 let input = parse_macro_input!(input as ItemEnum);
108 effect::effect_impl(args, input).into()
109}
110
111#[proc_macro_derive(Export)]
112#[proc_macro_error]
113pub fn export(input: TokenStream) -> TokenStream {
114 export_impl(&parse_macro_input!(input)).into()
115}
116
117/// Deprecated: use the `effect` attribute macro instead.
118#[proc_macro_derive(Capability)]
119#[proc_macro_error]
120pub fn capability(input: TokenStream) -> TokenStream {
121 capability_impl(&parse_macro_input!(input)).into()
122}
123
124#[cfg(test)]
125fn pretty_print(ts: &proc_macro2::TokenStream) -> String {
126 let file = syn::parse_file(&ts.to_string()).unwrap();
127 prettyplease::unparse(&file)
128}