1mod derive_action;
  2mod derive_app_context;
  3mod derive_into_element;
  4mod derive_render;
  5mod derive_visual_context;
  6mod register_action;
  7mod styles;
  8mod test;
  9
 10#[cfg(any(feature = "inspector", debug_assertions))]
 11mod derive_inspector_reflection;
 12
 13use proc_macro::TokenStream;
 14use syn::{DeriveInput, Ident};
 15
 16/// `Action` derive macro - see the trait documentation for details.
 17#[proc_macro_derive(Action, attributes(action))]
 18pub fn derive_action(input: TokenStream) -> TokenStream {
 19    derive_action::derive_action(input)
 20}
 21
 22/// This can be used to register an action with the GPUI runtime when you want to manually implement
 23/// the `Action` trait. Typically you should use the `Action` derive macro or `actions!` macro
 24/// instead.
 25#[proc_macro]
 26pub fn register_action(ident: TokenStream) -> TokenStream {
 27    register_action::register_action(ident)
 28}
 29
 30/// #[derive(IntoElement)] is used to create a Component out of anything that implements
 31/// the `RenderOnce` trait.
 32#[proc_macro_derive(IntoElement)]
 33pub fn derive_into_element(input: TokenStream) -> TokenStream {
 34    derive_into_element::derive_into_element(input)
 35}
 36
 37#[proc_macro_derive(Render)]
 38#[doc(hidden)]
 39pub fn derive_render(input: TokenStream) -> TokenStream {
 40    derive_render::derive_render(input)
 41}
 42
 43/// #[derive(AppContext)] is used to create a context out of anything that holds a `&mut App`
 44/// Note that a `#[app]` attribute is required to identify the variable holding the &mut App.
 45///
 46/// Failure to add the attribute causes a compile error:
 47///
 48/// ```compile_fail
 49/// # #[macro_use] extern crate gpui_macros;
 50/// # #[macro_use] extern crate gpui;
 51/// #[derive(AppContext)]
 52/// struct MyContext<'a> {
 53///     app: &'a mut gpui::App
 54/// }
 55/// ```
 56#[proc_macro_derive(AppContext, attributes(app))]
 57pub fn derive_app_context(input: TokenStream) -> TokenStream {
 58    derive_app_context::derive_app_context(input)
 59}
 60
 61/// #[derive(VisualContext)] is used to create a visual context out of anything that holds a `&mut Window` and
 62/// implements `AppContext`
 63/// Note that a `#[app]` and a `#[window]` attribute are required to identify the variables holding the &mut App,
 64/// and &mut Window respectively.
 65///
 66/// Failure to add both attributes causes a compile error:
 67///
 68/// ```compile_fail
 69/// # #[macro_use] extern crate gpui_macros;
 70/// # #[macro_use] extern crate gpui;
 71/// #[derive(VisualContext)]
 72/// struct MyContext<'a, 'b> {
 73///     #[app]
 74///     app: &'a mut gpui::App,
 75///     window: &'b mut gpui::Window
 76/// }
 77/// ```
 78///
 79/// ```compile_fail
 80/// # #[macro_use] extern crate gpui_macros;
 81/// # #[macro_use] extern crate gpui;
 82/// #[derive(VisualContext)]
 83/// struct MyContext<'a, 'b> {
 84///     app: &'a mut gpui::App,
 85///     #[window]
 86///     window: &'b mut gpui::Window
 87/// }
 88/// ```
 89#[proc_macro_derive(VisualContext, attributes(window, app))]
 90pub fn derive_visual_context(input: TokenStream) -> TokenStream {
 91    derive_visual_context::derive_visual_context(input)
 92}
 93
 94/// Used by GPUI to generate the style helpers.
 95#[proc_macro]
 96#[doc(hidden)]
 97pub fn style_helpers(input: TokenStream) -> TokenStream {
 98    styles::style_helpers(input)
 99}
