use proc_macro::TokenStream; use quote::quote; use syn::{DeriveInput, parse_macro_input}; use crate::get_simple_attribute_field; pub fn derive_app_context(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); let Some(app_variable) = get_simple_attribute_field(&ast, "app") else { return quote! { compile_error!("Derive must have an #[app] attribute to detect the &mut App field"); } .into(); }; let type_name = &ast.ident; let (impl_generics, type_generics, where_clause) = ast.generics.split_for_impl(); let r#gen = quote! { impl #impl_generics gpui::AppContext for #type_name #type_generics #where_clause { type Result = T; fn new( &mut self, build_entity: impl FnOnce(&mut gpui::Context<'_, T>) -> T, ) -> Self::Result> { self.#app_variable.new(build_entity) } fn reserve_entity(&mut self) -> Self::Result> { self.#app_variable.reserve_entity() } fn insert_entity( &mut self, reservation: gpui::Reservation, build_entity: impl FnOnce(&mut gpui::Context<'_, T>) -> T, ) -> Self::Result> { self.#app_variable.insert_entity(reservation, build_entity) } fn update_entity( &mut self, handle: &gpui::Entity, update: impl FnOnce(&mut T, &mut gpui::Context<'_, T>) -> R, ) -> Self::Result where T: 'static, { self.#app_variable.update_entity(handle, update) } fn as_mut<'y, 'z, T>( &'y mut self, handle: &'z gpui::Entity, ) -> Self::Result> where T: 'static, { self.#app_variable.as_mut(handle) } fn read_entity( &self, handle: &gpui::Entity, read: impl FnOnce(&T, &gpui::App) -> R, ) -> Self::Result where T: 'static, { self.#app_variable.read_entity(handle, read) } fn update_window(&mut self, window: gpui::AnyWindowHandle, f: F) -> gpui::Result where F: FnOnce(gpui::AnyView, &mut gpui::Window, &mut gpui::App) -> T, { self.#app_variable.update_window(window, f) } fn read_window( &self, window: &gpui::WindowHandle, read: impl FnOnce(gpui::Entity, &gpui::App) -> R, ) -> gpui::Result where T: 'static, { self.#app_variable.read_window(window, read) } fn background_spawn(&self, future: impl std::future::Future + Send + 'static) -> gpui::Task where R: Send + 'static, { self.#app_variable.background_spawn(future) } fn read_global(&self, callback: impl FnOnce(&G, &gpui::App) -> R) -> Self::Result where G: gpui::Global, { self.#app_variable.read_global(callback) } } }; r#gen.into() }