Use one BevyManifest instance in proc macros (#16766)

# 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 <mockersf@gmail.com>
This commit is contained in:
raldone01 2024-12-15 16:00:05 +01:00 committed by GitHub
parent 73a66d6bd8
commit 760d0a3100
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 22 additions and 36 deletions

View File

@ -8,7 +8,7 @@ use quote::{format_ident, quote};
use syn::{parse_macro_input, Data, DeriveInput, Path}; use syn::{parse_macro_input, Data, DeriveInput, Path};
pub(crate) fn bevy_asset_path() -> 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"; const DEPENDENCY_ATTRIBUTE: &str = "dependency";

View File

@ -205,7 +205,7 @@ pub fn derive_enum_variant_meta(input: TokenStream) -> TokenStream {
#[proc_macro_derive(AppLabel)] #[proc_macro_derive(AppLabel)]
pub fn derive_app_label(input: TokenStream) -> TokenStream { pub fn derive_app_label(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput); 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(); let mut dyn_eq_path = trait_path.clone();
trait_path.segments.push(format_ident!("AppLabel").into()); trait_path.segments.push(format_ident!("AppLabel").into());
dyn_eq_path.segments.push(format_ident!("DynEq").into()); dyn_eq_path.segments.push(format_ident!("DynEq").into());

View File

@ -708,7 +708,7 @@ pub fn derive_system_set(input: TokenStream) -> TokenStream {
} }
pub(crate) fn bevy_ecs_path() -> syn::Path { pub(crate) fn bevy_ecs_path() -> syn::Path {
BevyManifest::default().get_path("bevy_ecs") BevyManifest::shared().get_path("bevy_ecs")
} }
#[proc_macro_derive(Event)] #[proc_macro_derive(Event)]

View File

@ -13,7 +13,7 @@ use encase_derive_impl::{implement, syn};
const ENCASE: &str = "encase"; const ENCASE: &str = "encase";
fn bevy_encase_path() -> syn::Path { fn bevy_encase_path() -> syn::Path {
let bevy_manifest = BevyManifest::default(); let bevy_manifest = BevyManifest::shared();
bevy_manifest bevy_manifest
.get_subcrate("render") .get_subcrate("render")
.map(|bevy_render_path| { .map(|bevy_render_path| {

View File

@ -11,8 +11,8 @@ use syn::{parse_macro_input, parse_quote, DeriveInput, Path};
#[proc_macro_derive(GizmoConfigGroup)] #[proc_macro_derive(GizmoConfigGroup)]
pub fn derive_gizmo_config_group(input: TokenStream) -> TokenStream { pub fn derive_gizmo_config_group(input: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(input as DeriveInput); let mut ast = parse_macro_input!(input as DeriveInput);
let bevy_gizmos_path: Path = BevyManifest::default().get_path("bevy_gizmos"); let bevy_gizmos_path: Path = BevyManifest::shared().get_path("bevy_gizmos");
let bevy_reflect_path: Path = BevyManifest::default().get_path("bevy_reflect"); let bevy_reflect_path: Path = BevyManifest::shared().get_path("bevy_reflect");
ast.generics.make_where_clause().predicates.push( ast.generics.make_where_clause().predicates.push(
parse_quote! { Self: #bevy_reflect_path::Reflect + #bevy_reflect_path::TypePath + Default}, parse_quote! { Self: #bevy_reflect_path::Reflect + #bevy_reflect_path::TypePath + Default},

View File

@ -1,7 +1,7 @@
extern crate proc_macro; extern crate proc_macro;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use std::{env, path::PathBuf}; use std::{env, path::PathBuf, sync::LazyLock};
use toml_edit::{DocumentMut, Item}; use toml_edit::{DocumentMut, Item};
/// The path to the `Cargo.toml` file for the Bevy project. /// The path to the `Cargo.toml` file for the Bevy project.
@ -9,9 +9,13 @@ pub struct BevyManifest {
manifest: DocumentMut, manifest: DocumentMut,
} }
impl Default for BevyManifest { const BEVY: &str = "bevy";
fn default() -> Self { const BEVY_INTERNAL: &str = "bevy_internal";
Self {
impl BevyManifest {
/// Returns a global shared instance of the [`BevyManifest`] struct.
pub fn shared() -> &'static LazyLock<Self> {
static LAZY_SELF: LazyLock<BevyManifest> = LazyLock::new(|| BevyManifest {
manifest: env::var_os("CARGO_MANIFEST_DIR") manifest: env::var_os("CARGO_MANIFEST_DIR")
.map(PathBuf::from) .map(PathBuf::from)
.map(|mut path| { .map(|mut path| {
@ -30,13 +34,10 @@ impl Default for BevyManifest {
}) })
}) })
.expect("CARGO_MANIFEST_DIR is not defined."), .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 /// Attempt to retrieve the [path](syn::Path) of a particular package in
/// the [manifest](BevyManifest) by [name](str). /// the [manifest](BevyManifest) by [name](str).
pub fn maybe_get_path(&self, name: &str) -> Option<syn::Path> { pub fn maybe_get_path(&self, name: &str) -> Option<syn::Path> {
@ -73,21 +74,6 @@ impl BevyManifest {
.or_else(|| deps_dev.and_then(find_in_deps)) .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. /// Returns the path for the crate with the given name.
pub fn get_path(&self, name: &str) -> syn::Path { pub fn get_path(&self, name: &str) -> syn::Path {
self.maybe_get_path(name) self.maybe_get_path(name)

View File

@ -3,5 +3,5 @@ use syn::Path;
/// Returns the correct path for `bevy_reflect`. /// Returns the correct path for `bevy_reflect`.
pub(crate) fn get_bevy_reflect_path() -> Path { pub(crate) fn get_bevy_reflect_path() -> Path {
BevyManifest::get_path_direct("bevy_reflect") BevyManifest::shared().get_path("bevy_reflect")
} }

View File

@ -34,7 +34,7 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr
let trait_ident = &item_trait.ident; let trait_ident = &item_trait.ident;
let trait_vis = &item_trait.vis; let trait_vis = &item_trait.vis;
let reflect_trait_ident = crate::ident::get_reflect_ident(&item_trait.ident.to_string()); 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!( 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}`.", " 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}`.",

View File

@ -40,7 +40,7 @@ enum BindingState<'a> {
} }
pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> { pub fn derive_as_bind_group(ast: syn::DeriveInput) -> Result<TokenStream> {
let manifest = BevyManifest::default(); let manifest = BevyManifest::shared();
let render_path = manifest.get_path("bevy_render"); let render_path = manifest.get_path("bevy_render");
let image_path = manifest.get_path("bevy_image"); let image_path = manifest.get_path("bevy_image");
let asset_path = manifest.get_path("bevy_asset"); let asset_path = manifest.get_path("bevy_asset");

View File

@ -5,7 +5,7 @@ use syn::{parse_macro_input, parse_quote, DeriveInput, Path};
pub fn derive_extract_component(input: TokenStream) -> TokenStream { pub fn derive_extract_component(input: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(input as DeriveInput); let mut ast = parse_macro_input!(input as DeriveInput);
let bevy_render_path: Path = crate::bevy_render_path(); 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") .maybe_get_path("bevy_ecs")
.expect("bevy_ecs should be found in manifest"); .expect("bevy_ecs should be found in manifest");

View File

@ -12,7 +12,7 @@ use quote::format_ident;
use syn::{parse_macro_input, DeriveInput}; use syn::{parse_macro_input, DeriveInput};
pub(crate) fn bevy_render_path() -> syn::Path { pub(crate) fn bevy_render_path() -> syn::Path {
BevyManifest::default() BevyManifest::shared()
.maybe_get_path("bevy_render") .maybe_get_path("bevy_render")
// NOTE: If the derivation is within bevy_render, then we need to return 'crate' // NOTE: If the derivation is within bevy_render, then we need to return 'crate'
.unwrap_or_else(|| BevyManifest::parse_str("crate")) .unwrap_or_else(|| BevyManifest::parse_str("crate"))

View File

@ -20,5 +20,5 @@ pub fn derive_substates(input: TokenStream) -> TokenStream {
} }
pub(crate) fn bevy_state_path() -> syn::Path { pub(crate) fn bevy_state_path() -> syn::Path {
BevyManifest::default().get_path("bevy_state") BevyManifest::shared().get_path("bevy_state")
} }