100
101/// Generates methods for visibility styles.
102#[proc_macro]
103pub fn visibility_style_methods(input: TokenStream) -> TokenStream {
104    styles::visibility_style_methods(input)
105}
106
107/// Generates methods for margin styles.
108#[proc_macro]
109pub fn margin_style_methods(input: TokenStream) -> TokenStream {
110    styles::margin_style_methods(input)
111}
112
113/// Generates methods for padding styles.
114#[proc_macro]
115pub fn padding_style_methods(input: TokenStream) -> TokenStream {
116    styles::padding_style_methods(input)
117}
118
119/// Generates methods for position styles.
120#[proc_macro]
121pub fn position_style_methods(input: TokenStream) -> TokenStream {
122    styles::position_style_methods(input)
123}
124
125/// Generates methods for overflow styles.
126#[proc_macro]
127pub fn overflow_style_methods(input: TokenStream) -> TokenStream {
128    styles::overflow_style_methods(input)
129}
130
131/// Generates methods for cursor styles.
132#[proc_macro]
133pub fn cursor_style_methods(input: TokenStream) -> TokenStream {
134    styles::cursor_style_methods(input)
135}
136
137/// Generates methods for border styles.
138#[proc_macro]
139pub fn border_style_methods(input: TokenStream) -> TokenStream {
140    styles::border_style_methods(input)
141}
142
143/// Generates methods for box shadow styles.
144#[proc_macro]
145pub fn box_shadow_style_methods(input: TokenStream) -> TokenStream {
146    styles::box_shadow_style_methods(input)
147}
148
149/// `#[gpui::test]` can be used to annotate test functions that run with GPUI support.
150///
151/// It supports both synchronous and asynchronous tests, and can provide you with
152/// as many `TestAppContext` instances as you need.
153/// The output contains a `#[test]` annotation so this can be used with any existing
154/// test harness (`cargo test` or `cargo-nextest`).
155///
156/// ```
157/// #[gpui::test]
158/// async fn test_foo(mut cx: &TestAppContext) { }
159/// ```
160///
161/// In addition to passing a TestAppContext, you can also ask for a `StdRnd` instance.
162/// this will be seeded with the `SEED` environment variable and is used internally by
163/// the ForegroundExecutor and BackgroundExecutor to run tasks deterministically in tests.
164/// Using the same `StdRng` for behavior in your test will allow you to exercise a wide
165/// variety of scenarios and interleavings just by changing the seed.
166///
167/// # Arguments
168///
169/// - `#[gpui::test]` with no arguments runs once with the seed `0` or `SEED` env var if set.
170/// - `#[gpui::test(seed = 10)]` runs once with the seed `10`.
171/// - `#[gpui::test(seeds(10, 20, 30))]` runs three times with seeds `10`, `20`, and `30`.
172/// - `#[gpui::test(iterations = 5)]` runs five times, providing as seed the values in the range `0..5`.
173/// - `#[gpui::test(retries = 3)]` runs up to four times if it fails to try and make it pass.
174/// - `#[gpui::test(on_failure = "crate::test::report_failure")]` will call the specified function after the
175///   tests fail so that you can write out more detail about the failure.
176///
177/// You can combine `iterations = ...` with `seeds(...)`:
178/// - `#[gpui::test(iterations = 5, seed = 10)]` is equivalent to `#[gpui::test(seeds(0, 1, 2, 3, 4, 10))]`.
179/// - `#[gpui::test(iterations = 5, seeds(10, 20, 30)]` is equivalent to `#[gpui::test(seeds(0, 1, 2, 3, 4, 10, 20, 30))]`.
180/// - `#[gpui::test(seeds(10, 20, 30), iterations = 5]` is equivalent to `#[gpui::test(seeds(0, 1, 2, 3, 4, 10, 20, 30))]`.
181///
182/// # Environment Variables
183///
184/// - `SEED`: sets a seed for the first run
185/// - `ITERATIONS`: forces the value of the `iterations` argument
186#[proc_macro_attribute]
187pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
188    test::test(args, function)
189}
190
191/// When added to a trait, `#[derive_inspector_reflection]` generates a module which provides
192/// enumeration and lookup by name of all methods that have the shape `fn method(self) -> Self`.
193/// This is used by the inspector so that it can use the builder methods in `Styled` and
194/// `StyledExt`.
195///
196/// The generated module will have the name `<snake_case_trait_name>_reflection` and contain the
197/// following functions:
198///
199/// ```ignore
200/// pub fn methods::<T: TheTrait + 'static>() -> Vec<gpui::inspector_reflection::FunctionReflection<T>>;
201///
202/// pub fn find_method::<T: TheTrait + 'static>() -> Option<gpui::inspector_reflection::FunctionReflection<T>>;
203/// ```
204///
205/// The `invoke` method on `FunctionReflection` will run the method. `FunctionReflection` also
206/// provides the method's documentation.
207#[cfg(any(feature = "inspector", debug_assertions))]
208#[proc_macro_attribute]
209pub fn derive_inspector_reflection(_args: TokenStream, input: TokenStream) -> TokenStream {
210    derive_inspector_reflection::derive_inspector_reflection(_args, input)
211}
212
213pub(crate) fn get_simple_attribute_field(ast: &DeriveInput, name: &'static str) -> Option<Ident> {
214    match &ast.data {
215        syn::Data::Struct(data_struct) => data_struct
216            .fields
217            .iter()
218            .find(|field| field.attrs.iter().any(|attr| attr.path().is_ident(name)))
219            .map(|field| field.ident.clone().unwrap()),
220        syn::Data::Enum(_) => None,
221        syn::Data::Union(_) => None,
222    }
223}