From 760d0a31003c70ed6017b2a70059a76d9b268425 Mon Sep 17 00:00:00 2001 From: raldone01 Date: Sun, 15 Dec 2024 16:00:05 +0100 Subject: [PATCH] Use one `BevyManifest` instance in proc macros (#16766) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective - Minor consistency improvement in proc macro code. - Remove `get_path_direct` since it was only used once anyways and doesn't add much. ## Solution - Possibly a minor performance improvement since the `Cargo.toml` wont be parsed as often. ## Testing - I don't think it breaks anything. - This is my first time working on bevy itself. Is there a script to do a quick verify of my pr? ## Other PR Similar to #7536 but has no extra dependencies. Co-authored-by: François Mockers --- crates/bevy_asset/macros/src/lib.rs | 2 +- crates/bevy_derive/src/lib.rs | 2 +- crates/bevy_ecs/macros/src/lib.rs | 2 +- crates/bevy_encase_derive/src/lib.rs | 2 +- crates/bevy_gizmos/macros/src/lib.rs | 4 +-- crates/bevy_macro_utils/src/bevy_manifest.rs | 34 ++++++------------- crates/bevy_reflect/derive/src/meta.rs | 2 +- .../derive/src/trait_reflection.rs | 2 +- .../bevy_render/macros/src/as_bind_group.rs | 2 +- .../macros/src/extract_component.rs | 2 +- crates/bevy_render/macros/src/lib.rs | 2 +- crates/bevy_state/macros/src/lib.rs | 2 +- 12 files changed, 22 insertions(+), 36 deletions(-) diff --git a/crates/bevy_asset/macros/src/lib.rs b/crates/bevy_asset/macros/src/lib.rs index 49b3070347ce5..901afd4c48aae 100644 --- a/crates/bevy_asset/macros/src/lib.rs +++ b/crates/bevy_asset/macros/src/lib.rs @@ -8,7 +8,7 @@ use quote::{format_ident, quote}; use syn::{parse_macro_input, Data, DeriveInput, Path}; pub(crate) fn bevy_asset_path() -> Path { - BevyManifest::default().get_path("bevy_asset") + BevyManifest::shared().get_path("bevy_asset") } const DEPENDENCY_ATTRIBUTE: &str = "dependency"; diff --git a/crates/bevy_derive/src/lib.rs b/crates/bevy_derive/src/lib.rs index 0225a7cb5a386..a18e7cbd427c8 100644 --- a/crates/bevy_derive/src/lib.rs +++ b/crates/bevy_derive/src/lib.rs @@ -205,7 +205,7 @@ pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream { #[proc_macro_derive(AppLabel)] pub fn derive_app_label(input: TokenStream) -> TokenStream { let input = syn::parse_macro_input!(input as syn::DeriveInput); - let mut trait_path = BevyManifest::default().get_path("bevy_app"); + let mut trait_path = BevyManifest::shared().get_path("bevy_app"); let mut dyn_eq_path = trait_path.clone(); trait_path.segments.push(format_ident!("AppLabel").into()); dyn_eq_path.segments.push(format_ident!("DynEq").into()); diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index c3a256fef8629..61774882b8973 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -708,7 +708,7 @@ pub fn derive_system_set(input: TokenStream) -> TokenStream { } pub(crate) fn bevy_ecs_path() -> syn::Path { - BevyManifest::default().get_path("bevy_ecs") + BevyManifest::shared().get_path("bevy_ecs") } #[proc_macro_derive(Event)] diff --git a/crates/bevy_encase_derive/src/lib.rs b/crates/bevy_encase_derive/src/lib.rs index b38c657226794..9d924bb9ff5cd 100644 --- a/crates/bevy_encase_derive/src/lib.rs +++ b/crates/bevy_encase_derive/src/lib.rs @@ -13,7 +13,7 @@ use encase_derive_impl::{implement, syn}; const ENCASE: &str = "encase"; fn bevy_encase_path() -> syn::Path { - let bevy_manifest = BevyManifest::default(); + let bevy_manifest = BevyManifest::shared(); bevy_manifest .get_subcrate("render") .map(|bevy_render_path| { diff --git a/crates/bevy_gizmos/macros/src/lib.rs b/crates/bevy_gizmos/macros/src/lib.rs index adce45a4d0e2a..441882d4b01ab 100644 --- a/crates/bevy_gizmos/macros/src/lib.rs +++ b/crates/bevy_gizmos/macros/src/lib.rs @@ -11,8 +11,8 @@ use syn::{parse_macro_input, parse_quote, DeriveInput, Path}; #[proc_macro_derive(GizmoConfigGroup)] pub fn derive_gizmo_config_group(input: TokenStream) -> TokenStream { let mut ast = parse_macro_input!(input as DeriveInput); - let bevy_gizmos_path: Path = BevyManifest::default().get_path("bevy_gizmos"); - let bevy_reflect_path: Path = BevyManifest::default().get_path("bevy_reflect"); + let bevy_gizmos_path: Path = BevyManifest::shared().get_path("bevy_gizmos"); + let bevy_reflect_path: Path = BevyManifest::shared().get_path("bevy_reflect"); ast.generics.make_where_clause().predicates.push( parse_quote! { Self: #bevy_reflect_path::Reflect + #bevy_reflect_path::TypePath + Default}, diff --git a/crates/bevy_macro_utils/src/bevy_manifest.rs b/crates/bevy_macro_utils/src/bevy_manifest.rs index f06b46abacc5a..2185f09252d0f 100644 --- a/crates/bevy_macro_utils/src/bevy_manifest.rs +++ b/crates/bevy_macro_utils/src/bevy_manifest.rs @@ -1,7 +1,7 @@ extern crate proc_macro; use proc_macro::TokenStream; -use std::{env, path::PathBuf}; +use std::{env, path::PathBuf, sync::LazyLock}; use toml_edit::{DocumentMut, Item}; /// The path to the `Cargo.toml` file for the Bevy project. @@ -9,9 +9,13 @@ pub struct BevyManifest { manifest: DocumentMut, } -impl Default for BevyManifest { - fn default() -> Self { - Self { +const BEVY: &str = "bevy"; +const BEVY_INTERNAL: &str = "bevy_internal"; + +impl BevyManifest { + /// Returns a global shared instance of the [`BevyManifest`] struct. + pub fn shared() -> &'static LazyLock { + static LAZY_SELF: LazyLock = LazyLock::new(|| BevyManifest { manifest: env::var_os("CARGO_MANIFEST_DIR") .map(PathBuf::from) .map(|mut path| { @@ -30,13 +34,10 @@ impl Default for BevyManifest { }) }) .expect("CARGO_MANIFEST_DIR is not defined."), - } + }); + &LAZY_SELF } -} -const BEVY: &str = "bevy"; -const BEVY_INTERNAL: &str = "bevy_internal"; -impl BevyManifest { /// Attempt to retrieve the [path](syn::Path) of a particular package in /// the [manifest](BevyManifest) by [name](str). pub fn maybe_get_path(&self, name: &str) -> Option { @@ -73,21 +74,6 @@ impl BevyManifest { .or_else(|| deps_dev.and_then(find_in_deps)) } - /// Returns the path for the crate with the given name. - /// - /// This is a convenience method for constructing a [manifest] and - /// calling the [`get_path`] method. - /// - /// This method should only be used where you just need the path and can't - /// cache the [manifest]. If caching is possible, it's recommended to create - /// the [manifest] yourself and use the [`get_path`] method. - /// - /// [`get_path`]: Self::get_path - /// [manifest]: Self - pub fn get_path_direct(name: &str) -> syn::Path { - Self::default().get_path(name) - } - /// Returns the path for the crate with the given name. pub fn get_path(&self, name: &str) -> syn::Path { self.maybe_get_path(name) diff --git a/crates/bevy_reflect/derive/src/meta.rs b/crates/bevy_reflect/derive/src/meta.rs index c759634f3b2b6..2423dfafb3706 100644 --- a/crates/bevy_reflect/derive/src/meta.rs +++ b/crates/bevy_reflect/derive/src/meta.rs @@ -3,5 +3,5 @@ use syn::Path; /// Returns the correct path for `bevy_reflect`. pub(crate) fn get_bevy_reflect_path() -> Path { - BevyManifest::get_path_direct("bevy_reflect") + BevyManifest::shared().get_path("bevy_reflect") } diff --git a/crates/bevy_reflect/derive/src/trait_reflection.rs b/crates/bevy_reflect/derive/src/trait_reflection.rs index e2c8a4d3d581b..24c452f2f1249 100644 --- a/crates/bevy_reflect/derive/src/trait_reflection.rs +++ b/crates/bevy_reflect/derive/src/trait_reflection.rs @@ -34,7 +34,7 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr let trait_ident = &item_trait.ident; let trait_vis = &item_trait.vis; let reflect_trait_ident = crate::ident::get_reflect_ident(&item_trait.ident.to_string()); - let bevy_reflect_path = BevyManifest::default().get_path("bevy_reflect"); + let bevy_reflect_path = BevyManifest::shared().get_path("bevy_reflect"); let struct_doc = format!( " A type generated by the #[reflect_trait] macro for the `{trait_ident}` trait.\n\n This allows casting from `dyn Reflect` to `dyn {trait_ident}`.", diff --git a/crates/bevy_render/macros/src/as_bind_group.rs b/crates/bevy_render/macros/src/as_bind_group.rs index a31db478fba8f..699b428053ae8 100644 --- a/crates/bevy_render/macros/src/as_bind_group.rs +++ b/crates/bevy_render/macros/src/as_bind_group.rs @@ -40,7 +40,7 @@ enum BindingState<'a> { } pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result { - let manifest = BevyManifest::default(); + let manifest = BevyManifest::shared(); let render_path = manifest.get_path("bevy_render"); let image_path = manifest.get_path("bevy_image"); let asset_path = manifest.get_path("bevy_asset"); diff --git a/crates/bevy_render/macros/src/extract_component.rs b/crates/bevy_render/macros/src/extract_component.rs index 80d1aa57ca5b5..2bfd0e0e11133 100644 --- a/crates/bevy_render/macros/src/extract_component.rs +++ b/crates/bevy_render/macros/src/extract_component.rs @@ -5,7 +5,7 @@ use syn::{parse_macro_input, parse_quote, DeriveInput, Path}; pub fn derive_extract_component(input: TokenStream) -> TokenStream { let mut ast = parse_macro_input!(input as DeriveInput); let bevy_render_path: Path = crate::bevy_render_path(); - let bevy_ecs_path: Path = bevy_macro_utils::BevyManifest::default() + let bevy_ecs_path: Path = bevy_macro_utils::BevyManifest::shared() .maybe_get_path("bevy_ecs") .expect("bevy_ecs should be found in manifest"); diff --git a/crates/bevy_render/macros/src/lib.rs b/crates/bevy_render/macros/src/lib.rs index 6ebcc43cd272d..2d6d9a7864809 100644 --- a/crates/bevy_render/macros/src/lib.rs +++ b/crates/bevy_render/macros/src/lib.rs @@ -12,7 +12,7 @@ use quote::format_ident; use syn::{parse_macro_input, DeriveInput}; pub(crate) fn bevy_render_path() -> syn::Path { - BevyManifest::default() + BevyManifest::shared() .maybe_get_path("bevy_render") // NOTE: If the derivation is within bevy_render, then we need to return 'crate' .unwrap_or_else(|| BevyManifest::parse_str("crate")) diff --git a/crates/bevy_state/macros/src/lib.rs b/crates/bevy_state/macros/src/lib.rs index 8e3300a57b043..873d358ef5e66 100644 --- a/crates/bevy_state/macros/src/lib.rs +++ b/crates/bevy_state/macros/src/lib.rs @@ -20,5 +20,5 @@ pub fn derive_substates(input: TokenStream) -> TokenStream { } pub(crate) fn bevy_state_path() -> syn::Path { - BevyManifest::default().get_path("bevy_state") + BevyManifest::shared().get_path("bevy_state") }