From 3cbf37104e2ab82084d5c8dc52a41cc53482e954 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 20 Oct 2025 16:30:43 -0400 Subject: [PATCH 001/162] refactor: prepare new structures --- .../src/macro_api/attributes/mod.rs | 71 +++++++- .../src/macro_api/composed.rs | 153 ++++++++++++++++++ .../src/macro_api/context.rs | 5 + .../src/macro_api/input_item.rs | 75 +++++++++ .../src/macro_api/macro_paths.rs | 18 +++ .../src/macro_api/mixins/generics/mod.rs | 8 + .../src/macro_api/mixins/generics/with.rs | 39 +++++ .../src/macro_api/mixins/generics/without.rs | 57 +++++++ .../src/macro_api/mixins/mod.rs | 29 ++++ .../src/macro_api/mixins/nothing.rs | 20 +++ .../src/macro_api/mixins/with_plugin.rs | 27 ++++ .../src/macro_api/mod.rs | 7 + .../src/macro_api/q.rs | 27 ++++ .../src/macro_api/qq.rs | 51 ++++++ 14 files changed, 585 insertions(+), 2 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/composed.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/context.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/without.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/mixins/nothing.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/q.rs create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/qq.rs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index b95700ec..cc52410a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -1,12 +1,18 @@ use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; +use crate::macro_api::composed::Composed; +use crate::macro_api::context::Context; +use crate::macro_api::input_item::InputItem; +use crate::macro_api::mixins::generics::HasGenerics; +use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::analysis::item::IdentFromItemResult; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; -use proc_macro2::Ident; +use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use std::hash::Hash; use syn::parse::Parse; -use syn::{Item, parse_quote}; +use syn::spanned::Spanned; +use syn::{Item, parse_quote, parse2}; mod actions; mod auto_plugin; @@ -59,3 +65,64 @@ pub trait ItemAttributeArgs: } fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_>; } + +pub struct ItemAttribute { + pub args: T, + pub context: Context, + pub input_item: InputItem, + pub target: syn::Ident, +} + +impl ItemAttribute +where + T: Parse, +{ + pub fn from_attr_input( + attr: TokenStream, + input: TokenStream, + context: Context, + ) -> syn::Result { + let mut input_item = InputItem::new(input); + let Some(target) = input_item.get_ident()?.cloned() else { + return Err(syn::Error::new( + input_item.span(), + "Unable to resolve target ident", + )); + }; + Ok(Self { + args: parse2::(attr)?, + context, + input_item, + target, + }) + } +} + +impl ItemAttribute> { + pub fn plugin(&self) -> &syn::Path { + self.args.plugin() + } +} + +impl ItemAttribute> +where + M2: HasGenerics, +{ + pub fn concrete_paths(&self) -> Vec { + self.args.concrete_paths(&self.target.clone().into()) + } +} + +impl ItemAttribute { + fn convert_into(value: ItemAttribute) -> ItemAttribute + where + T2: From, + { + ItemAttribute { + args: T2::from(value.args), + context: value.context, + input_item: value.input_item, + target: value.target, + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs new file mode 100644 index 00000000..b83e8e92 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -0,0 +1,153 @@ +use crate::macro_api::context::Context; +use crate::macro_api::macro_paths::MacroPathProvider; +use crate::macro_api::mixins::generics::HasGenerics; +use crate::macro_api::mixins::nothing::Nothing; +use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::macro_api::mixins::{HasKeys, Mixin}; +use crate::syntax::ast::type_list::TypeList; +use darling::FromMeta; +use darling::ast::NestedMeta; +use proc_macro2::TokenStream; +use quote::ToTokens; +use std::collections::HashSet; +use syn::parse::{Parse, ParseStream}; +use syn::parse_quote; +use syn::punctuated::Punctuated; + +#[derive(Debug)] +pub struct Composed { + pub core: C, + // todo: rename to plugin? + pub m1: M1, + // todo: rename to generics? + pub m2: M2, +} + +impl FromMeta for Composed +where + C: FromMeta, + M1: Mixin, + M2: Mixin, +{ + fn from_list(items: &[NestedMeta]) -> darling::Result { + let keys1: HashSet<&str> = M1::keys().iter().copied().collect(); + let keys2: HashSet<&str> = M2::keys().iter().copied().collect(); + + let mut bucket1 = Vec::::new(); + let mut bucket2 = Vec::::new(); + let mut bucket_core = Vec::::new(); + + for nm in items { + let key_opt = match &nm { + NestedMeta::Meta(syn::Meta::Path(p)) => { + p.segments.last().map(|s| s.ident.to_string()) + } + NestedMeta::Meta(syn::Meta::NameValue(nv)) => { + nv.path.segments.last().map(|s| s.ident.to_string()) + } + NestedMeta::Meta(syn::Meta::List(ml)) => { + ml.path.segments.last().map(|s| s.ident.to_string()) + } + NestedMeta::Lit(_) => None, + }; + + let routed = if let Some(ref k) = key_opt { + if keys1.contains(k.as_str()) { + bucket1.push(nm.clone()); + true + } else if keys2.contains(k.as_str()) { + bucket2.push(nm.clone()); + true + } else { + false + } + } else { + false + }; + + if !routed { + bucket_core.push(nm.clone()); + } + } + + // Parse each bucket + let core = C::from_list(&bucket_core)?; + let m1 = M1::from_list(&bucket1)?; + let m2 = M2::from_list(&bucket2)?; + + Ok(Self { core, m1, m2 }) + } +} + +impl Parse for Composed +where + C: FromMeta, + M1: Mixin, + M2: Mixin, +{ + fn parse(input: ParseStream) -> syn::Result { + // Parse `#[attr()]`'s inner as: key = value, key(...), literal, ... + let list: Punctuated = Punctuated::parse_terminated(input)?; + let items: Vec = list.into_iter().collect(); + Composed::::from_list(&items) + .map_err(|e| syn::Error::new(e.span(), e.to_string())) + } +} + +impl Composed { + pub fn args(&self) -> &C { + &self.core + } +} + +impl Composed { + pub fn plugin(&self) -> &syn::Path { + &self.m1.plugin + } +} + +impl Composed +where + M2: HasGenerics, +{ + pub fn generics(&self) -> &[TypeList] { + self.m2.generics() + } + pub fn concrete_paths(&self, target: &syn::Path) -> Vec { + if self.m2.generics().is_empty() { + vec![target.clone()] + } else { + self.m2 + .generics() + .iter() + .map(|g| parse_quote!(#target :: < #g >)) + .collect() + } + } +} + +impl Composed +where + M1: ToTokens, + M2: ToTokens, +{ + pub fn extra_args(&self) -> Vec { + let m1_tokens = self.m1.to_token_stream(); + let m2_tokens = self.m2.to_token_stream(); + match (m1_tokens.is_empty(), m2_tokens.is_empty()) { + (true, true) => vec![], + (false, true) => vec![m1_tokens], + (true, false) => vec![m2_tokens], + (false, false) => vec![m1_tokens, m2_tokens], + } + } +} + +impl MacroPathProvider for Composed +where + C: MacroPathProvider, +{ + fn macro_path(context: &Context) -> &syn::Path { + C::macro_path(context) + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context.rs new file mode 100644 index 00000000..5296ab43 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/context.rs @@ -0,0 +1,5 @@ +use crate::macro_api::macro_paths::MacroPaths; + +pub struct Context { + pub macros: MacroPaths, +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs new file mode 100644 index 00000000..43244377 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs @@ -0,0 +1,75 @@ +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; +use syn::parse2; + +pub enum InputItem { + Tokens(TokenStream), + Ast(Box), +} + +impl InputItem { + pub fn new(item_ts: TokenStream) -> Self { + Self::Tokens(item_ts) + } + fn _upgrade(&mut self) -> syn::Result<()> { + if let Self::Tokens(ts) = &self { + let parsed: syn::Item = parse2(ts.clone())?; + *self = Self::Ast(Box::new(parsed)); + } + Ok(()) + } + fn ensure_ast(&mut self) -> syn::Result<&syn::Item> { + self._upgrade()?; + Ok(match &*self { + Self::Ast(ast) => ast.as_ref(), + _ => unreachable!(), + }) + } + pub fn ensure_ast_mut(&mut self) -> syn::Result<&mut syn::Item> { + self._upgrade()?; + Ok(match &mut *self { + Self::Ast(ast) => ast.as_mut(), + _ => unreachable!(), + }) + } + pub fn get_ident(&mut self) -> syn::Result> { + use syn::Item; + let item = self.ensure_ast()?; + Ok(match item { + Item::Const(item) => Some(&item.ident), + Item::Enum(item) => Some(&item.ident), + Item::ExternCrate(item) => Some(&item.ident), + Item::Fn(item) => Some(&item.sig.ident), + Item::ForeignMod(_) => None, + Item::Impl(_) => None, + Item::Macro(item) => item.ident.as_ref(), + Item::Mod(item) => Some(&item.ident), + Item::Static(item) => Some(&item.ident), + Item::Struct(item) => Some(&item.ident), + Item::Trait(item) => Some(&item.ident), + Item::TraitAlias(item) => Some(&item.ident), + Item::Type(item) => Some(&item.ident), + Item::Union(item) => Some(&item.ident), + // TODO: implement + Item::Use(_) => None, + Item::Verbatim(item) => None, + _ => None, + }) + } + pub fn map_ast(&mut self, f: F) -> syn::Result<()> + where + F: FnOnce(&mut syn::Item) -> syn::Result<()>, + { + let item = self.ensure_ast_mut()?; + f(item) + } +} + +impl ToTokens for InputItem { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(match self { + InputItem::Tokens(ts) => ts.clone(), + InputItem::Ast(ast) => quote! { #ast }, + }) + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs new file mode 100644 index 00000000..17cd58c3 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs @@ -0,0 +1,18 @@ +use crate::macro_api::attributes::prelude::AddSystemArgs; +use crate::macro_api::context::Context; + +pub struct MacroPaths { + /// resolved absolute path to `auto_add_system` + pub emit_add_system_macro: syn::Path, + // .. others +} + +pub trait MacroPathProvider { + fn macro_path(context: &Context) -> &syn::Path; +} + +impl MacroPathProvider for AddSystemArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_add_system_macro + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs new file mode 100644 index 00000000..2b664ea0 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs @@ -0,0 +1,8 @@ +use crate::syntax::ast::type_list::TypeList; + +pub mod with; +pub mod without; + +pub trait HasGenerics { + fn generics(&self) -> &[TypeList]; +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with.rs new file mode 100644 index 00000000..7c4c8014 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with.rs @@ -0,0 +1,39 @@ +use crate::macro_api::mixins::HasKeys; +use crate::macro_api::mixins::generics::HasGenerics; +use crate::syntax::ast::type_list::TypeList; +use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; + +#[derive(Debug, Clone, Default, FromMeta)] +#[darling(derive_syn_parse)] +pub struct WithGenerics { + #[darling(multiple, default, rename = "generics")] + pub generics: Vec, +} + +impl WithGenerics { + pub const KEYS: &'static [&'static str] = &["generics"]; +} + +impl HasKeys for WithGenerics { + fn keys() -> &'static [&'static str] { + WithGenerics::KEYS + } +} + +impl HasGenerics for WithGenerics { + fn generics(&self) -> &[TypeList] { + &self.generics + } +} + +impl ToTokens for WithGenerics { + fn to_tokens(&self, tokens: &mut TokenStream) { + if !self.generics.is_empty() { + for g in &self.generics { + tokens.extend(quote! { generics(#g) }); + } + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/without.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/without.rs new file mode 100644 index 00000000..f6cfd283 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/without.rs @@ -0,0 +1,57 @@ +use crate::macro_api::mixins::HasKeys; +use crate::macro_api::mixins::generics::HasGenerics; +use crate::syntax::ast::type_list::TypeList; +use darling::FromMeta; +use darling::ast::NestedMeta; +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::parse::{Parse, ParseStream}; +use syn::spanned::Spanned; + +#[derive(Debug, Clone, Default)] +pub struct WithoutGenerics {} + +impl WithoutGenerics { + pub const KEYS: &'static [&'static str] = &["generics"]; +} + +impl HasKeys for WithoutGenerics { + fn keys() -> &'static [&'static str] { + WithoutGenerics::KEYS + } +} + +impl HasGenerics for WithoutGenerics { + fn generics(&self) -> &[TypeList] { + &[] + } +} + +impl ToTokens for WithoutGenerics { + fn to_tokens(&self, _tokens: &mut TokenStream) {} +} + +impl FromMeta for WithoutGenerics { + fn from_list(items: &[NestedMeta]) -> darling::Result { + if !items.is_empty() { + let errors = items + .iter() + .map(|item| { + darling::Error::unsupported_shape("generics are not supported") + .with_span(&item.span()) + }) + .collect(); + return Err(darling::Error::multiple(errors)); + } + Ok(Self::default()) + } +} + +impl Parse for WithoutGenerics { + fn parse(input: ParseStream) -> syn::Result { + if !input.is_empty() { + return Err(input.error("generics are not supported")); + } + Ok(Self::default()) + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs new file mode 100644 index 00000000..473bd4cb --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs @@ -0,0 +1,29 @@ +use darling::ast::NestedMeta; + +pub mod generics; +pub mod nothing; +pub mod with_plugin; + +pub trait HasKeys { + fn keys() -> &'static [&'static str]; +} + +pub trait Mixin: Sized { + /// Keys this mixin recognizes (top-level names). + fn keys() -> &'static [&'static str]; + + /// Parse from just the metas that were routed to this mixin. + fn from_list(items: &[NestedMeta]) -> darling::Result; +} + +impl Mixin for T +where + T: darling::FromMeta + HasKeys, +{ + fn keys() -> &'static [&'static str] { + ::keys() + } + fn from_list(items: &[NestedMeta]) -> darling::Result { + ::from_list(items) + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/nothing.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/nothing.rs new file mode 100644 index 00000000..a173e1a8 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/nothing.rs @@ -0,0 +1,20 @@ +use crate::macro_api::mixins::HasKeys; +use crate::macro_api::mixins::generics::HasGenerics; +use crate::syntax::ast::type_list::TypeList; +use darling::FromMeta; + +#[derive(Debug, Clone, FromMeta)] +#[darling(derive_syn_parse)] +pub struct Nothing {} + +impl HasGenerics for Nothing { + fn generics(&self) -> &[TypeList] { + &[] + } +} + +impl HasKeys for Nothing { + fn keys() -> &'static [&'static str] { + &[] + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs new file mode 100644 index 00000000..d1226a41 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs @@ -0,0 +1,27 @@ +use crate::macro_api::mixins::HasKeys; +use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; + +#[derive(Debug, Clone, FromMeta)] +#[darling(derive_syn_parse)] +pub struct WithPlugin { + #[darling(rename = "plugin")] + pub plugin: syn::Path, +} + +impl WithPlugin { + pub const KEYS: &'static [&'static str] = &["plugin"]; +} + +impl ToTokens for WithPlugin { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(quote! { plugin = #self.plugin }); + } +} + +impl HasKeys for WithPlugin { + fn keys() -> &'static [&'static str] { + WithPlugin::KEYS + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index f9acb7b7..e91c1375 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -1,4 +1,11 @@ pub(crate) mod attributes; +pub(crate) mod composed; +pub(crate) mod context; pub mod derives; +pub(crate) mod input_item; +pub(crate) mod macro_paths; +pub(super) mod mixins; +pub(crate) mod q; +pub(crate) mod qq; pub mod schedule_config; pub mod with_plugin; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs new file mode 100644 index 00000000..7c3f7191 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -0,0 +1,27 @@ +use crate::macro_api::attributes::ItemAttribute; +use crate::macro_api::attributes::prelude::AddSystemArgs; +use crate::macro_api::composed::Composed; +use crate::macro_api::context::Context; +use crate::macro_api::input_item::InputItem; +use crate::macro_api::mixins::generics::with::WithGenerics; +use crate::macro_api::mixins::with_plugin::WithPlugin; +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; + +/// for codegen attaching to bevy app +struct Q<'a, T> { + args: &'a T, + context: &'a Context, + input_item: &'a InputItem, +} + +impl ToTokens for Q<'_, ItemAttribute>> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let schedule = &self.args.args.core.schedule_config.schedule; + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.add_system(#schedule, #concrete_path); + }}); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs new file mode 100644 index 00000000..d2c1c8ed --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -0,0 +1,51 @@ +use crate::macro_api::attributes::ItemAttribute; +use crate::macro_api::attributes::prelude::AddSystemArgs; +use crate::macro_api::composed::Composed; +use crate::macro_api::context::Context; +use crate::macro_api::input_item::InputItem; +use crate::macro_api::macro_paths::MacroPathProvider; +use crate::macro_api::mixins::generics::with::WithGenerics; +use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::syntax::extensions::item::ItemAttrsExt; +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; +use syn::parse_quote; +use syn::spanned::Spanned; + +/// for codegen re-emitting macro args +struct QQ<'a, T> { + args: &'a T, + context: &'a Context, + input_item: &'a mut InputItem, +} + +impl QQ<'_, T> +where + T: MacroPathProvider, + Self: ToTokens, +{ + fn inject_attribute_macro(&mut self) -> syn::Result<()> { + let args = self.to_token_stream(); + self.input_item.map_ast(|item| { + let macro_path = T::macro_path(self.context); + // insert attribute tokens + let mut attrs = item + .take_attrs() + .map_err(|err| syn::Error::new(item.span(), err))?; + attrs.insert(0, parse_quote!(#[#macro_path(#args)])); + item.put_attrs(attrs).unwrap(); // infallible + Ok(()) + }) + } +} + +impl ToTokens for QQ<'_, ItemAttribute>> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let schedule = &self.args.args.core.schedule_config.schedule; + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + schedule = #schedule, + }); + } +} From d2a1ad63effa06c82c2ce964c55dafed253a0061 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 20 Oct 2025 16:39:17 -0400 Subject: [PATCH 002/162] refactor: rename `Composed` fields and type parameters for improved clarity --- .../src/macro_api/composed.rs | 106 +++++++++--------- .../src/macro_api/q.rs | 2 +- .../src/macro_api/qq.rs | 2 +- 3 files changed, 56 insertions(+), 54 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index b83e8e92..7ad7d0cd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -1,9 +1,9 @@ use crate::macro_api::context::Context; use crate::macro_api::macro_paths::MacroPathProvider; +use crate::macro_api::mixins::Mixin; use crate::macro_api::mixins::generics::HasGenerics; use crate::macro_api::mixins::nothing::Nothing; use crate::macro_api::mixins::with_plugin::WithPlugin; -use crate::macro_api::mixins::{HasKeys, Mixin}; use crate::syntax::ast::type_list::TypeList; use darling::FromMeta; use darling::ast::NestedMeta; @@ -15,27 +15,25 @@ use syn::parse_quote; use syn::punctuated::Punctuated; #[derive(Debug)] -pub struct Composed { - pub core: C, - // todo: rename to plugin? - pub m1: M1, - // todo: rename to generics? - pub m2: M2, +pub struct Composed { + pub base: CBase, + pub plugin: MPlugin, + pub generics: MGenerics, } -impl FromMeta for Composed +impl FromMeta for Composed where - C: FromMeta, - M1: Mixin, - M2: Mixin, + CBase: FromMeta, + MPlugin: Mixin, + MGenerics: Mixin, { fn from_list(items: &[NestedMeta]) -> darling::Result { - let keys1: HashSet<&str> = M1::keys().iter().copied().collect(); - let keys2: HashSet<&str> = M2::keys().iter().copied().collect(); + let plugin_keys: HashSet<&str> = MPlugin::keys().iter().copied().collect(); + let generics_keys: HashSet<&str> = MGenerics::keys().iter().copied().collect(); - let mut bucket1 = Vec::::new(); - let mut bucket2 = Vec::::new(); - let mut bucket_core = Vec::::new(); + let mut plugin_bucket = Vec::::new(); + let mut generics_bucket = Vec::::new(); + let mut base_bucket = Vec::::new(); for nm in items { let key_opt = match &nm { @@ -52,11 +50,11 @@ where }; let routed = if let Some(ref k) = key_opt { - if keys1.contains(k.as_str()) { - bucket1.push(nm.clone()); + if plugin_keys.contains(k.as_str()) { + plugin_bucket.push(nm.clone()); true - } else if keys2.contains(k.as_str()) { - bucket2.push(nm.clone()); + } else if generics_keys.contains(k.as_str()) { + generics_bucket.push(nm.clone()); true } else { false @@ -66,58 +64,62 @@ where }; if !routed { - bucket_core.push(nm.clone()); + base_bucket.push(nm.clone()); } } // Parse each bucket - let core = C::from_list(&bucket_core)?; - let m1 = M1::from_list(&bucket1)?; - let m2 = M2::from_list(&bucket2)?; + let base = CBase::from_list(&base_bucket)?; + let plugin = MPlugin::from_list(&plugin_bucket)?; + let generics = MGenerics::from_list(&generics_bucket)?; - Ok(Self { core, m1, m2 }) + Ok(Self { + base, + plugin, + generics, + }) } } -impl Parse for Composed +impl Parse for Composed where - C: FromMeta, - M1: Mixin, - M2: Mixin, + CBase: FromMeta, + MPlugin: Mixin, + MGenerics: Mixin, { fn parse(input: ParseStream) -> syn::Result { // Parse `#[attr()]`'s inner as: key = value, key(...), literal, ... let list: Punctuated = Punctuated::parse_terminated(input)?; let items: Vec = list.into_iter().collect(); - Composed::::from_list(&items) + Composed::::from_list(&items) .map_err(|e| syn::Error::new(e.span(), e.to_string())) } } -impl Composed { - pub fn args(&self) -> &C { - &self.core +impl Composed { + pub fn args(&self) -> &CBase { + &self.base } } -impl Composed { +impl Composed { pub fn plugin(&self) -> &syn::Path { - &self.m1.plugin + &self.plugin.plugin } } -impl Composed +impl Composed where - M2: HasGenerics, + MGenerics: HasGenerics, { pub fn generics(&self) -> &[TypeList] { - self.m2.generics() + self.generics.generics() } pub fn concrete_paths(&self, target: &syn::Path) -> Vec { - if self.m2.generics().is_empty() { + if self.generics.generics().is_empty() { vec![target.clone()] } else { - self.m2 + self.generics .generics() .iter() .map(|g| parse_quote!(#target :: < #g >)) @@ -126,28 +128,28 @@ where } } -impl Composed +impl Composed where - M1: ToTokens, - M2: ToTokens, + MPlugin: ToTokens, + MGenerics: ToTokens, { pub fn extra_args(&self) -> Vec { - let m1_tokens = self.m1.to_token_stream(); - let m2_tokens = self.m2.to_token_stream(); - match (m1_tokens.is_empty(), m2_tokens.is_empty()) { + let plugin_tokens = self.plugin.to_token_stream(); + let generics_tokens = self.generics.to_token_stream(); + match (plugin_tokens.is_empty(), generics_tokens.is_empty()) { (true, true) => vec![], - (false, true) => vec![m1_tokens], - (true, false) => vec![m2_tokens], - (false, false) => vec![m1_tokens, m2_tokens], + (false, true) => vec![plugin_tokens], + (true, false) => vec![generics_tokens], + (false, false) => vec![plugin_tokens, generics_tokens], } } } -impl MacroPathProvider for Composed +impl MacroPathProvider for Composed where - C: MacroPathProvider, + CBase: MacroPathProvider, { fn macro_path(context: &Context) -> &syn::Path { - C::macro_path(context) + CBase::macro_path(context) } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 7c3f7191..21e00445 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -17,7 +17,7 @@ struct Q<'a, T> { impl ToTokens for Q<'_, ItemAttribute>> { fn to_tokens(&self, tokens: &mut TokenStream) { - let schedule = &self.args.args.core.schedule_config.schedule; + let schedule = &self.args.args.base.schedule_config.schedule; for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { app.add_system(#schedule, #concrete_path); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index d2c1c8ed..69b725c9 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -41,7 +41,7 @@ where impl ToTokens for QQ<'_, ItemAttribute>> { fn to_tokens(&self, tokens: &mut TokenStream) { - let schedule = &self.args.args.core.schedule_config.schedule; + let schedule = &self.args.args.base.schedule_config.schedule; let extra_args = self.args.args.extra_args(); tokens.extend(quote! { #(#extra_args),* From 441c1d79ada335161dc0e93f558085829e7eac24 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 20 Oct 2025 16:53:08 -0400 Subject: [PATCH 003/162] refactor: rename generics mixins and add a none variant --- .../src/macro_api/mixins/generics/mod.rs | 5 ++- .../mixins/generics/{without.rs => none.rs} | 16 ++++---- .../macro_api/mixins/generics/with_many.rs | 39 +++++++++++++++++++ .../generics/{with.rs => with_single.rs} | 12 +++--- .../src/macro_api/q.rs | 6 ++- .../src/macro_api/qq.rs | 6 ++- 6 files changed, 64 insertions(+), 20 deletions(-) rename crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/{without.rs => none.rs} (82%) create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs rename crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/{with.rs => with_single.rs} (77%) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs index 2b664ea0..075ccf8a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs @@ -1,7 +1,8 @@ use crate::syntax::ast::type_list::TypeList; -pub mod with; -pub mod without; +pub mod none; +pub mod with_many; +pub mod with_single; pub trait HasGenerics { fn generics(&self) -> &[TypeList]; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/without.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs similarity index 82% rename from crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/without.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs index f6cfd283..690f9063 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/without.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs @@ -9,29 +9,29 @@ use syn::parse::{Parse, ParseStream}; use syn::spanned::Spanned; #[derive(Debug, Clone, Default)] -pub struct WithoutGenerics {} +pub struct WithNoGenerics {} -impl WithoutGenerics { +impl WithNoGenerics { pub const KEYS: &'static [&'static str] = &["generics"]; } -impl HasKeys for WithoutGenerics { +impl HasKeys for WithNoGenerics { fn keys() -> &'static [&'static str] { - WithoutGenerics::KEYS + WithNoGenerics::KEYS } } -impl HasGenerics for WithoutGenerics { +impl HasGenerics for WithNoGenerics { fn generics(&self) -> &[TypeList] { &[] } } -impl ToTokens for WithoutGenerics { +impl ToTokens for WithNoGenerics { fn to_tokens(&self, _tokens: &mut TokenStream) {} } -impl FromMeta for WithoutGenerics { +impl FromMeta for WithNoGenerics { fn from_list(items: &[NestedMeta]) -> darling::Result { if !items.is_empty() { let errors = items @@ -47,7 +47,7 @@ impl FromMeta for WithoutGenerics { } } -impl Parse for WithoutGenerics { +impl Parse for WithNoGenerics { fn parse(input: ParseStream) -> syn::Result { if !input.is_empty() { return Err(input.error("generics are not supported")); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs new file mode 100644 index 00000000..d156014f --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs @@ -0,0 +1,39 @@ +use crate::macro_api::mixins::HasKeys; +use crate::macro_api::mixins::generics::HasGenerics; +use crate::syntax::ast::type_list::TypeList; +use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; + +#[derive(Debug, Clone, Default, FromMeta)] +#[darling(derive_syn_parse)] +pub struct WithZeroOrManyGenerics { + #[darling(multiple, default, rename = "generics")] + pub generics: Vec, +} + +impl WithZeroOrManyGenerics { + pub const KEYS: &'static [&'static str] = &["generics"]; +} + +impl HasKeys for WithZeroOrManyGenerics { + fn keys() -> &'static [&'static str] { + WithZeroOrManyGenerics::KEYS + } +} + +impl HasGenerics for WithZeroOrManyGenerics { + fn generics(&self) -> &[TypeList] { + &self.generics + } +} + +impl ToTokens for WithZeroOrManyGenerics { + fn to_tokens(&self, tokens: &mut TokenStream) { + if !self.generics.is_empty() { + for g in &self.generics { + tokens.extend(quote! { generics(#g) }); + } + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs similarity index 77% rename from crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index 7c4c8014..e1da9bbe 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -7,28 +7,28 @@ use quote::{ToTokens, quote}; #[derive(Debug, Clone, Default, FromMeta)] #[darling(derive_syn_parse)] -pub struct WithGenerics { +pub struct WithZeroOrOneGenerics { #[darling(multiple, default, rename = "generics")] pub generics: Vec, } -impl WithGenerics { +impl WithZeroOrOneGenerics { pub const KEYS: &'static [&'static str] = &["generics"]; } -impl HasKeys for WithGenerics { +impl HasKeys for WithZeroOrOneGenerics { fn keys() -> &'static [&'static str] { - WithGenerics::KEYS + WithZeroOrOneGenerics::KEYS } } -impl HasGenerics for WithGenerics { +impl HasGenerics for WithZeroOrOneGenerics { fn generics(&self) -> &[TypeList] { &self.generics } } -impl ToTokens for WithGenerics { +impl ToTokens for WithZeroOrOneGenerics { fn to_tokens(&self, tokens: &mut TokenStream) { if !self.generics.is_empty() { for g in &self.generics { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 21e00445..dbb07593 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -3,7 +3,7 @@ use crate::macro_api::attributes::prelude::AddSystemArgs; use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; -use crate::macro_api::mixins::generics::with::WithGenerics; +use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; @@ -15,7 +15,9 @@ struct Q<'a, T> { input_item: &'a InputItem, } -impl ToTokens for Q<'_, ItemAttribute>> { +impl ToTokens + for Q<'_, ItemAttribute>> +{ fn to_tokens(&self, tokens: &mut TokenStream) { let schedule = &self.args.args.base.schedule_config.schedule; for concrete_path in self.args.concrete_paths() { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 69b725c9..f19d22b8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -4,7 +4,7 @@ use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; use crate::macro_api::macro_paths::MacroPathProvider; -use crate::macro_api::mixins::generics::with::WithGenerics; +use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::extensions::item::ItemAttrsExt; use proc_macro2::TokenStream; @@ -39,7 +39,9 @@ where } } -impl ToTokens for QQ<'_, ItemAttribute>> { +impl ToTokens + for QQ<'_, ItemAttribute>> +{ fn to_tokens(&self, tokens: &mut TokenStream) { let schedule = &self.args.args.base.schedule_config.schedule; let extra_args = self.args.args.extra_args(); From bc6ec12b2d81588fc1d84939d56350e039048f5b Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 20 Oct 2025 16:54:43 -0400 Subject: [PATCH 004/162] feat: implement `ToTokens` for `Q` with various `ItemAttribute` compositions on action macros --- .../src/macro_api/q.rs | 120 +++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index dbb07593..f77a5bf8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -1,9 +1,11 @@ use crate::macro_api::attributes::ItemAttribute; -use crate::macro_api::attributes::prelude::AddSystemArgs; +use crate::macro_api::attributes::prelude::*; use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; +use crate::macro_api::mixins::generics::none::WithNoGenerics; use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; +use crate::macro_api::mixins::generics::with_single::WithZeroOrOneGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; @@ -27,3 +29,119 @@ impl ToTokens } } } + +impl ToTokens + for Q<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.add_message::<#concrete_path>(); + }}); + } + } +} + +impl ToTokens + for Q<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.add_observer::<#concrete_path>(); + }}); + } + } +} + +impl ToTokens + for Q<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.add_plugin::<#concrete_path>(); + }}); + } + } +} + +impl ToTokens + for Q<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.init_resource::<#concrete_path>(); + }}); + } + } +} + +impl ToTokens for Q<'_, ItemAttribute>> { + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.init_state::<#concrete_path>(); + }}); + } + } +} + +impl ToTokens for Q<'_, ItemAttribute>> { + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.init_sub_state::<#concrete_path>(); + }}); + } + } +} + +impl ToTokens + for Q<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.insert_resource(#concrete_path::default()); + }}); + } + } +} + +impl ToTokens + for Q<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.register_state_type::<#concrete_path>(); + }}); + } + } +} + +impl ToTokens + for Q<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + app.register_type::<#concrete_path>(); + }}); + } + } +} + +impl ToTokens + for Q<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + #concrete_path(app); + }}); + } + } +} From 20d9f3fcc3b6a43e7c7ea0d28d64e43eefaa9f7a Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 20 Oct 2025 16:57:30 -0400 Subject: [PATCH 005/162] feat: add macro path providers for all action macros --- .../src/macro_api/macro_paths.rs | 83 ++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs index 17cd58c3..cf0d0aa8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs @@ -1,10 +1,29 @@ -use crate::macro_api::attributes::prelude::AddSystemArgs; +use crate::macro_api::attributes::prelude::*; use crate::macro_api::context::Context; pub struct MacroPaths { /// resolved absolute path to `auto_add_system` pub emit_add_system_macro: syn::Path, - // .. others + /// resolved absolute path to `auto_add_message` + pub emit_add_message_macro: syn::Path, + /// resolved absolute path to `auto_add_observer` + pub emit_add_observer_macro: syn::Path, + /// resolved absolute path to `auto_add_plugin` + pub emit_add_plugin_macro: syn::Path, + /// resolved absolute path to `auto_init_resource` + pub emit_init_resource_macro: syn::Path, + /// resolved absolute path to `auto_init_state` + pub emit_init_state_macro: syn::Path, + /// resolved absolute path to `auto_init_sub_state` + pub emit_init_sub_state_macro: syn::Path, + /// resolved absolute path to `auto_insert_resource` + pub emit_insert_resource_macro: syn::Path, + /// resolved absolute path to `auto_register_state_type` + pub emit_register_state_type_macro: syn::Path, + /// resolved absolute path to `auto_register_type` + pub emit_register_type_macro: syn::Path, + /// resolved absolute path to `auto_run_on_build` + pub emit_run_on_build_macro: syn::Path, } pub trait MacroPathProvider { @@ -16,3 +35,63 @@ impl MacroPathProvider for AddSystemArgs { &context.macros.emit_add_system_macro } } + +impl MacroPathProvider for AddMessageArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_add_message_macro + } +} + +impl MacroPathProvider for AddObserverArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_add_observer_macro + } +} + +impl MacroPathProvider for AddPluginArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_add_plugin_macro + } +} + +impl MacroPathProvider for InitResourceArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_init_resource_macro + } +} + +impl MacroPathProvider for InitStateArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_init_state_macro + } +} + +impl MacroPathProvider for InitSubStateArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_init_sub_state_macro + } +} + +impl MacroPathProvider for InsertResourceArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_insert_resource_macro + } +} + +impl MacroPathProvider for RegisterStateTypeArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_register_state_type_macro + } +} + +impl MacroPathProvider for RegisterTypeArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_register_type_macro + } +} + +impl MacroPathProvider for RunOnBuildArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_run_on_build_macro + } +} From 9212461715eef0e634d4c9ef66cf9c34d3a7665f Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 20 Oct 2025 17:00:06 -0400 Subject: [PATCH 006/162] feat: implement `ToTokens` for `QQ` with action macro `ItemAttribute` compositions --- .../src/macro_api/qq.rs | 110 +++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index f19d22b8..3235ee67 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -1,10 +1,12 @@ use crate::macro_api::attributes::ItemAttribute; -use crate::macro_api::attributes::prelude::AddSystemArgs; +use crate::macro_api::attributes::prelude::*; use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; use crate::macro_api::macro_paths::MacroPathProvider; +use crate::macro_api::mixins::generics::none::WithNoGenerics; use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; +use crate::macro_api::mixins::generics::with_single::WithZeroOrOneGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::extensions::item::ItemAttrsExt; use proc_macro2::TokenStream; @@ -51,3 +53,109 @@ impl ToTokens }); } } + +impl ToTokens + for QQ<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens + for QQ<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens + for QQ<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens + for QQ<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens for QQ<'_, ItemAttribute>> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens for QQ<'_, ItemAttribute>> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens + for QQ<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens + for QQ<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens + for QQ<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} + +impl ToTokens + for QQ<'_, ItemAttribute>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let extra_args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#extra_args),* + }); + } +} From 256efc9c66d46177b00bf32e1684ae30b57ebd46 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 20 Oct 2025 18:08:58 -0400 Subject: [PATCH 007/162] feat: add `IdentPathResolver` and extend `ItemAttribute` with it --- .../src/macro_api/attributes/mod.rs | 52 +++++++++--- .../src/macro_api/input_item.rs | 2 +- .../src/macro_api/q.rs | 73 ++++++++++++++--- .../src/macro_api/qq.rs | 79 ++++++++++++++++--- 4 files changed, 172 insertions(+), 34 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index cc52410a..7a25c9ef 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -10,6 +10,7 @@ use darling::FromMeta; use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use std::hash::Hash; +use std::marker::PhantomData; use syn::parse::Parse; use syn::spanned::Spanned; use syn::{Item, parse_quote, parse2}; @@ -66,16 +67,46 @@ pub trait ItemAttributeArgs: fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_>; } -pub struct ItemAttribute { +pub trait IdentPathResolver { + const NOT_ALLOWED_MESSAGE: &'static str = "Unable to resolve ident path"; + fn resolve_ident_path(item: &Item) -> Option; +} + +pub struct AllowStructOrEnum; +impl IdentPathResolver for AllowStructOrEnum { + const NOT_ALLOWED_MESSAGE: &'static str = "Only allowed on Struct Or Enum items"; + fn resolve_ident_path(item: &Item) -> Option { + Some(match item { + Item::Struct(item) => item.ident.clone().into(), + Item::Enum(item) => item.ident.clone().into(), + _ => return None, + }) + } +} + +pub struct AllowFn; +impl IdentPathResolver for AllowFn { + const NOT_ALLOWED_MESSAGE: &'static str = "Only allowed on Fn items"; + fn resolve_ident_path(item: &Item) -> Option { + Some(match item { + Item::Fn(item) => item.sig.ident.clone().into(), + _ => return None, + }) + } +} + +pub struct ItemAttribute { pub args: T, pub context: Context, pub input_item: InputItem, - pub target: syn::Ident, + pub target: syn::Path, + pub _resolver: PhantomData, } -impl ItemAttribute +impl ItemAttribute where T: Parse, + Resolver: IdentPathResolver, { pub fn from_attr_input( attr: TokenStream, @@ -83,10 +114,11 @@ where context: Context, ) -> syn::Result { let mut input_item = InputItem::new(input); - let Some(target) = input_item.get_ident()?.cloned() else { + let item = input_item.ensure_ast()?; + let Some(target) = Resolver::resolve_ident_path(item) else { return Err(syn::Error::new( input_item.span(), - "Unable to resolve target ident", + Resolver::NOT_ALLOWED_MESSAGE, )); }; Ok(Self { @@ -94,17 +126,18 @@ where context, input_item, target, + _resolver: PhantomData, }) } } -impl ItemAttribute> { +impl ItemAttribute, Resolver> { pub fn plugin(&self) -> &syn::Path { self.args.plugin() } } -impl ItemAttribute> +impl ItemAttribute, Resolver> where M2: HasGenerics, { @@ -113,8 +146,8 @@ where } } -impl ItemAttribute { - fn convert_into(value: ItemAttribute) -> ItemAttribute +impl ItemAttribute { + fn convert_into(value: ItemAttribute) -> ItemAttribute where T2: From, { @@ -123,6 +156,7 @@ impl ItemAttribute { context: value.context, input_item: value.input_item, target: value.target, + _resolver: PhantomData, } } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs index 43244377..c3227823 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs @@ -18,7 +18,7 @@ impl InputItem { } Ok(()) } - fn ensure_ast(&mut self) -> syn::Result<&syn::Item> { + pub fn ensure_ast(&mut self) -> syn::Result<&syn::Item> { self._upgrade()?; Ok(match &*self { Self::Ast(ast) => ast.as_ref(), diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index f77a5bf8..0845751e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -1,5 +1,5 @@ -use crate::macro_api::attributes::ItemAttribute; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::attributes::{AllowFn, AllowStructOrEnum, ItemAttribute}; use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; @@ -18,7 +18,7 @@ struct Q<'a, T> { } impl ToTokens - for Q<'_, ItemAttribute>> + for Q<'_, ItemAttribute, AllowFn>> { fn to_tokens(&self, tokens: &mut TokenStream) { let schedule = &self.args.args.base.schedule_config.schedule; @@ -31,7 +31,13 @@ impl ToTokens } impl ToTokens - for Q<'_, ItemAttribute>> + for Q< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { @@ -43,7 +49,7 @@ impl ToTokens } impl ToTokens - for Q<'_, ItemAttribute>> + for Q<'_, ItemAttribute, AllowFn>> { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { @@ -55,7 +61,13 @@ impl ToTokens } impl ToTokens - for Q<'_, ItemAttribute>> + for Q< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { @@ -67,7 +79,13 @@ impl ToTokens } impl ToTokens - for Q<'_, ItemAttribute>> + for Q< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { @@ -78,7 +96,9 @@ impl ToTokens } } -impl ToTokens for Q<'_, ItemAttribute>> { +impl ToTokens + for Q<'_, ItemAttribute, AllowStructOrEnum>> +{ fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { @@ -88,7 +108,12 @@ impl ToTokens for Q<'_, ItemAttribute>> { +impl ToTokens + for Q< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { @@ -99,7 +124,13 @@ impl ToTokens for Q<'_, ItemAttribute>> + for Q< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { @@ -111,7 +142,13 @@ impl ToTokens } impl ToTokens - for Q<'_, ItemAttribute>> + for Q< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { @@ -123,7 +160,13 @@ impl ToTokens } impl ToTokens - for Q<'_, ItemAttribute>> + for Q< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { @@ -135,7 +178,13 @@ impl ToTokens } impl ToTokens - for Q<'_, ItemAttribute>> + for Q< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 3235ee67..c15e29ab 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -1,5 +1,5 @@ -use crate::macro_api::attributes::ItemAttribute; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::attributes::{AllowFn, AllowStructOrEnum, ItemAttribute}; use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; @@ -42,7 +42,7 @@ where } impl ToTokens - for QQ<'_, ItemAttribute>> + for QQ<'_, ItemAttribute, AllowFn>> { fn to_tokens(&self, tokens: &mut TokenStream) { let schedule = &self.args.args.base.schedule_config.schedule; @@ -55,7 +55,13 @@ impl ToTokens } impl ToTokens - for QQ<'_, ItemAttribute>> + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); @@ -66,7 +72,10 @@ impl ToTokens } impl ToTokens - for QQ<'_, ItemAttribute>> + for QQ< + '_, + ItemAttribute, AllowFn>, + > { fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); @@ -77,7 +86,13 @@ impl ToTokens } impl ToTokens - for QQ<'_, ItemAttribute>> + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); @@ -88,7 +103,13 @@ impl ToTokens } impl ToTokens - for QQ<'_, ItemAttribute>> + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); @@ -98,7 +119,12 @@ impl ToTokens } } -impl ToTokens for QQ<'_, ItemAttribute>> { +impl ToTokens + for QQ< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); tokens.extend(quote! { @@ -107,7 +133,12 @@ impl ToTokens for QQ<'_, ItemAttribute>> { +impl ToTokens + for QQ< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); tokens.extend(quote! { @@ -117,7 +148,13 @@ impl ToTokens for QQ<'_, ItemAttribute>> + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); @@ -128,7 +165,13 @@ impl ToTokens } impl ToTokens - for QQ<'_, ItemAttribute>> + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); @@ -139,7 +182,13 @@ impl ToTokens } impl ToTokens - for QQ<'_, ItemAttribute>> + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); @@ -150,7 +199,13 @@ impl ToTokens } impl ToTokens - for QQ<'_, ItemAttribute>> + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > { fn to_tokens(&self, tokens: &mut TokenStream) { let extra_args = self.args.args.extra_args(); From 31fcafd722985a36e6501dbbf207da51ce34cd7e Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 10:17:05 -0400 Subject: [PATCH 008/162] refactor: add `PluginCap` and `GenericsCap` traits and update `ItemAttribute` implementations restricts accessing generics to only when they may exist --- .../src/macro_api/attributes/mod.rs | 55 ++++++++++++++----- .../src/macro_api/mixins/generics/none.rs | 8 --- .../src/macro_api/q.rs | 20 +++---- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 7a25c9ef..c7ad82ce 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -3,8 +3,11 @@ use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; use crate::macro_api::mixins::generics::HasGenerics; +use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; +use crate::macro_api::mixins::generics::with_single::WithZeroOrOneGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::analysis::item::IdentFromItemResult; +use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream}; @@ -95,6 +98,15 @@ impl IdentPathResolver for AllowFn { } } +pub trait PluginCap { + fn plugin_path(&self) -> &syn::Path; +} + +pub trait GenericsCap { + fn generics(&self) -> &[TypeList]; + fn concrete_paths(&self) -> Vec; +} + pub struct ItemAttribute { pub args: T, pub context: Context, @@ -131,21 +143,6 @@ where } } -impl ItemAttribute, Resolver> { - pub fn plugin(&self) -> &syn::Path { - self.args.plugin() - } -} - -impl ItemAttribute, Resolver> -where - M2: HasGenerics, -{ - pub fn concrete_paths(&self) -> Vec { - self.args.concrete_paths(&self.target.clone().into()) - } -} - impl ItemAttribute { fn convert_into(value: ItemAttribute) -> ItemAttribute where @@ -160,3 +157,31 @@ impl ItemAttribute { } } } + +impl PluginCap for ItemAttribute, R> { + fn plugin_path(&self) -> &syn::Path { + &self.args.plugin.plugin + } +} + +impl GenericsCap for ItemAttribute, R> +where + M2: HasGenerics, +{ + fn generics(&self) -> &[TypeList] { + self.args.generics.generics() + } + fn concrete_paths(&self) -> Vec { + let target = &self.target; + if self.args.generics.generics().is_empty() { + vec![target.clone()] + } else { + self.args + .generics + .generics() + .iter() + .map(|g| syn::parse_quote!(#target::<#g>)) + .collect() + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs index 690f9063..3913f503 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs @@ -1,6 +1,4 @@ use crate::macro_api::mixins::HasKeys; -use crate::macro_api::mixins::generics::HasGenerics; -use crate::syntax::ast::type_list::TypeList; use darling::FromMeta; use darling::ast::NestedMeta; use proc_macro2::TokenStream; @@ -21,12 +19,6 @@ impl HasKeys for WithNoGenerics { } } -impl HasGenerics for WithNoGenerics { - fn generics(&self) -> &[TypeList] { - &[] - } -} - impl ToTokens for WithNoGenerics { fn to_tokens(&self, _tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 0845751e..431bbf49 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -1,5 +1,5 @@ use crate::macro_api::attributes::prelude::*; -use crate::macro_api::attributes::{AllowFn, AllowStructOrEnum, ItemAttribute}; +use crate::macro_api::attributes::{AllowFn, AllowStructOrEnum, GenericsCap, ItemAttribute}; use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; @@ -100,11 +100,10 @@ impl ToTokens for Q<'_, ItemAttribute, AllowStructOrEnum>> { fn to_tokens(&self, tokens: &mut TokenStream) { - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - app.init_state::<#concrete_path>(); - }}); - } + let target = &self.args.target; + tokens.extend(quote! { |app| { + app.init_state::<#target>(); + }}); } } @@ -115,11 +114,10 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - app.init_sub_state::<#concrete_path>(); - }}); - } + let target = &self.args.target; + tokens.extend(quote! { |app| { + app.init_sub_state::<#target>(); + }}); } } From 434b022d9098df433e49c20747206e895238a9db Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 10:28:32 -0400 Subject: [PATCH 009/162] fix: `ToTokens` on generics --- .../src/macro_api/mixins/generics/with_many.rs | 11 +++++++---- .../src/macro_api/mixins/generics/with_single.rs | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs index d156014f..264b60bc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs @@ -30,10 +30,13 @@ impl HasGenerics for WithZeroOrManyGenerics { impl ToTokens for WithZeroOrManyGenerics { fn to_tokens(&self, tokens: &mut TokenStream) { - if !self.generics.is_empty() { - for g in &self.generics { - tokens.extend(quote! { generics(#g) }); - } + if self.generics.is_empty() { + return; } + + let sets = self.generics.iter().map(|g| quote! { generics(#g) }); + tokens.extend(quote! { + #(#sets),* + }); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index e1da9bbe..54c3008d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -30,10 +30,13 @@ impl HasGenerics for WithZeroOrOneGenerics { impl ToTokens for WithZeroOrOneGenerics { fn to_tokens(&self, tokens: &mut TokenStream) { - if !self.generics.is_empty() { - for g in &self.generics { - tokens.extend(quote! { generics(#g) }); - } + if self.generics.is_empty() { + return; } + + let sets = self.generics.iter().map(|g| quote! { generics(#g) }); + tokens.extend(quote! { + #(#sets),* + }); } } From 8c5dc364bc73043027cd600461303d8f17c17e8d Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 10:40:26 -0400 Subject: [PATCH 010/162] refactor: simplify `ToTokens` and add tests for generics --- .../macro_api/mixins/generics/with_many.rs | 42 +++++++++++++++++-- .../macro_api/mixins/generics/with_single.rs | 35 ++++++++++++---- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs index 264b60bc..65ea2925 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs @@ -30,13 +30,47 @@ impl HasGenerics for WithZeroOrManyGenerics { impl ToTokens for WithZeroOrManyGenerics { fn to_tokens(&self, tokens: &mut TokenStream) { - if self.generics.is_empty() { - return; - } - let sets = self.generics.iter().map(|g| quote! { generics(#g) }); tokens.extend(quote! { #(#sets),* }); } } + +#[cfg(test)] +mod tests { + use super::*; + use internal_test_proc_macro::xtest; + use syn::parse_quote; + + #[xtest] + fn test_to_tokens_zero() { + WithZeroOrManyGenerics { generics: vec![] } + .to_token_stream() + .to_string() + == r#""#; + } + + #[xtest] + fn test_to_tokens_single() { + WithZeroOrManyGenerics { + generics: vec![TypeList(vec![parse_quote!(bool), parse_quote!(u32)])], + } + .to_token_stream() + .to_string() + == r#"generics(bool, u32)"#; + } + + #[xtest] + fn test_to_tokens_multiple() { + WithZeroOrManyGenerics { + generics: vec![ + TypeList(vec![parse_quote!(bool), parse_quote!(u32)]), + TypeList(vec![parse_quote!(usize)]), + ], + } + .to_token_stream() + .to_string() + == r#"generics(bool, u32), generics(usize)"#; + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index 54c3008d..49b184f6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -8,8 +8,8 @@ use quote::{ToTokens, quote}; #[derive(Debug, Clone, Default, FromMeta)] #[darling(derive_syn_parse)] pub struct WithZeroOrOneGenerics { - #[darling(multiple, default, rename = "generics")] - pub generics: Vec, + #[darling(default, rename = "generics")] + pub generics: Option, } impl WithZeroOrOneGenerics { @@ -24,19 +24,40 @@ impl HasKeys for WithZeroOrOneGenerics { impl HasGenerics for WithZeroOrOneGenerics { fn generics(&self) -> &[TypeList] { - &self.generics + self.generics.as_slice() } } impl ToTokens for WithZeroOrOneGenerics { fn to_tokens(&self, tokens: &mut TokenStream) { - if self.generics.is_empty() { - return; - } - let sets = self.generics.iter().map(|g| quote! { generics(#g) }); tokens.extend(quote! { #(#sets),* }); } } + +#[cfg(test)] +mod tests { + use super::*; + use internal_test_proc_macro::xtest; + use syn::parse_quote; + + #[xtest] + fn test_to_tokens_zero() { + WithZeroOrOneGenerics { generics: None } + .to_token_stream() + .to_string() + == r#""#; + } + + #[xtest] + fn test_to_tokens_single() { + WithZeroOrOneGenerics { + generics: Some(TypeList(vec![parse_quote!(bool), parse_quote!(u32)])), + } + .to_token_stream() + .to_string() + == r#"generics(bool, u32)"#; + } +} From 6b1a0e6cd247e701d145a5c9f7e7e94617825d91 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 10:48:55 -0400 Subject: [PATCH 011/162] fix: make sure impl ToTokens for Q matches original tokens --- .../src/macro_api/q.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 431bbf49..3cac5e26 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -22,9 +22,10 @@ impl ToTokens { fn to_tokens(&self, tokens: &mut TokenStream) { let schedule = &self.args.args.base.schedule_config.schedule; + let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { - app.add_system(#schedule, #concrete_path); + .add_systems(#schedule, #concrete_path #config_tokens) }}); } } @@ -71,9 +72,19 @@ impl ToTokens { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - app.add_plugin::<#concrete_path>(); - }}); + if let Some(expr) = &self.args.args.base.init.expr { + tokens.extend(quote! { |app| { + app.add_plugins({ let plugin: #concrete_path = #expr; plugin }) + }}); + } else if self.args.args.base.init.present { + tokens.extend(quote! { |app| { + app.add_plugins(#concrete_path::default()) + }}); + } else { + tokens.extend(quote! { |app| { + app.add_plugins(#concrete_path) + }}); + } } } } From b5c7e5938cfb027c176f68b28abe010374153b0e Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 10:51:27 -0400 Subject: [PATCH 012/162] fix: make sure impl ToTokens for QQ matches original tokens --- .../src/macro_api/qq.rs | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index c15e29ab..ce67f502 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -46,10 +46,10 @@ impl ToTokens { fn to_tokens(&self, tokens: &mut TokenStream) { let schedule = &self.args.args.base.schedule_config.schedule; - let extra_args = self.args.args.extra_args(); + let mut args = self.args.args.extra_args(); + args.push(quote! { schedule = #schedule }); tokens.extend(quote! { - #(#extra_args),* - schedule = #schedule, + #(#args),* }); } } @@ -64,9 +64,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -78,9 +78,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -95,9 +95,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -112,9 +112,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -126,9 +126,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -140,9 +140,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -157,9 +157,11 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let mut args = self.args.args.extra_args(); + let resource = &self.args.args.base.resource; + args.push(quote! { resource = #resource }); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -174,9 +176,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -191,9 +193,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } @@ -208,9 +210,9 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { - let extra_args = self.args.args.extra_args(); + let args = self.args.args.extra_args(); tokens.extend(quote! { - #(#extra_args),* + #(#args),* }); } } From 5adb0e4e4ffb334a21f1a838808490974f61a4d6 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 11:13:34 -0400 Subject: [PATCH 013/162] feat: implement `ToTokens` for Q and QQ with `ConfigureSystemSetArgs` composition --- .../src/macro_api/q.rs | 63 +++++++++++++++++++ .../src/macro_api/qq.rs | 35 ++++++++++- 2 files changed, 96 insertions(+), 2 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 3cac5e26..656e9b75 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -203,3 +203,66 @@ impl ToTokens } } } + +impl ToTokens + for Q< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = &self.args.args; + let generics = args.generics(); + let base = &self.args.args.base; + let schedule = &args.base.schedule_config.schedule; + let config_tokens = args.base.schedule_config.config.to_token_stream(); + for concrete_path in self.args.concrete_paths() { + if let Some(inner) = &base.inner { + // enum + let chained = if base.chain.is_present() { + quote! { .chain() } + } else if base.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let mut entries = vec![]; + for (ident, entry) in inner.entries.iter() { + let chained = if entry.chain.is_present() { + quote! { .chain() } + } else if entry.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let config_tokens = entry.config.to_token_stream(); + entries.push(quote! { + #concrete_path :: #ident #chained #config_tokens + }); + } + if !entries.is_empty() { + tokens.extend(quote! { + .configure_sets(#schedule, (#(#entries),*) #chained #config_tokens) + }); + } + } else { + // struct + if generics.is_empty() { + tokens.extend(quote! { + .configure_sets(#schedule, #concrete_path #config_tokens) + }); + } else { + // TODO: generics are kind of silly here + // but if someone does use them we'll assume its just a marker type + // that can be initialized via `Default::default()` + tokens.extend(quote! { + .configure_sets(#schedule, #concrete_path::default() #config_tokens) + }); + } + } + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index ce67f502..2eec39fd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -45,9 +45,15 @@ impl ToTokens for QQ<'_, ItemAttribute, AllowFn>> { fn to_tokens(&self, tokens: &mut TokenStream) { - let schedule = &self.args.args.base.schedule_config.schedule; let mut args = self.args.args.extra_args(); - args.push(quote! { schedule = #schedule }); + // TODO: cleanup + args.extend( + self.args + .args + .base + .schedule_config + .to_inner_arg_tokens_vec(), + ); tokens.extend(quote! { #(#args),* }); @@ -216,3 +222,28 @@ impl ToTokens }); } } + +impl ToTokens + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut args = self.args.args.extra_args(); + // TODO: cleanup + args.extend( + self.args + .args + .base + .schedule_config + .to_inner_arg_tokens_vec(), + ); + tokens.extend(quote! { + #(#args),* + }); + } +} From 624040067da28b804261da8efc2af97714852ebf Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 11:36:36 -0400 Subject: [PATCH 014/162] fix: extend `ToTokens` for Q and QQ to support AutoName and RegisterStateTypeArgs --- .../src/macro_api/q.rs | 36 ++++++++++++++++++- .../src/macro_api/qq.rs | 17 +++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 656e9b75..9fb7a4df 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -7,6 +7,7 @@ use crate::macro_api::mixins::generics::none::WithNoGenerics; use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; use crate::macro_api::mixins::generics::with_single::WithZeroOrOneGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::syntax::extensions::lit::LitExt; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; @@ -161,8 +162,10 @@ impl ToTokens { fn to_tokens(&self, tokens: &mut TokenStream) { for concrete_path in self.args.concrete_paths() { + let bevy_state = crate::__private::paths::state::root_path(); tokens.extend(quote! { |app| { - app.register_state_type::<#concrete_path>(); + app.register_type :: < #bevy_state::prelude::State< #concrete_path > >(); + app.register_type :: < #bevy_state::prelude::NextState< #concrete_path > >(); }}); } } @@ -266,3 +269,34 @@ impl ToTokens } } } + +impl ToTokens + for Q< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = &self.args.args.base; + for concrete_path in self.args.concrete_paths() { + let name = args + .name + .as_ref() + .map(|name| name.unquoted_string()) + .unwrap_or_else(|| { + // TODO: move to util fn + quote!(#concrete_path) + .to_string() + .replace(" < ", "<") + .replace(" >", ">") + .replace(" ,", ",") + // TODO: offer option to only remove all spaces? + // .replace(" ", "") + }); + let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); + tokens.extend(quote! { |app| { + app.register_required_components_with::<#concrete_path, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new(#name)); + }}); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 2eec39fd..157a6c78 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -247,3 +247,20 @@ impl ToTokens }); } } + +impl ToTokens + for QQ< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut args = self.args.args.extra_args(); + if let Some(name) = &self.args.args.base.name { + args.push(quote! { name = #name }); + } + tokens.extend(quote! { + #(#args),* + }); + } +} From 669f7374fe3e6cc488f562ec2f613312955b3df6 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 11:47:05 -0400 Subject: [PATCH 015/162] refactor: remove attribute tests, trait impls, with_plugin --- .../src/__private/expand/attr/mod.rs | 2 - .../attributes/actions/auto_add_message.rs | 116 +------- .../attributes/actions/auto_add_observer.rs | 118 +-------- .../attributes/actions/auto_add_plugin.rs | 168 +----------- .../attributes/actions/auto_add_system.rs | 51 +--- .../actions/auto_configure_system_set.rs | 108 +------- .../attributes/actions/auto_init_resource.rs | 112 +------- .../attributes/actions/auto_init_state.rs | 70 +---- .../attributes/actions/auto_init_sub_state.rs | 70 +---- .../actions/auto_insert_resource.rs | 91 +------ .../macro_api/attributes/actions/auto_name.rs | 146 +---------- .../actions/auto_register_state_type.rs | 115 +------- .../attributes/actions/auto_register_type.rs | 112 +------- .../attributes/actions/auto_run_on_build.rs | 117 +-------- .../src/macro_api/attributes/mod.rs | 38 ++- .../attributes/rewrites/auto_component.rs | 121 +-------- .../attributes/rewrites/auto_event.rs | 248 +----------------- .../attributes/rewrites/auto_message.rs | 82 +----- .../attributes/rewrites/auto_observer.rs | 77 +----- .../attributes/rewrites/auto_resource.rs | 80 +----- .../attributes/rewrites/auto_states.rs | 78 ------ .../attributes/rewrites/auto_system.rs | 63 +---- .../src/macro_api/mod.rs | 1 - .../src/macro_api/with_plugin.rs | 97 ------- 24 files changed, 59 insertions(+), 2222 deletions(-) delete mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/with_plugin.rs diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index a0ea176d..114d0927 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,9 +1,7 @@ use crate::__private::attribute::RewriteAttribute; use crate::__private::auto_plugin_registry::_plugin_entry_block; use crate::codegen::with_target_path::{ToTokensIterItem, WithTargetPath}; -use crate::macro_api::attributes::ItemAttributeArgs; use crate::macro_api::attributes::prelude::*; -use crate::macro_api::with_plugin::{PluginBound, WithPlugin}; use crate::syntax::diagnostic::kind::item_kind; use darling::FromMeta; use proc_macro2::{Ident, Span, TokenStream as MacroStream}; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index b2c518d5..c48023aa 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -1,122 +1,10 @@ -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] -pub struct AddMessageArgs { - #[darling(multiple)] - pub generics: Vec, -} +pub struct AddMessageArgs {} impl AttributeIdent for AddMessageArgs { const IDENT: &'static str = "auto_add_message"; } - -impl ItemAttributeArgs for AddMessageArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for AddMessageArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for AddMessageArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - tokens.extend(quote! { - .add_message::< #target >() - }) - } -} - -impl ArgsBackToTokens for AddMessageArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut args = vec![]; - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - tokens.extend(quote! { #(#args),* }); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_message :: < FooTarget > () - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_message :: < FooTarget > () - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_multiple() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool), generics(bool, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_message :: < FooTarget > () - } - .to_string() - ); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_message :: < FooTarget > () - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 1266c89e..913ccb44 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -1,124 +1,10 @@ -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_fn}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] -pub struct AddObserverArgs { - #[darling(multiple)] - pub generics: Vec, -} +pub struct AddObserverArgs {} impl AttributeIdent for AddObserverArgs { const IDENT: &'static str = "auto_add_observer"; } - -impl ItemAttributeArgs for AddObserverArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_fn(item) - } -} - -impl GenericsArgs for AddObserverArgs { - const TURBOFISH: bool = true; - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for AddObserverArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - tokens.extend(quote! { - .add_observer(#target) - }) - } -} - -impl ArgsBackToTokens for AddObserverArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut args = vec![]; - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - tokens.extend(quote! { #(#args),* }); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(foo_target); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - - .add_observer(foo_target) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool)))?; - let path: Path = parse_quote!(foo_target); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_observer(foo_target::) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_multiple() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool), generics(bool, bool)))?; - let path: Path = parse_quote!(foo_target); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_observer(foo_target::) - } - .to_string() - ); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_observer(foo_target::) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index c2fae94c..a356b74d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -1,20 +1,10 @@ -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; +use crate::macro_api::attributes::AttributeIdent; use crate::syntax::ast::flag_or_expr::FlagOrExpr; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] pub struct AddPluginArgs { - #[darling(default)] - pub generics: Option, #[darling(default)] pub init: FlagOrExpr, } @@ -22,159 +12,3 @@ pub struct AddPluginArgs { impl AttributeIdent for AddPluginArgs { const IDENT: &'static str = "auto_add_plugin"; } - -impl ItemAttributeArgs for AddPluginArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for AddPluginArgs { - const TURBOFISH: bool = true; - fn type_lists(&self) -> &[TypeList] { - self.generics.as_slice() - } -} - -impl ToTokensWithConcreteTargetPath for AddPluginArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - if let Some(expr) = &self.init.expr { - tokens.extend(quote! { - .add_plugins({ let plugin: #target = #expr; plugin }) - }) - } else if self.init.present { - tokens.extend(quote! { - .add_plugins(#target::default()) - }) - } else { - tokens.extend(quote! { - .add_plugins(#target) - }) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics_no_init() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_plugins(FooTarget) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_no_generics_init_present() -> syn::Result<()> { - let args = parse2::(quote!(init))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_plugins(FooTarget :: default ()) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_no_generics_init() -> syn::Result<()> { - let args = parse2::(quote!(init(FooTarget(1, true))))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_plugins({ let plugin: FooTarget = FooTarget(1, true); plugin }) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_no_init() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_plugins(FooTarget :: < u8 , bool >) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_init_present() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool), init))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_plugins(FooTarget :: < u8 , bool > :: default ()) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool), init(FooTarget(1, true))))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_plugins({ let plugin: FooTarget :: < u8 , bool > = FooTarget(1, true); plugin }) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - #[should_panic(expected = "Duplicate field `generics`")] - fn test_to_tokens_multiple() { - parse2::(quote!( - generics(u8, bool), - generics(bool, bool), - plugin(FooTarget(1, true)) - )) - .unwrap(); - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index 6ac706ee..012e531a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -1,21 +1,10 @@ -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; +use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_fn}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; -use syn::Item; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] pub struct AddSystemArgs { - #[darling(multiple)] - pub generics: Vec, #[darling(flatten)] pub schedule_config: ScheduleWithScheduleConfigArgs, } @@ -23,41 +12,3 @@ pub struct AddSystemArgs { impl AttributeIdent for AddSystemArgs { const IDENT: &'static str = "auto_add_system"; } - -impl ItemAttributeArgs for AddSystemArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_fn(item) - } -} - -impl GenericsArgs for AddSystemArgs { - const TURBOFISH: bool = true; - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for AddSystemArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - let schedule = &self.schedule_config.schedule; - let config_tokens = self.schedule_config.config.to_token_stream(); - tokens.extend(quote! { - .add_systems(#schedule, #target #config_tokens) - }) - } -} - -impl ArgsBackToTokens for AddSystemArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut args = vec![]; - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - args.extend(self.schedule_config.to_inner_arg_tokens_vec()); - tokens.extend(quote! { #(#args),* }); - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index cb440b99..89195589 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,20 +1,13 @@ -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; +use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::schedule_config::{ScheduleConfigArgs, ScheduleWithScheduleConfigArgs}; -use crate::macro_api::with_plugin::WithPlugin; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; +use crate::syntax::analysis::item::resolve_ident_from_struct_or_enum; use crate::syntax::ast::flag::Flag; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::parse::item::ts_item_has_attr; use crate::syntax::parse::scrub_helpers::{AttrSite, scrub_helpers_and_ident_with_filter}; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream}; -use quote::{ToTokens, quote}; use syn::spanned::Spanned; -use syn::{Attribute, Item, parse_quote, parse2}; +use syn::{Attribute, Item, parse_quote}; const CONFIG_ATTR_NAME: &str = "auto_configure_system_set_config"; const CHAIN_CONFLICT_ERR: &str = "`chain` and `chain_ignore_deferred` are mutually exclusive"; @@ -65,8 +58,6 @@ pub struct ConfigureSystemSetArgsInner { #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, and_then = Self::validate)] pub struct ConfigureSystemSetArgs { - #[darling(multiple, default)] - pub generics: Vec, /// allows per schedule entry/variants to be configured pub group: Option, #[darling(flatten)] @@ -99,84 +90,6 @@ impl AttributeIdent for ConfigureSystemSetArgs { const IDENT: &'static str = "auto_configure_system_set"; } -impl ItemAttributeArgs for ConfigureSystemSetArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for ConfigureSystemSetArgs { - const TURBOFISH: bool = true; - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for ConfigureSystemSetArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - let schedule = &self.schedule_config.schedule; - let config_tokens = self.schedule_config.config.to_token_stream(); - if let Some(inner) = &self.inner { - // enum - let chained = if self.chain.is_present() { - quote! { .chain() } - } else if self.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let mut entries = vec![]; - for (ident, entry) in inner.entries.iter() { - let chained = if entry.chain.is_present() { - quote! { .chain() } - } else if entry.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let config_tokens = entry.config.to_token_stream(); - entries.push(quote! { - #target :: #ident #chained #config_tokens - }); - } - if !entries.is_empty() { - tokens.extend(quote! { - .configure_sets(#schedule, (#(#entries),*) #chained #config_tokens) - }); - } - } else { - // struct - if target.generics.is_empty() { - tokens.extend(quote! { - .configure_sets(#schedule, #target #config_tokens) - }); - } else { - // TODO: generics are kind of silly here - // but if someone does use them we'll assume its just a marker type - // that can be initialized via `Default::default()` - tokens.extend(quote! { - .configure_sets(#schedule, #target::default() #config_tokens) - }); - } - } - } -} - -impl ArgsBackToTokens for ConfigureSystemSetArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut args = vec![]; - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - args.extend(self.schedule_config.to_inner_arg_tokens_vec()); - tokens.extend(quote! { #(#args),* }); - } -} - /// HACK - if the item doesn't have anymore `auto_configure_system_set` - set a flag to strip out the helper attributes fn check_strip_helpers(input: TokenStream, args: &mut ConfigureSystemSetArgs) -> syn::Result<()> { if !ts_item_has_attr(input, &parse_quote!(auto_configure_system_set))? { @@ -191,23 +104,12 @@ pub fn args_from_attr_input( // this is the only way we can strip out non-derive based attribute helpers input: &mut TokenStream, ) -> syn::Result { - let mut args = parse2::(attr)?; + let mut args = syn::parse2::(attr)?; check_strip_helpers(input.clone(), &mut args)?; args_with_plugin_from_args_input(&mut args, input)?; Ok(args) } -pub fn with_plugin_args_from_attr_input( - attr: TokenStream, - // this is the only way we can strip out non-derive based attribute helpers - input: &mut TokenStream, -) -> syn::Result> { - let mut args = parse2::>(attr)?; - check_strip_helpers(input.clone(), &mut args.inner)?; - args_with_plugin_from_args_input(&mut args.inner, input)?; - Ok(args) -} - pub fn args_with_plugin_from_args_input( args: &mut ConfigureSystemSetArgs, // this is the only way we can strip out non-derive based attribute helpers @@ -417,6 +319,7 @@ mod tests { mod test_struct { use super::*; + use quote::quote; #[xtest] fn test_to_tokens_no_generics() -> syn::Result<()> { let args = parse2::(quote!(schedule = Update))?; @@ -484,6 +387,7 @@ mod tests { mod test_enum { use super::*; use crate::syntax::validated::path_without_generics::PathWithoutGenerics; + use quote::quote; #[xtest] fn test_to_tokens_no_generics() -> syn::Result<()> { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 6046865f..bc39a9ef 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -1,118 +1,10 @@ -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] -pub struct InitResourceArgs { - #[darling(multiple)] - pub generics: Vec, -} +pub struct InitResourceArgs {} impl AttributeIdent for InitResourceArgs { const IDENT: &'static str = "auto_init_resource"; } - -impl ItemAttributeArgs for InitResourceArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for InitResourceArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for InitResourceArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - tokens.extend(quote! { - .init_resource::< #target >() - }) - } -} - -impl ArgsBackToTokens for InitResourceArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(self.generics().to_attribute_arg_tokens()); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .init_resource :: < FooTarget > () - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .init_resource :: < FooTarget > () - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_multiple() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool), generics(bool, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .init_resource :: < FooTarget > () - } - .to_string() - ); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .init_resource :: < FooTarget > () - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index e8c8b995..28c9302b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -1,15 +1,5 @@ -use crate::codegen::tokens; -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -18,61 +8,3 @@ pub struct InitStateArgs {} impl AttributeIdent for InitStateArgs { const IDENT: &'static str = "auto_init_state"; } - -impl ItemAttributeArgs for InitStateArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for InitStateArgs { - fn type_lists(&self) -> &[TypeList] { - &[] - } -} - -impl ToTokensWithConcreteTargetPath for InitStateArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - tokens.extend(quote! { - .init_state::< #target >() - }) - } - fn required_use_statements(&self) -> Vec { - vec![tokens::use_bevy_state_app_ext_states()] - } -} - -impl ArgsBackToTokens for InitStateArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(self.generics().to_attribute_arg_tokens()); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .init_state :: < FooTarget > () - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index a6be47be..f57c4c20 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -1,15 +1,5 @@ -use crate::codegen::tokens; -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -18,61 +8,3 @@ pub struct InitSubStateArgs {} impl AttributeIdent for InitSubStateArgs { const IDENT: &'static str = "auto_init_sub_state"; } - -impl ItemAttributeArgs for InitSubStateArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for InitSubStateArgs { - fn type_lists(&self) -> &[TypeList] { - &[] - } -} - -impl ToTokensWithConcreteTargetPath for InitSubStateArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - tokens.extend(quote! { - .add_sub_state::< #target >() - }) - } - fn required_use_statements(&self) -> Vec { - vec![tokens::use_bevy_state_app_ext_states()] - } -} - -impl ArgsBackToTokens for InitSubStateArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(self.generics().to_attribute_arg_tokens()); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .add_sub_state :: < FooTarget > () - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index e500a7b9..5651b0fc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -1,102 +1,13 @@ -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; +use crate::macro_api::attributes::AttributeIdent; use crate::syntax::ast::any_expr::AnyExprCallClosureMacroPath; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] pub struct InsertResourceArgs { - #[darling(default)] - pub generics: Option, pub resource: AnyExprCallClosureMacroPath, } impl AttributeIdent for InsertResourceArgs { const IDENT: &'static str = "auto_insert_resource"; } - -impl ItemAttributeArgs for InsertResourceArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for InsertResourceArgs { - fn type_lists(&self) -> &[TypeList] { - self.generics.as_slice() - } -} - -impl ToTokensWithConcreteTargetPath for InsertResourceArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - let resource = &self.resource; - tokens.extend(quote! { - .insert_resource::< #target >(#resource) - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!(resource(FooTarget)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .insert_resource :: < FooTarget > (FooTarget) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = - parse2::(quote!(generics(u8, bool), resource(FooTarget(1, true))))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .insert_resource :: < FooTarget > (FooTarget(1, true)) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - #[should_panic(expected = "Duplicate field `generics`")] - fn test_to_tokens_multiple() { - parse2::(quote!( - generics(u8, bool), - generics(bool, bool), - resource(FooTarget(1, true)) - )) - .unwrap(); - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index 962148ca..b3aeb7a8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -1,156 +1,12 @@ -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::extensions::lit::LitExt; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] pub struct NameArgs { - #[darling(multiple)] - pub generics: Vec, pub name: Option, } impl AttributeIdent for NameArgs { const IDENT: &'static str = "auto_name"; } - -impl ItemAttributeArgs for NameArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for NameArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for NameArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - let name = self - .name - .as_ref() - .map(|name| name.unquoted_string()) - .unwrap_or_else(|| { - // TODO: move to util fn - quote!(#target) - .to_string() - .replace(" < ", "<") - .replace(" >", ">") - .replace(" ,", ",") - // TODO: offer option to only remove all spaces? - // .replace(" ", "") - }); - let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); - tokens.extend(quote! { - .register_required_components_with::<#target, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new(#name)) - }) - } -} - -impl ArgsBackToTokens for NameArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(self.generics().to_attribute_arg_tokens()); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_required_components_with::(|| #bevy_ecs::prelude::Name::new("FooTarget")) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_with_custom_name_no_generics() -> syn::Result<()> { - let args = parse2::(quote!(name = "bar"))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_required_components_with::(|| #bevy_ecs::prelude::Name::new("bar")) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_required_components_with::, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new("FooTarget")) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_multiple() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool), generics(bool, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_required_components_with::, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new("FooTarget")) - } - .to_string() - ); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_required_components_with::, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new("FooTarget")) - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 79bf2d3c..7a1c0ec6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -1,121 +1,10 @@ -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] -pub struct RegisterStateTypeArgs { - #[darling(multiple)] - pub generics: Vec, -} +pub struct RegisterStateTypeArgs {} impl AttributeIdent for RegisterStateTypeArgs { const IDENT: &'static str = "auto_register_state_type"; } - -impl ItemAttributeArgs for RegisterStateTypeArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for RegisterStateTypeArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for RegisterStateTypeArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - let bevy_state = crate::__private::paths::state::root_path(); - tokens.extend(quote! { - .register_type :: < #bevy_state::prelude::State< #target > >() - .register_type :: < #bevy_state::prelude::NextState< #target > >() - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let bevy_state = crate::__private::paths::state::root_path(); - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_type :: < #bevy_state::prelude::State< FooTarget > >() - .register_type :: < #bevy_state::prelude::NextState< FooTarget > >() - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let bevy_state = crate::__private::paths::state::root_path(); - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_type :: < #bevy_state::prelude::State< FooTarget > >() - .register_type :: < #bevy_state::prelude::NextState< FooTarget > >() - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_multiple() -> syn::Result<()> { - let args = - parse2::(quote!(generics(u8, bool), generics(bool, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let bevy_state = crate::__private::paths::state::root_path(); - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_type :: < #bevy_state::prelude::State< FooTarget > >() - .register_type :: < #bevy_state::prelude::NextState< FooTarget > >() - } - .to_string() - ); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_type :: < #bevy_state::prelude::State< FooTarget > >() - .register_type :: < #bevy_state::prelude::NextState< FooTarget > >() - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 702fa221..4ad04b05 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -1,118 +1,10 @@ -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_struct_or_enum}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] -pub struct RegisterTypeArgs { - #[darling(multiple)] - pub generics: Vec, -} +pub struct RegisterTypeArgs {} impl AttributeIdent for RegisterTypeArgs { const IDENT: &'static str = "auto_register_type"; } - -impl ItemAttributeArgs for RegisterTypeArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_struct_or_enum(item) - } -} - -impl GenericsArgs for RegisterTypeArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for RegisterTypeArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - tokens.extend(quote! { - .register_type :: < #target >() - }) - } -} - -impl ArgsBackToTokens for RegisterTypeArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(self.generics().to_attribute_arg_tokens()); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; - - #[xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_type :: < FooTarget >() - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_type :: < FooTarget >() - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[xtest] - fn test_to_tokens_multiple() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool), generics(bool, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_type :: < FooTarget >() - } - .to_string() - ); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - .register_type :: < FooTarget >() - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index 49e1a28a..2ffe29e7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -1,123 +1,10 @@ -use crate::codegen::tokens::ArgsBackToTokens; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::syntax::analysis::item::{IdentFromItemResult, resolve_ident_from_fn}; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; +use crate::macro_api::attributes::AttributeIdent; use darling::FromMeta; -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] -pub struct RunOnBuildArgs { - #[darling(multiple)] - pub generics: Vec, -} +pub struct RunOnBuildArgs {} impl AttributeIdent for RunOnBuildArgs { const IDENT: &'static str = "auto_run_on_build"; } - -impl ItemAttributeArgs for RunOnBuildArgs { - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_> { - resolve_ident_from_fn(item) - } -} - -impl GenericsArgs for RunOnBuildArgs { - const TURBOFISH: bool = true; - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - -impl ToTokensWithConcreteTargetPath for RunOnBuildArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ) { - tokens.extend(quote! { - #target - }) - } -} - -impl ArgsBackToTokens for RunOnBuildArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut args = vec![]; - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - tokens.extend(quote! { #(#args),* }); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::codegen::with_target_path::WithTargetPath; - use syn::{Path, parse_quote, parse2}; - - #[internal_test_proc_macro::xtest] - fn test_to_tokens_no_generics() -> syn::Result<()> { - let args = parse2::(quote!())?; - let path: Path = parse_quote!(foo_target); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - - foo_target - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[internal_test_proc_macro::xtest] - fn test_to_tokens_single() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool)))?; - let path: Path = parse_quote!(foo_target); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - foo_target:: - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } - - #[internal_test_proc_macro::xtest] - fn test_to_tokens_multiple() -> syn::Result<()> { - let args = parse2::(quote!(generics(u8, bool), generics(bool, bool)))?; - let path: Path = parse_quote!(foo_target); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - foo_target:: - } - .to_string() - ); - assert_eq!( - token_iter.next().expect("token_iter").to_string(), - quote! { - foo_target:: - } - .to_string() - ); - assert!(token_iter.next().is_none()); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index c7ad82ce..cd541f9b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -1,15 +1,10 @@ -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; use crate::macro_api::mixins::generics::HasGenerics; -use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; -use crate::macro_api::mixins::generics::with_single::WithZeroOrOneGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; -use crate::syntax::analysis::item::IdentFromItemResult; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; -use darling::FromMeta; use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use std::hash::Hash; @@ -31,10 +26,7 @@ pub mod prelude { pub use crate::macro_api::attributes::actions::auto_add_observer::AddObserverArgs; pub use crate::macro_api::attributes::actions::auto_add_plugin::AddPluginArgs; pub use crate::macro_api::attributes::actions::auto_add_system::AddSystemArgs; - pub use crate::macro_api::attributes::actions::auto_configure_system_set::{ - ConfigureSystemSetArgs, - with_plugin_args_from_attr_input as configure_system_set_args_from_attr_input, - }; + pub use crate::macro_api::attributes::actions::auto_configure_system_set::ConfigureSystemSetArgs; pub use crate::macro_api::attributes::actions::auto_init_resource::InitResourceArgs; pub use crate::macro_api::attributes::actions::auto_init_state::InitStateArgs; pub use crate::macro_api::attributes::actions::auto_init_sub_state::InitSubStateArgs; @@ -61,13 +53,10 @@ pub trait AttributeIdent { } } -pub trait ItemAttributeArgs: - AttributeIdent + FromMeta + Parse + ToTokensWithConcreteTargetPath + Hash + Clone -{ +pub trait ItemAttributeArgs: AttributeIdent + Hash + Clone { fn global_build_prefix() -> Ident { format_ident!("_auto_plugin_{}_", Self::IDENT) } - fn resolve_item_ident(item: &Item) -> IdentFromItemResult<'_>; } pub trait IdentPathResolver { @@ -115,6 +104,29 @@ pub struct ItemAttribute { pub _resolver: PhantomData, } +// TODO: where should this live? +impl ItemAttribute +where + T: ItemAttributeArgs + Hash, +{ + fn _concat_ident_hash(&self, ident: &Ident) -> String { + use std::hash::{Hash, Hasher}; + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + ident.hash(&mut hasher); + self.args.hash(&mut hasher); + format!("{:x}", hasher.finish()) + } + + fn _get_unique_ident(&self, prefix: Ident, ident: &Ident) -> Ident { + let hash = self._concat_ident_hash(ident); + format_ident!("{prefix}_{hash}") + } + + fn get_unique_ident(&self, ident: &Ident) -> Ident { + self._get_unique_ident(T::global_build_prefix(), ident) + } +} + impl ItemAttribute where T: Parse, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index 1fb9c180..8241df47 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -6,7 +6,6 @@ use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::ast::flag_or_lit::FlagOrLit; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; @@ -16,36 +15,25 @@ use syn::parse_quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] pub struct ComponentArgs { - #[darling(multiple)] - pub generics: Vec, pub derive: FlagOrList, pub reflect: FlagOrList, pub register: bool, pub auto_name: FlagOrLit, } -impl GenericsArgs for ComponentArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - impl AttributeIdent for ComponentArgs { const IDENT: &'static str = "auto_component"; } impl<'a> From<&'a ComponentArgs> for RegisterTypeArgs { fn from(value: &'a ComponentArgs) -> Self { - Self { - generics: value.generics.clone(), - } + Self {} } } impl<'a> From<&'a ComponentArgs> for NameArgs { fn from(value: &'a ComponentArgs) -> Self { Self { - generics: value.generics.clone(), name: value.auto_name.lit.clone(), } } @@ -110,110 +98,3 @@ impl RewriteAttribute for ComponentArgs { expanded_attrs } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::macro_api::with_plugin::WithPlugin; - use crate::test_util::combo::combos_one_per_group_or_skip; - use crate::test_util::macros::*; - use darling::ast::NestedMeta; - use internal_test_proc_macro::xtest; - use internal_test_util::{extract_punctuated_paths, vec_spread}; - use quote::ToTokens; - use syn::parse_quote; - - #[xtest] - fn test_expand_back_into_args() -> syn::Result<()> { - for args in combos_one_per_group_or_skip(&[ - vec![quote!(derive), quote!(derive(Debug, Default))], - vec![quote!(reflect), quote!(reflect(Debug, Default))], - vec![quote!(register)], - vec![quote!(auto_name), quote!(auto_name = "foobar")], - ]) { - println!("checking args: {}", quote! { #(#args),*}); - assert_vec_args_expand!(plugin!(parse_quote!(Test)), ComponentArgs, args); - } - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global() -> syn::Result<()> { - let extras = extract_punctuated_paths(parse_quote!(Debug, Default)) - .into_iter() - .map(NonEmptyPath::try_from) - .collect::>>()?; - let args: NestedMeta = parse_quote! {_( - plugin = Test, - derive(#(#extras),*), - reflect(#(#extras),*), - register, - auto_name, - )}; - let args = WithPlugin::::from_nested_meta(&args)?; - let derive_args = vec_spread![tokens::derive_component_path(), ..extras.clone(),]; - let derive_reflect_path = tokens::derive_reflect_path(); - let reflect_args = vec_spread![parse_quote!(Component), ..extras,]; - let reflect_attr = tokens::reflect(reflect_args.iter().map(NonEmptyPath::last_ident)); - assert_eq!( - args.inner - .expand_attrs(&args.plugin()) - .to_token_stream() - .to_string(), - ExpandAttrs { - use_items: reflect_attr.use_items, - attrs: vec![ - quote! { #[derive(#(#derive_args),*)] }, - // TODO: merge these derives - quote! { #[derive(#derive_reflect_path)] }, - quote! { #[reflect(#(#reflect_args),*)] }, - tokens::auto_register_type(args.plugin(), (&args.inner).into()), - tokens::auto_name(args.plugin(), (&args.inner).into()), - ] - } - .to_token_stream() - .to_string() - ); - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global_with_custom_name() -> syn::Result<()> { - let extras = extract_punctuated_paths(parse_quote!(Debug, Default)) - .into_iter() - .map(NonEmptyPath::try_from) - .collect::>>()?; - let args: NestedMeta = parse_quote! {_( - plugin = Test, - derive(#(#extras),*), - reflect(#(#extras),*), - register, - auto_name = "foobar", - )}; - let args = WithPlugin::::from_nested_meta(&args)?; - let derive_args = vec_spread![tokens::derive_component_path(), ..extras.clone(),]; - let derive_reflect_path = tokens::derive_reflect_path(); - let reflect_args = vec_spread![parse_quote!(Component), ..extras,]; - let reflect_attr = tokens::reflect(reflect_args.iter().map(NonEmptyPath::last_ident)); - assert_eq!( - args.inner - .expand_attrs(&args.plugin()) - .to_token_stream() - .to_string(), - ExpandAttrs { - use_items: reflect_attr.use_items, - attrs: vec![ - quote! { #[derive(#(#derive_args),*)] }, - // TODO: merge these derives - quote! { #[derive(#derive_reflect_path)] }, - quote! { #[reflect(#(#reflect_args),*)] }, - tokens::auto_register_type(args.plugin(), (&args.inner).into()), - tokens::auto_name(args.plugin(), (&args.inner).into()), - ] - } - .to_token_stream() - .to_string() - ); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 8c29c89f..0561c6ec 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -5,7 +5,6 @@ use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; @@ -37,29 +36,19 @@ impl ToTokens for EventTarget { #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] pub struct EventArgs { - #[darling(multiple)] - pub generics: Vec, pub derive: FlagOrList, pub reflect: FlagOrList, pub register: bool, pub target: EventTarget, } -impl GenericsArgs for EventArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - impl AttributeIdent for EventArgs { const IDENT: &'static str = "auto_event"; } impl<'a> From<&'a EventArgs> for RegisterTypeArgs { fn from(value: &'a EventArgs) -> Self { - Self { - generics: value.generics.clone(), - } + Self {} } } @@ -121,238 +110,3 @@ impl RewriteAttribute for EventArgs { expanded_attrs } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::test_util::combo::combos_one_per_group_or_skip_with; - use crate::test_util::macros::*; - use crate::test_util::test_params::{_inject_derive, Side, TestParams as _TestParams}; - use internal_test_proc_macro::xtest; - use internal_test_util::extract_punctuated_paths; - use syn::parse_quote; - - type TestParams = _TestParams; - - pub trait TestParamsExt { - fn with_global(self, derive: bool) -> Self; - fn with_entity_event(self, derive: bool) -> Self; - } - - impl TestParamsExt for TestParams { - /// calling order matters - fn with_global(mut self, derive: bool) -> Self { - if derive { - _inject_derive( - &mut self.expected_derives.attrs, - &[tokens::derive_event_path()], - Side::Left, - ); - } - self - } - - /// calling order matters - fn with_entity_event(mut self, derive: bool) -> Self { - if derive { - _inject_derive( - &mut self.expected_derives.attrs, - &[tokens::derive_entity_event_path()], - Side::Left, - ); - } - self - } - } - - #[xtest] - fn test_expand_back_into_args() -> syn::Result<()> { - for args in combos_one_per_group_or_skip_with( - &[ - vec![quote!(derive), quote!(derive(Debug, Default))], - vec![quote!(reflect), quote!(reflect(Debug, Default))], - vec![quote!(register)], - ], - // TODO: target(global) is always emitted when no target is provided - quote!(target(global)), - ) { - println!("checking args: {}", quote! { #(#args),*}); - assert_vec_args_expand!(plugin!(parse_quote!(Test)), EventArgs, args); - } - Ok(()) - } - - fn extras() -> Vec { - extract_punctuated_paths(parse_quote!(Debug, Default)) - .into_iter() - .map(NonEmptyPath::try_from) - .collect::>>() - .expect("failed to extract punctuated paths") - } - - #[xtest] - fn test_expand_attrs_default() -> anyhow::Result<()> { - TestParams::from_args(quote! { - plugin = Test, - })? - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_no_global_or_entity_flags() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - derive(#(#extras),*), - reflect(#(#extras),*), - register, - })? - .with_derive(extras.clone()) - .with_global(true) - .with_reflect(extras.clone(), true) - .with_register() - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global_event() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - target(global), - derive(#(#extras),*), - reflect(#(#extras),*), - register, - })? - .with_derive(extras.clone()) - .with_global(true) - .with_reflect(extras.clone(), true) - .with_register() - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global_event_no_derive() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - target(global), - reflect(#(#extras),*), - register, - })? - .with_global(false) - .with_reflect(extras.clone(), false) - .with_register() - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_entity_event() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - target(entity), - derive(#(#extras),*), - reflect(#(#extras),*), - register, - })? - .with_derive(extras.clone()) - .with_entity_event(true) - .with_reflect(extras.clone(), true) - .with_register() - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_entity_event_no_derive() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - target(entity), - reflect(#(#extras),*), - register, - })? - .with_entity_event(false) - .with_reflect(extras.clone(), false) - .with_register() - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_entity_event_propagate() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - target(entity), - derive(#(#extras),*), - reflect(#(#extras),*), - register, - })? - .with_derive(extras.clone()) - .with_entity_event(true) - .with_reflect(extras.clone(), true) - .with_register() - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_entity_event_propagate_custom() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - target(entity), - derive(#(#extras),*), - reflect(#(#extras),*), - register, - })? - .with_derive(extras.clone()) - .with_entity_event(true) - .with_reflect(extras.clone(), true) - .with_register() - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_entity_event_propagate_custom_and_auto_propagate() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - target(entity), - derive(#(#extras),*), - reflect(#(#extras),*), - register, - })? - .with_derive(extras.clone()) - .with_entity_event(true) - .with_reflect(extras.clone(), true) - .with_register() - .test()?; - Ok(()) - } - - #[xtest] - fn test_expand_attrs_entity_event_auto_propagate() -> anyhow::Result<()> { - let extras = extras(); - TestParams::from_args(quote! { - plugin = Test, - target(entity), - derive(#(#extras),*), - reflect(#(#extras),*), - register, - })? - .with_derive(extras.clone()) - .with_entity_event(true) - .with_reflect(extras.clone(), true) - .with_register() - .test()?; - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 669b3e8e..358bbc68 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -6,7 +6,6 @@ use crate::macro_api::attributes::actions::auto_add_message::AddMessageArgs; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; @@ -15,36 +14,24 @@ use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] pub struct MessageArgs { - #[darling(multiple)] - pub generics: Vec, pub derive: FlagOrList, pub reflect: FlagOrList, pub register: bool, } -impl GenericsArgs for MessageArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - impl AttributeIdent for MessageArgs { const IDENT: &'static str = "auto_message"; } impl<'a> From<&'a MessageArgs> for RegisterTypeArgs { fn from(value: &'a MessageArgs) -> Self { - Self { - generics: value.generics.clone(), - } + Self {} } } impl<'a> From<&'a MessageArgs> for AddMessageArgs { fn from(value: &'a MessageArgs) -> Self { - Self { - generics: value.generics.clone(), - } + Self {} } } @@ -103,68 +90,3 @@ impl RewriteAttribute for MessageArgs { expanded_attrs } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::macro_api::with_plugin::WithPlugin; - use crate::test_util::combo::combos_one_per_group_or_skip; - use crate::test_util::macros::*; - use darling::ast::NestedMeta; - use internal_test_proc_macro::xtest; - use internal_test_util::{extract_punctuated_paths, vec_spread}; - use quote::ToTokens; - use syn::parse_quote; - - #[xtest] - fn test_expand_back_into_args() -> syn::Result<()> { - for args in combos_one_per_group_or_skip(&[ - vec![quote!(derive), quote!(derive(Debug, Default))], - vec![quote!(reflect), quote!(reflect(Debug, Default))], - vec![quote!(register)], - ]) { - println!("checking args: {}", quote! { #(#args),*}); - assert_vec_args_expand!(plugin!(parse_quote!(Test)), MessageArgs, args); - } - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global() -> syn::Result<()> { - let extras = extract_punctuated_paths(parse_quote!(Debug, Default)) - .into_iter() - .map(NonEmptyPath::try_from) - .collect::>>()?; - let args: NestedMeta = parse_quote! {_( - plugin = Test, - derive(#(#extras),*), - reflect(#(#extras),*), - register, - )}; - let args = WithPlugin::::from_nested_meta(&args)?; - let derive_args = vec_spread![tokens::derive_message_path(), ..extras.clone(),]; - let derive_reflect_path = tokens::derive_reflect_path(); - let reflect_args = vec_spread![..extras,]; - let reflect_attr = tokens::reflect(reflect_args.iter().map(NonEmptyPath::last_ident)); - assert_eq!( - args.inner - .expand_attrs(&args.plugin()) - .to_token_stream() - .to_string(), - ExpandAttrs { - use_items: reflect_attr.use_items, - attrs: vec![ - quote! { #[derive(#(#derive_args),*)] }, - // TODO: merge these derives - quote! { #[derive(#derive_reflect_path)] }, - quote! { #[reflect(#(#reflect_args),*)] }, - tokens::auto_register_type(args.plugin(), (&args.inner).into()), - tokens::auto_add_message(args.plugin(), (&args.inner).into()), - ] - } - .to_token_stream() - .to_string() - ); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index d007a489..f2c79f94 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -1,27 +1,16 @@ use crate::__private::attribute::RewriteAttribute; -use crate::codegen::tokens::ArgsBackToTokens; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; -use proc_macro2::{TokenStream as MacroStream, TokenStream}; +use proc_macro2::TokenStream as MacroStream; use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] -pub struct ObserverArgs { - #[darling(multiple)] - pub generics: Vec, -} - -impl GenericsArgs for ObserverArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} +pub struct ObserverArgs {} impl AttributeIdent for ObserverArgs { const IDENT: &'static str = "auto_observer"; @@ -29,23 +18,13 @@ impl AttributeIdent for ObserverArgs { impl<'a> From<&'a ObserverArgs> for RegisterTypeArgs { fn from(value: &'a ObserverArgs) -> Self { - Self { - generics: value.generics.clone(), - } + Self {} } } impl<'a> From<&'a ObserverArgs> for AddObserverArgs { fn from(value: &'a ObserverArgs) -> Self { - AddObserverArgs { - generics: value.generics.clone(), - } - } -} - -impl ArgsBackToTokens for ObserverArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - AddObserverArgs::from(self).back_to_inner_arg_tokens(tokens); + AddObserverArgs {} } } @@ -67,51 +46,3 @@ impl RewriteAttribute for ObserverArgs { expanded_attrs } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::macro_api::with_plugin::WithPlugin; - use crate::test_util::macros::*; - use darling::ast::NestedMeta; - use internal_test_proc_macro::xtest; - use internal_test_util::vec_spread; - use quote::ToTokens; - use syn::parse_quote; - - #[xtest] - fn test_expand_back_into_args() -> syn::Result<()> { - let args = vec![quote! {}]; - println!("checking args: {}", quote! { #(#args),*}); - assert_vec_args_expand!(plugin!(parse_quote!(Test)), ObserverArgs, args); - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global() -> syn::Result<()> { - let args: NestedMeta = parse_quote! {_( - plugin = Test, - )}; - let args = WithPlugin::::from_nested_meta(&args)?; - println!( - "{}", - args.inner.expand_attrs(&args.plugin()).to_token_stream() - ); - assert_eq!( - args.inner - .expand_attrs(&args.plugin()) - .to_token_stream() - .to_string(), - ExpandAttrs { - use_items: vec![], - attrs: vec_spread![tokens::auto_add_observer( - args.plugin(), - (&args.inner).into() - ),] - } - .to_token_stream() - .to_string() - ); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 01210807..8b1b6d5c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -5,7 +5,6 @@ use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; @@ -15,29 +14,19 @@ use syn::parse_quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] pub struct ResourceArgs { - #[darling(multiple)] - pub generics: Vec, pub derive: FlagOrList, pub reflect: FlagOrList, pub register: bool, pub init: bool, } -impl GenericsArgs for ResourceArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - impl AttributeIdent for ResourceArgs { const IDENT: &'static str = "auto_resource"; } impl<'a> From<&'a ResourceArgs> for RegisterTypeArgs { fn from(value: &'a ResourceArgs) -> Self { - Self { - generics: value.generics.clone(), - } + Self {} } } @@ -106,70 +95,3 @@ impl RewriteAttribute for ResourceArgs { expanded_attrs } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::macro_api::with_plugin::WithPlugin; - use crate::test_util::combo::combos_one_per_group_or_skip; - use crate::test_util::macros::*; - use darling::ast::NestedMeta; - use internal_test_proc_macro::xtest; - use internal_test_util::{extract_punctuated_paths, vec_spread}; - use quote::ToTokens; - use syn::parse_quote; - - #[xtest] - fn test_expand_back_into_args() -> syn::Result<()> { - for args in combos_one_per_group_or_skip(&[ - vec![quote!(derive), quote!(derive(Debug, Default))], - vec![quote!(reflect), quote!(reflect(Debug, Default))], - vec![quote!(register)], - vec![quote!(init)], - ]) { - println!("checking args: {}", quote! { #(#args),*}); - assert_vec_args_expand!(plugin!(parse_quote!(Test)), ResourceArgs, args); - } - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global() -> syn::Result<()> { - let extras = extract_punctuated_paths(parse_quote!(Debug, Default)) - .into_iter() - .map(NonEmptyPath::try_from) - .collect::>>()?; - let args: NestedMeta = parse_quote! {_( - plugin = Test, - derive(#(#extras),*), - reflect(#(#extras),*), - register, - init, - )}; - let args = WithPlugin::::from_nested_meta(&args)?; - let derive_args = vec_spread![tokens::derive_resource_path(), ..extras.clone(),]; - let derive_reflect_path = tokens::derive_reflect_path(); - let reflect_args = vec_spread![parse_quote!(Resource), ..extras,]; - let reflect_attr = tokens::reflect(reflect_args.iter().map(NonEmptyPath::last_ident)); - assert_eq!( - args.inner - .expand_attrs(&args.plugin()) - .to_token_stream() - .to_string(), - ExpandAttrs { - use_items: reflect_attr.use_items, - attrs: vec![ - quote! { #[derive(#(#derive_args),*)] }, - // TODO: merge these derives - quote! { #[derive(#derive_reflect_path)] }, - quote! { #[reflect(#(#reflect_args),*)] }, - tokens::auto_register_type(args.plugin(), (&args.inner).into()), - tokens::auto_init_resource(args.plugin(), (&args.inner).into()), - ] - } - .to_token_stream() - .to_string() - ); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 999c9853..1548b119 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -5,7 +5,6 @@ use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; @@ -20,12 +19,6 @@ pub struct StatesArgs { pub init: bool, } -impl GenericsArgs for StatesArgs { - fn type_lists(&self) -> &[TypeList] { - &[] - } -} - impl AttributeIdent for StatesArgs { const IDENT: &'static str = "auto_states"; } @@ -97,74 +90,3 @@ impl RewriteAttribute for StatesArgs { expanded_attrs } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::macro_api::with_plugin::WithPlugin; - use crate::test_util::combo::combos_one_per_group_or_skip; - use crate::test_util::macros::*; - use darling::ast::NestedMeta; - use internal_test_proc_macro::xtest; - use internal_test_util::{extract_punctuated_paths, vec_spread}; - use quote::ToTokens; - use syn::parse_quote; - - #[xtest] - fn test_expand_back_into_args() -> syn::Result<()> { - for args in combos_one_per_group_or_skip(&[ - vec![quote!(derive), quote!(derive(Debug, Default))], - vec![quote!(reflect), quote!(reflect(Debug, Default))], - vec![quote!(register)], - vec![quote!(init)], - ]) { - println!("checking args: {}", quote! { #(#args),*}); - assert_vec_args_expand!(plugin!(parse_quote!(Test)), StatesArgs, args); - } - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global() -> syn::Result<()> { - let extras = extract_punctuated_paths(parse_quote!(A, B)) - .into_iter() - .map(NonEmptyPath::try_from) - .collect::>>()?; - let args: NestedMeta = parse_quote! {_( - plugin = Test, - derive(#(#extras),*), - reflect(#(#extras),*), - register, - init, - )}; - let args = WithPlugin::::from_nested_meta(&args)?; - let derive_attr = tokens::derive_states(&extras); - let derive_reflect_path = tokens::derive_reflect_path(); - let reflect_args = vec_spread![..extras,]; - let reflect_attr = tokens::reflect(reflect_args.iter().map(NonEmptyPath::last_ident)); - println!( - "{}", - args.inner.expand_attrs(&args.plugin()).to_token_stream() - ); - assert_eq!( - args.inner - .expand_attrs(&args.plugin()) - .to_token_stream() - .to_string(), - ExpandAttrs { - use_items: [derive_attr.use_items, reflect_attr.use_items].concat(), - attrs: vec_spread![ - ..derive_attr.attrs, - // TODO: merge these derives - quote! { #[derive(#derive_reflect_path)] }, - quote! { #[reflect(#(#reflect_args),*)] }, - tokens::auto_register_type(args.plugin(), (&args.inner).into()), - tokens::auto_init_states(args.plugin(), (&args.inner).into()), - ] - } - .to_token_stream() - .to_string() - ); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 2040b991..a4a73f5d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -5,7 +5,6 @@ use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{TokenStream as MacroStream, TokenStream}; @@ -14,34 +13,23 @@ use quote::quote; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] pub struct SystemArgs { - #[darling(multiple)] - pub generics: Vec, #[darling(flatten)] pub schedule_config: ScheduleWithScheduleConfigArgs, } -impl GenericsArgs for SystemArgs { - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - impl AttributeIdent for SystemArgs { const IDENT: &'static str = "auto_system"; } impl<'a> From<&'a SystemArgs> for RegisterTypeArgs { fn from(value: &'a SystemArgs) -> Self { - Self { - generics: value.generics.clone(), - } + Self {} } } impl<'a> From<&'a SystemArgs> for AddSystemArgs { fn from(value: &'a SystemArgs) -> Self { AddSystemArgs { - generics: value.generics.clone(), schedule_config: value.schedule_config.clone(), } } @@ -74,52 +62,3 @@ impl RewriteAttribute for SystemArgs { expanded_attrs } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::macro_api::with_plugin::WithPlugin; - use crate::test_util::macros::*; - use darling::ast::NestedMeta; - use internal_test_proc_macro::xtest; - use internal_test_util::vec_spread; - use quote::ToTokens; - use syn::parse_quote; - - #[xtest] - fn test_expand_back_into_args() -> syn::Result<()> { - let args = vec![quote! { schedule = Update }]; - println!("checking args: {}", quote! { #(#args),*}); - assert_vec_args_expand!(plugin!(parse_quote!(Test)), SystemArgs, args); - Ok(()) - } - - #[xtest] - fn test_expand_attrs_global() -> syn::Result<()> { - let args: NestedMeta = parse_quote! {_( - plugin = Test, - schedule = Update, - )}; - let args = WithPlugin::::from_nested_meta(&args)?; - println!( - "{}", - args.inner.expand_attrs(&args.plugin()).to_token_stream() - ); - assert_eq!( - args.inner - .expand_attrs(&args.plugin()) - .to_token_stream() - .to_string(), - ExpandAttrs { - use_items: vec![], - attrs: vec_spread![tokens::auto_add_systems( - args.plugin(), - (&args.inner).into() - ),] - } - .to_token_stream() - .to_string() - ); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index e91c1375..22070e54 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -8,4 +8,3 @@ pub(super) mod mixins; pub(crate) mod q; pub(crate) mod qq; pub mod schedule_config; -pub mod with_plugin; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/with_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/with_plugin.rs deleted file mode 100644 index 87a2df4c..00000000 --- a/crates/bevy_auto_plugin_shared/src/macro_api/with_plugin.rs +++ /dev/null @@ -1,97 +0,0 @@ -use crate::codegen::tokens::{ArgsBackToTokens, ArgsWithPlugin}; -use crate::codegen::with_target_path::ToTokensWithConcreteTargetPath; -use crate::macro_api::attributes::ItemAttributeArgs; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use darling::FromMeta; -use proc_macro2::{Ident, TokenStream as MacroStream}; -use quote::format_ident; -use std::hash::Hash; -use syn::Path; -use syn::parse::Parse; - -pub trait PluginBound: FromMeta + Parse + ToTokensWithConcreteTargetPath + Hash + Clone { - type Inner: ItemAttributeArgs; - fn inner(&self) -> &Self::Inner; - fn plugin(&self) -> &Path; - - fn _concat_ident_hash(&self, ident: &Ident) -> String { - use std::hash::{Hash, Hasher}; - let mut hasher = std::collections::hash_map::DefaultHasher::new(); - ident.hash(&mut hasher); - self.hash(&mut hasher); - format!("{:x}", hasher.finish()) - } - - fn _get_unique_ident(&self, prefix: Ident, ident: &Ident) -> Ident { - let hash = self._concat_ident_hash(ident); - format_ident!("{prefix}_{hash}") - } - - fn get_unique_ident(&self, ident: &Ident) -> Ident { - self._get_unique_ident(Self::Inner::global_build_prefix(), ident) - } -} - -#[derive(FromMeta, Debug, Clone, PartialEq, Hash)] -#[darling(derive_syn_parse)] -pub struct WithPlugin { - pub plugin: Path, - #[darling(flatten)] - pub inner: T, -} - -impl WithPlugin { - pub fn plugin(&self) -> NonEmptyPath { - NonEmptyPath::new(self.plugin.clone()).expect("expected plugin to be a valid path") - } -} - -impl From> for ArgsWithPlugin { - fn from(value: WithPlugin) -> Self { - ArgsWithPlugin::new(value.plugin(), value.inner) - } -} - -impl GenericsArgs for WithPlugin -where - T: GenericsArgs, -{ - const TURBOFISH: bool = T::TURBOFISH; - fn type_lists(&self) -> &[TypeList] { - self.inner.type_lists() - } -} - -impl ToTokensWithConcreteTargetPath for WithPlugin -where - T: ItemAttributeArgs, -{ - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut MacroStream, - target: &ConcreteTargetPath, - ) { - self.inner - .to_tokens_with_concrete_target_path(tokens, target) - } - - fn required_use_statements(&self) -> Vec { - self.inner.required_use_statements() - } -} - -impl PluginBound for WithPlugin -where - T: ItemAttributeArgs, -{ - type Inner = T; - fn inner(&self) -> &Self::Inner { - &self.inner - } - fn plugin(&self) -> &Path { - &self.plugin - } -} From 30ca6e0b9aaaadc50275d6f8b930f27c41d5922b Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 12:22:18 -0400 Subject: [PATCH 016/162] refactor: cleaning up several paths --- .../__private/expand/attr/auto_bind_plugin.rs | 58 +++-- .../src/__private/expand/attr/mod.rs | 199 +----------------- .../src/macro_api/attributes/mod.rs | 6 +- .../src/macro_api/composed.rs | 19 +- .../src/macro_api/mixins/generics/none.rs | 2 +- .../macro_api/mixins/generics/with_many.rs | 2 +- .../macro_api/mixins/generics/with_single.rs | 2 +- .../src/macro_api/mixins/with_plugin.rs | 2 +- .../src/macro_api/q.rs | 8 +- .../src/macro_api/qq.rs | 10 +- 10 files changed, 80 insertions(+), 228 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index 29f2b137..45e29369 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -1,35 +1,49 @@ -use crate::util::macros::compile_error_with; +use crate::__private::expand::attr; +use crate::macro_api::attributes::ItemAttribute; +use crate::macro_api::composed::Composed; +use crate::macro_api::context::Context; +use crate::macro_api::mixins::nothing::Nothing; +use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::syntax::extensions::item::ItemAttrsExt; +use crate::util::macros::{compile_error_with, ok_or_emit_with}; use proc_macro2::TokenStream as MacroStream; +use quote::ToTokens; +use syn::spanned::Spanned; -pub fn auto_bind_plugin_inner(attr: MacroStream, input: MacroStream) -> syn::Result { - use crate::__private::expand::attr; - use crate::macro_api::with_plugin::WithPlugin; - use crate::syntax::extensions::item::ItemAttrsExt; - use proc_macro2::Span; - use quote::quote; - use syn::{Item, parse2}; +pub fn auto_bind_plugin_inner( + attr: MacroStream, + input: MacroStream, + context: Context, +) -> syn::Result { + // TODO: need to determine correct flow to maintain input tokens for errors + let mut item_attribute = ItemAttribute::, _>::from_attr_input( + attr, + input.clone(), + context, + ) + .map_err(|err| compile_error_with!(err, input.clone()))?; - let mut item = parse2::(input)?; - let args = parse2::>(attr)?; - let plugin = args.plugin; + let plugin_path = item_attribute.args.plugin(); + let mut item = item_attribute.input_item.ensure_ast_mut()?; + let mut attrs = item + .take_attrs() + .map_err(|err| syn::Error::new(item.span(), err))?; - let Ok(mut attrs) = item.take_attrs() else { - return Err(syn::Error::new( - Span::call_site(), - "auto_bind_plugin supports only functions, structs, or enums", - )); - }; - - attr::inject_plugin_arg_for_attributes(&mut attrs, &plugin); + attr::inject_plugin_arg_for_attributes(&mut attrs, plugin_path); let Ok(_) = item.put_attrs(attrs) else { unreachable!() }; - Ok(quote! { #item }) + Ok(item_attribute.input_item.to_token_stream()) } -pub fn auto_bind_plugin_outer(attr: MacroStream, input: MacroStream) -> MacroStream { +pub fn auto_bind_plugin_outer( + attr: MacroStream, + input: MacroStream, + context: Context, +) -> MacroStream { let og_input = input.clone(); - auto_bind_plugin_inner(attr, input).unwrap_or_else(|err| compile_error_with!(err, og_input)) + auto_bind_plugin_inner(attr, input, context) + .unwrap_or_else(|err| compile_error_with!(err, og_input)) } diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 114d0927..52384a2f 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,48 +1,28 @@ use crate::__private::attribute::RewriteAttribute; use crate::__private::auto_plugin_registry::_plugin_entry_block; use crate::codegen::with_target_path::{ToTokensIterItem, WithTargetPath}; +use crate::macro_api::attributes::ItemAttribute; +use crate::macro_api::attributes::ItemAttributeArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::composed::Composed; +use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::diagnostic::kind::item_kind; use darling::FromMeta; use proc_macro2::{Ident, Span, TokenStream as MacroStream}; use quote::{ToTokens, format_ident, quote}; +use std::hash::Hash; use syn::{Item, parse2}; use thiserror::Error; pub mod auto_bind_plugin; pub mod auto_plugin; -pub enum ArgParser { - SynParse2, - Custom(CustomParser), -} - -impl ArgParser { - pub fn parse(&self, attr: MacroStream, input: &mut MacroStream) -> syn::Result { - match self { - ArgParser::SynParse2 => parse2::(attr), - ArgParser::Custom(custom) => custom.parse(attr, input), - } - } -} - -pub enum CustomParser { - AttrOnly(fn(MacroStream) -> syn::Result), - AttrInput(fn(MacroStream, &mut MacroStream) -> syn::Result), -} - -impl CustomParser { - pub fn parse(&self, attr: MacroStream, input: &mut MacroStream) -> syn::Result { - match self { - CustomParser::AttrOnly(f) => f(attr), - CustomParser::AttrInput(f) => f(attr, input), - } - } -} - -fn body( +fn body( body: impl Fn(MacroStream) -> MacroStream, -) -> impl Fn(&Ident, T, &Item) -> syn::Result { +) -> impl Fn(&Ident, ItemAttribute, R>, &Item) -> syn::Result +where + T: ItemAttributeArgs + Hash, +{ move |ident, params, _item| { let unique_ident = params.get_unique_ident(ident); let plugin = params.plugin().clone(); @@ -78,165 +58,6 @@ fn body( } } -#[derive(Error, Debug)] -enum ProcAttributeError { - #[error("Failed to parse item: {0}")] - ParseItem(syn::Error), - #[error("Failed to resolve ident: {0}")] - ResolveIdent(syn::Error), - #[error("Failed to parse attr or input: {0}")] - ParseAttrOrInput(syn::Error), - #[error("Failed to generate body: {0}")] - GenerateBody(syn::Error), -} - -impl ProcAttributeError { - fn err(&self) -> &syn::Error { - match self { - ProcAttributeError::ParseItem(err) => err, - ProcAttributeError::ResolveIdent(err) => err, - ProcAttributeError::ParseAttrOrInput(err) => err, - ProcAttributeError::GenerateBody(err) => err, - } - } -} - -impl ToTokens for ProcAttributeError { - fn to_tokens(&self, tokens: &mut MacroStream) { - tokens.extend(self.err().to_compile_error()); - } -} - -fn proc_attribute_core( - attr: impl Into, - // this is the only way we can strip out non-derive based attribute helpers - input: &mut MacroStream, - resolve_ident: fn(&Item) -> syn::Result<&Ident>, - parse_attr_input: ArgParser, - body: F, -) -> Result -where - A: PluginBound, - F: FnOnce(&Ident, A, &Item) -> syn::Result, -{ - let attr = attr.into(); - - // need to clone input so we can pass through input untouched for optimal IDE support - let item: Item = parse2(input.clone()).map_err(ProcAttributeError::ParseItem)?; - - let ident = resolve_ident(&item) - .map_err(|err| { - let message = format!( - "Attribute macro is not allowed on {}: {err}", - item_kind(&item) - ); - // make sure the call_site span is used instead so the user knows what attribute caused the error - syn::Error::new(Span::call_site(), message) - }) - .map_err(ProcAttributeError::ResolveIdent)?; - - let args = parse_attr_input - .parse(attr, input) - .map_err(ProcAttributeError::ParseAttrOrInput)?; - - let output = body(ident, args, &item).map_err(ProcAttributeError::GenerateBody)?; - - Ok(quote! { - #input - #output - }) -} - -fn proc_attribute_inner( - attr: impl Into, - input: impl Into, - resolve_ident: fn(&Item) -> syn::Result<&Ident>, - parse_attr_input: ArgParser, - body: F, -) -> MacroStream -where - A: PluginBound, - F: FnOnce(&Ident, A, &Item) -> syn::Result, -{ - let attr = attr.into(); - let mut input = input.into(); - - match proc_attribute_core(attr, &mut input, resolve_ident, parse_attr_input, body) { - Ok(res) => res, - Err(err) => quote! { - #err - #input - }, - } -} - -/// Maps [`crate::syntax::analysis::item::IdentFromItemResult`] to [`syn::Result<&Ident>`] -fn resolve_item_ident(item: &Item) -> syn::Result<&Ident> { - T::Inner::resolve_item_ident(item).map_err(syn::Error::from) -} - -pub fn proc_attribute_outer( - attr: impl Into, - input: impl Into, -) -> MacroStream -where - T: PluginBound, -{ - proc_attribute_inner( - attr, - input, - resolve_item_ident::, - ArgParser::::SynParse2, - body(|input| quote! { app #input ; }), - ) -} - -pub fn proc_attribute_with_parser_outer( - attr: impl Into, - input: impl Into, - parser: ArgParser, -) -> MacroStream -where - T: PluginBound, -{ - proc_attribute_inner( - attr, - input, - resolve_item_ident::, - parser, - body(|input| quote! { app #input ; }), - ) -} - -pub fn proc_attribute_outer_call_fn( - attr: impl Into, - input: impl Into, -) -> MacroStream -where - T: PluginBound, -{ - proc_attribute_inner( - attr, - input, - resolve_item_ident::, - ArgParser::::SynParse2, - body(|input| quote! { #input(app) ; }), - ) -} - -fn proc_attribute_rewrite_inner( - attr: MacroStream, - input: MacroStream, -) -> syn::Result { - use crate::macro_api::with_plugin::WithPlugin; - let args = parse2::>(attr)?; - let args_ts = args.inner.expand_attrs(&args.plugin()); - Ok(quote! { - #args_ts - #input - }) -} - pub fn proc_attribute_rewrite_outer( attr: MacroStream, input: MacroStream, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index cd541f9b..26ab543d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -109,7 +109,7 @@ impl ItemAttribute where T: ItemAttributeArgs + Hash, { - fn _concat_ident_hash(&self, ident: &Ident) -> String { + pub fn _concat_ident_hash(&self, ident: &Ident) -> String { use std::hash::{Hash, Hasher}; let mut hasher = std::collections::hash_map::DefaultHasher::new(); ident.hash(&mut hasher); @@ -117,12 +117,12 @@ where format!("{:x}", hasher.finish()) } - fn _get_unique_ident(&self, prefix: Ident, ident: &Ident) -> Ident { + pub fn _get_unique_ident(&self, prefix: Ident, ident: &Ident) -> Ident { let hash = self._concat_ident_hash(ident); format_ident!("{prefix}_{hash}") } - fn get_unique_ident(&self, ident: &Ident) -> Ident { + pub fn get_unique_ident(&self, ident: &Ident) -> Ident { self._get_unique_ident(T::global_build_prefix(), ident) } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 7ad7d0cd..67f8bb1f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -1,3 +1,4 @@ +use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; use crate::macro_api::context::Context; use crate::macro_api::macro_paths::MacroPathProvider; use crate::macro_api::mixins::Mixin; @@ -10,11 +11,12 @@ use darling::ast::NestedMeta; use proc_macro2::TokenStream; use quote::ToTokens; use std::collections::HashSet; +use std::hash::Hash; use syn::parse::{Parse, ParseStream}; use syn::parse_quote; use syn::punctuated::Punctuated; -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq, Hash)] pub struct Composed { pub base: CBase, pub plugin: MPlugin, @@ -96,6 +98,21 @@ where } } +impl AttributeIdent for Composed +where + T: AttributeIdent, +{ + const IDENT: &'static str = T::IDENT; +} + +impl ItemAttributeArgs for Composed +where + T: ItemAttributeArgs, + P: Hash + Clone, + G: Hash + Clone, +{ +} + impl Composed { pub fn args(&self) -> &CBase { &self.base diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs index 3913f503..8662800a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs @@ -6,7 +6,7 @@ use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::spanned::Spanned; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq, Hash)] pub struct WithNoGenerics {} impl WithNoGenerics { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs index 65ea2925..96c4f3ca 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs @@ -5,7 +5,7 @@ use darling::FromMeta; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; -#[derive(Debug, Clone, Default, FromMeta)] +#[derive(Debug, Clone, Default, FromMeta, PartialEq, Hash)] #[darling(derive_syn_parse)] pub struct WithZeroOrManyGenerics { #[darling(multiple, default, rename = "generics")] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index 49b184f6..99160fc5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -5,7 +5,7 @@ use darling::FromMeta; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; -#[derive(Debug, Clone, Default, FromMeta)] +#[derive(Debug, Clone, Default, FromMeta, PartialEq, Hash)] #[darling(derive_syn_parse)] pub struct WithZeroOrOneGenerics { #[darling(default, rename = "generics")] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs index d1226a41..7dce1352 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs @@ -3,7 +3,7 @@ use darling::FromMeta; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; -#[derive(Debug, Clone, FromMeta)] +#[derive(Debug, Clone, FromMeta, PartialEq, Hash)] #[darling(derive_syn_parse)] pub struct WithPlugin { #[darling(rename = "plugin")] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 9fb7a4df..aeec9735 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -12,10 +12,10 @@ use proc_macro2::TokenStream; use quote::{ToTokens, quote}; /// for codegen attaching to bevy app -struct Q<'a, T> { - args: &'a T, - context: &'a Context, - input_item: &'a InputItem, +pub(crate) struct Q<'a, T> { + pub(crate) args: &'a T, + pub(crate) context: &'a Context, + pub(crate) input_item: &'a InputItem, } impl ToTokens diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 157a6c78..194cf0b2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -15,10 +15,10 @@ use syn::parse_quote; use syn::spanned::Spanned; /// for codegen re-emitting macro args -struct QQ<'a, T> { - args: &'a T, - context: &'a Context, - input_item: &'a mut InputItem, +pub(crate) struct QQ<'a, T> { + pub(crate) args: &'a T, + pub(crate) context: &'a Context, + pub(crate) input_item: &'a mut InputItem, } impl QQ<'_, T> @@ -26,7 +26,7 @@ where T: MacroPathProvider, Self: ToTokens, { - fn inject_attribute_macro(&mut self) -> syn::Result<()> { + pub fn inject_attribute_macro(&mut self) -> syn::Result<()> { let args = self.to_token_stream(); self.input_item.map_ast(|item| { let macro_path = T::macro_path(self.context); From 3b034363730c7b6aaadb9cfd50dac59b8bdca287 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 12:57:34 -0400 Subject: [PATCH 017/162] fix: correct `add_systems` call by adding missing `app` invocation --- crates/bevy_auto_plugin_shared/src/macro_api/q.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index aeec9735..ec3fecf4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -26,7 +26,7 @@ impl ToTokens let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { - .add_systems(#schedule, #concrete_path #config_tokens) + app.add_systems(#schedule, #concrete_path #config_tokens) }}); } } From 5736bcbe5a593bd7a75fdd30b185545924359d57 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 12:58:26 -0400 Subject: [PATCH 018/162] fix: add missing semicolons in `add_systems` and `add_plugins` calls --- crates/bevy_auto_plugin_shared/src/macro_api/q.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index ec3fecf4..f07ac9c1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -26,7 +26,7 @@ impl ToTokens let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { - app.add_systems(#schedule, #concrete_path #config_tokens) + app.add_systems(#schedule, #concrete_path #config_tokens); }}); } } @@ -75,15 +75,15 @@ impl ToTokens for concrete_path in self.args.concrete_paths() { if let Some(expr) = &self.args.args.base.init.expr { tokens.extend(quote! { |app| { - app.add_plugins({ let plugin: #concrete_path = #expr; plugin }) + app.add_plugins({ let plugin: #concrete_path = #expr; plugin }); }}); } else if self.args.args.base.init.present { tokens.extend(quote! { |app| { - app.add_plugins(#concrete_path::default()) + app.add_plugins(#concrete_path::default()); }}); } else { tokens.extend(quote! { |app| { - app.add_plugins(#concrete_path) + app.add_plugins(#concrete_path); }}); } } From d9039b207a0c8af91b6e35de8a7905eb707d02b8 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 13:52:32 -0400 Subject: [PATCH 019/162] feat: add `prelude` modules for `generics` and `mixins` --- .../src/macro_api/mixins/generics/mod.rs | 7 +++++++ crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs index 075ccf8a..374cb7cd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs @@ -7,3 +7,10 @@ pub mod with_single; pub trait HasGenerics { fn generics(&self) -> &[TypeList]; } + +pub mod prelude { + use super::*; + pub use none::*; + pub use with_many::*; + pub use with_single::*; +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs index 473bd4cb..54589a3c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs @@ -27,3 +27,10 @@ where ::from_list(items) } } + +pub mod prelude { + use super::*; + pub use generics::*; + pub use nothing::*; + pub use with_plugin::*; +} From 67da324560c8c219c512d595005225f0ff997185 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 13:55:14 -0400 Subject: [PATCH 020/162] refactor: replace `ToTokens` implementations with `RequiredUseQTokens` and refactor `app` invocations --- .../src/macro_api/q.rs | 143 +++++++++++------- 1 file changed, 87 insertions(+), 56 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index f07ac9c1..e6dd1e16 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -16,23 +16,42 @@ pub(crate) struct Q<'a, T> { pub(crate) args: &'a T, pub(crate) context: &'a Context, pub(crate) input_item: &'a InputItem, + pub(crate) app_param: &'a syn::Ident, } -impl ToTokens +pub trait RequiredUseQTokens { + fn required_uses(&self) -> Vec { + vec![] + } + fn to_tokens(&self, tokens: &mut TokenStream); +} + +impl<'a, T> ToTokens for Q<'a, T> +where + Self: RequiredUseQTokens, +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.extend(self.required_uses()); + RequiredUseQTokens::to_tokens(self, tokens); + } +} + +impl RequiredUseQTokens for Q<'_, ItemAttribute, AllowFn>> { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; let schedule = &self.args.args.base.schedule_config.schedule; let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - app.add_systems(#schedule, #concrete_path #config_tokens); - }}); + tokens.extend(quote! { + #app_param.add_systems(#schedule, #concrete_path #config_tokens); + }); } } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute< @@ -42,27 +61,29 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - app.add_message::<#concrete_path>(); - }}); + tokens.extend(quote! { + #app_param.add_message::<#concrete_path>(); + }); } } } -impl ToTokens +impl RequiredUseQTokens for Q<'_, ItemAttribute, AllowFn>> { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - app.add_observer::<#concrete_path>(); - }}); + tokens.extend(quote! { + #app_param.add_observer::<#concrete_path>(); + }); } } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute< @@ -72,25 +93,26 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; for concrete_path in self.args.concrete_paths() { if let Some(expr) = &self.args.args.base.init.expr { - tokens.extend(quote! { |app| { - app.add_plugins({ let plugin: #concrete_path = #expr; plugin }); - }}); + tokens.extend(quote! { + #app_param.add_plugins({ let plugin: #concrete_path = #expr; plugin }); + }); } else if self.args.args.base.init.present { - tokens.extend(quote! { |app| { - app.add_plugins(#concrete_path::default()); - }}); + tokens.extend(quote! { + #app_param.add_plugins(#concrete_path::default()); + }); } else { - tokens.extend(quote! { |app| { - app.add_plugins(#concrete_path); - }}); + tokens.extend(quote! { + #app_param.add_plugins(#concrete_path); + }); } } } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute< @@ -100,40 +122,43 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - app.init_resource::<#concrete_path>(); - }}); + tokens.extend(quote! { + #app_param.init_resource::<#concrete_path>(); + }); } } } -impl ToTokens +impl RequiredUseQTokens for Q<'_, ItemAttribute, AllowStructOrEnum>> { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; let target = &self.args.target; - tokens.extend(quote! { |app| { - app.init_state::<#target>(); - }}); + tokens.extend(quote! { + #app_param.init_state::<#target>(); + }); } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute, AllowStructOrEnum>, > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; let target = &self.args.target; - tokens.extend(quote! { |app| { - app.init_sub_state::<#target>(); - }}); + tokens.extend(quote! { + #app_param.init_sub_state::<#target>(); + }); } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute< @@ -143,15 +168,16 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { - app.insert_resource(#concrete_path::default()); + #app_param.insert_resource(#concrete_path::default()); }}); } } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute< @@ -161,17 +187,18 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; for concrete_path in self.args.concrete_paths() { let bevy_state = crate::__private::paths::state::root_path(); - tokens.extend(quote! { |app| { - app.register_type :: < #bevy_state::prelude::State< #concrete_path > >(); - app.register_type :: < #bevy_state::prelude::NextState< #concrete_path > >(); - }}); + tokens.extend(quote! { + #app_param.register_type :: < #bevy_state::prelude::State< #concrete_path > >(); + #app_param.register_type :: < #bevy_state::prelude::NextState< #concrete_path > >(); + }); } } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute< @@ -181,15 +208,16 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - app.register_type::<#concrete_path>(); - }}); + tokens.extend(quote! { + #app_param.register_type::<#concrete_path>(); + }); } } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute< @@ -199,15 +227,16 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - #concrete_path(app); - }}); + tokens.extend(quote! { + #concrete_path(#app_param); + }); } } } -impl ToTokens +impl RequiredUseQTokens for Q< '_, ItemAttribute< @@ -217,6 +246,7 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; let args = &self.args.args; let generics = args.generics(); let base = &self.args.args.base; @@ -248,21 +278,21 @@ impl ToTokens } if !entries.is_empty() { tokens.extend(quote! { - .configure_sets(#schedule, (#(#entries),*) #chained #config_tokens) + #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); }); } } else { // struct if generics.is_empty() { tokens.extend(quote! { - .configure_sets(#schedule, #concrete_path #config_tokens) + #app_param.configure_sets(#schedule, #concrete_path #config_tokens); }); } else { // TODO: generics are kind of silly here // but if someone does use them we'll assume its just a marker type // that can be initialized via `Default::default()` tokens.extend(quote! { - .configure_sets(#schedule, #concrete_path::default() #config_tokens) + #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); }); } } @@ -277,6 +307,7 @@ impl ToTokens > { fn to_tokens(&self, tokens: &mut TokenStream) { + let app_param = self.app_param; let args = &self.args.args.base; for concrete_path in self.args.concrete_paths() { let name = args @@ -294,9 +325,9 @@ impl ToTokens // .replace(" ", "") }); let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); - tokens.extend(quote! { |app| { - app.register_required_components_with::<#concrete_path, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new(#name)); - }}); + tokens.extend(quote! { + #app_param.register_required_components_with::<#concrete_path, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new(#name)); + }); } } } From bf032ef8d521cf34a198a730d3a68c930d57d9f2 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 16:16:52 -0400 Subject: [PATCH 021/162] refactor: simplify attribute handling by replacing `WithPlugin` with `Composed` and streamline `to_tokens` implementations --- .../src/__private/expand/attr/mod.rs | 130 +++++----- .../src/macro_api/attributes/mod.rs | 37 ++- .../src/macro_api/context.rs | 1 + .../src/macro_api/macro_paths.rs | 21 ++ .../src/macro_api/q.rs | 224 ++++++++---------- .../src/test_util/test_params.rs | 20 +- 6 files changed, 223 insertions(+), 210 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 52384a2f..c639afe2 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,55 +1,40 @@ -use crate::__private::attribute::RewriteAttribute; use crate::__private::auto_plugin_registry::_plugin_entry_block; -use crate::codegen::with_target_path::{ToTokensIterItem, WithTargetPath}; -use crate::macro_api::attributes::ItemAttribute; -use crate::macro_api::attributes::ItemAttributeArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::attributes::{ItemAttribute, ItemAttributeInput, PluginCap}; +use crate::macro_api::attributes::{ItemAttributeArgs, ItemAttributeParse}; use crate::macro_api::composed::Composed; -use crate::macro_api::mixins::with_plugin::WithPlugin; -use crate::syntax::diagnostic::kind::item_kind; -use darling::FromMeta; -use proc_macro2::{Ident, Span, TokenStream as MacroStream}; +use crate::macro_api::context::Context; +use crate::macro_api::mixins::prelude::*; +use crate::macro_api::q::*; +use crate::util::macros::ok_or_emit_with; +use proc_macro2::{Ident, TokenStream as MacroStream}; use quote::{ToTokens, format_ident, quote}; use std::hash::Hash; -use syn::{Item, parse2}; -use thiserror::Error; +use syn::Item; +use syn::parse::Parse; pub mod auto_bind_plugin; pub mod auto_plugin; fn body( body: impl Fn(MacroStream) -> MacroStream, -) -> impl Fn(&Ident, ItemAttribute, R>, &Item) -> syn::Result +) -> impl Fn(&Ident, Q<'_, ItemAttribute, R>>) -> syn::Result where T: ItemAttributeArgs + Hash, + G: Hash + Clone, + for<'a> Q<'a, ItemAttribute, R>>: ToTokens, { - move |ident, params, _item| { - let unique_ident = params.get_unique_ident(ident); - let plugin = params.plugin().clone(); - let with_target_path = WithTargetPath::from((ident.into(), params)); - let output = with_target_path - .to_tokens_iter_items() - .enumerate() - .map( - |( - ix, - ToTokensIterItem { - required_uses, - main_tokens: tokens, - }, - )| { - let body = body(tokens); - let expr: syn::ExprClosure = syn::parse_quote!(|app| { - #(#required_uses)* - #body - }); - // required for generics - let unique_ident = format_ident!("{unique_ident}_{ix}"); - let output = _plugin_entry_block(&unique_ident, &plugin, &expr); - Ok(output) - }, - ) - .collect::>()?; + move |ident, params| { + let app_param = ¶ms.app_param; + let unique_ident = params.args.get_unique_ident(ident); + let plugin = params.args.plugin_path().clone(); + let body = body(params.to_token_stream()); + let expr: syn::ExprClosure = syn::parse_quote!(|#app_param| { + #body + }); + // required for generics + let unique_ident = format_ident!("{unique_ident}"); + let output = _plugin_entry_block(&unique_ident, &plugin, &expr); assert!( !output.is_empty(), "No plugin entry points were generated for ident: {ident}" @@ -58,11 +43,25 @@ where } } -pub fn proc_attribute_rewrite_outer( - attr: MacroStream, - input: MacroStream, -) -> MacroStream { - proc_attribute_rewrite_inner::(attr, input).unwrap_or_else(|err| err.to_compile_error()) +fn proc_attribute_outer(attr: MacroStream, input: MacroStream) -> MacroStream +where + T: ItemAttributeParse + ItemAttributeInput, + for<'a> Q<'a, T>: ToTokens, +{ + let args = ok_or_emit_with!( + T::from_attr_input_with_context(attr, input.clone(), Context::default()), + input + ); + let input = args.input_item(); + let after_item_tokens = Q::from_args(&args).to_token_stream(); + quote! { + #input + #after_item_tokens + } +} + +fn proc_attribute_rewrite_outer(attr: MacroStream, input: MacroStream) -> MacroStream { + todo!() } pub fn inject_plugin_arg_for_attributes(attrs: &mut Vec, plugin: &syn::Path) { @@ -128,17 +127,6 @@ fn list_has_key(ml: &syn::MetaList, key: &str) -> bool { } } -macro_rules! gen_auto_attribute_outer_call_fns { - ( $( $fn:ident => $args:ty ),+ $(,)? ) => { - $( - #[inline] - pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { - proc_attribute_outer_call_fn::>(attr, input) - } - )+ - }; -} - macro_rules! gen_auto_attribute_outers { // Each item: fn_name => ArgsTy [using ] ( $( $fn:ident => $args:ty $(: parser = $parser:expr)? ),+ $(,)? ) => { @@ -151,7 +139,7 @@ macro_rules! gen_auto_attribute_outers { (@one $fn:ident, $args:ty) => { #[inline] pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { - proc_attribute_outer::>(attr, input) + proc_attribute_outer::<$args>(attr, input) } }; @@ -159,7 +147,7 @@ macro_rules! gen_auto_attribute_outers { (@one $fn:ident, $args:ty, $parser:expr) => { #[inline] pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { - proc_attribute_with_parser_outer::>(attr, input, $parser) + proc_attribute_with_parser_outer::<$args>(attr, input, $parser) } }; } @@ -175,24 +163,20 @@ macro_rules! gen_auto_outers { }; } -gen_auto_attribute_outer_call_fns! { - auto_run_on_build => RunOnBuildArgs, -} - gen_auto_attribute_outers! { - auto_register_type => RegisterTypeArgs, - auto_add_message => AddMessageArgs, - auto_init_resource => InitResourceArgs, - auto_insert_resource => InsertResourceArgs, - auto_init_state => InitStateArgs, - auto_init_sub_state => InitSubStateArgs, - auto_name => NameArgs, - auto_register_state_type => RegisterStateTypeArgs, - auto_add_system => AddSystemArgs, - auto_add_observer => AddObserverArgs, - auto_add_plugin => AddPluginArgs, - auto_configure_system_set => ConfigureSystemSetArgs: - parser = ArgParser::Custom(CustomParser::AttrInput(configure_system_set_args_from_attr_input)), + auto_run_on_build => RunOnBuild, + auto_register_type => RegisterType, + auto_add_message => AddMessage, + auto_init_resource => InitResource, + auto_insert_resource => InsertResource, + auto_init_state => InitState, + auto_init_sub_state => InitSubState, + auto_name => Name, + auto_register_state_type => RegisterStateType, + auto_add_system => AddSystem, + auto_add_observer => AddObserver, + auto_add_plugin => AddPlugin, + auto_configure_system_set => ConfigureSystemSet, } gen_auto_outers! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 26ab543d..190a0ef2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -2,6 +2,7 @@ use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; use crate::macro_api::mixins::generics::HasGenerics; +use crate::macro_api::mixins::nothing::Nothing; use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; @@ -9,7 +10,7 @@ use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use std::hash::Hash; use std::marker::PhantomData; -use syn::parse::Parse; +use syn::parse::{Parse, ParseStream}; use syn::spanned::Spanned; use syn::{Item, parse_quote, parse2}; @@ -127,6 +128,40 @@ where } } +pub trait ItemAttributeInput { + fn input_item(&self) -> &InputItem; +} + +impl ItemAttributeInput for ItemAttribute { + fn input_item(&self) -> &InputItem { + &self.input_item + } +} + +pub trait ItemAttributeParse { + fn from_attr_input_with_context( + attr: TokenStream, + input: TokenStream, + context: Context, + ) -> syn::Result + where + Self: Sized; +} + +impl ItemAttributeParse for ItemAttribute +where + T: Parse, + Resolver: IdentPathResolver, +{ + fn from_attr_input_with_context( + attr: TokenStream, + input: TokenStream, + context: Context, + ) -> syn::Result { + Self::from_attr_input(attr, input, context) + } +} + impl ItemAttribute where T: Parse, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context.rs index 5296ab43..233eeda8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/context.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/context.rs @@ -1,5 +1,6 @@ use crate::macro_api::macro_paths::MacroPaths; +#[derive(Debug, Clone, Default)] pub struct Context { pub macros: MacroPaths, } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs index cf0d0aa8..491371d2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs @@ -1,6 +1,8 @@ use crate::macro_api::attributes::prelude::*; use crate::macro_api::context::Context; +use syn::parse_quote; +#[derive(Debug, Clone)] pub struct MacroPaths { /// resolved absolute path to `auto_add_system` pub emit_add_system_macro: syn::Path, @@ -26,6 +28,25 @@ pub struct MacroPaths { pub emit_run_on_build_macro: syn::Path, } +impl Default for MacroPaths { + #[rustfmt::skip] + fn default() -> Self { + Self { + emit_add_system_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_system ), + emit_add_message_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_message ), + emit_add_observer_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_observer ), + emit_add_plugin_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_plugin ), + emit_init_resource_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_resource ), + emit_init_state_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_state ), + emit_init_sub_state_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_sub_state ), + emit_insert_resource_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_insert_resource ), + emit_register_state_type_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_register_state_type ), + emit_register_type_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_register_type ), + emit_run_on_build_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_run_on_build ), + } + } +} + pub trait MacroPathProvider { fn macro_path(context: &Context) -> &syn::Path; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index e6dd1e16..0dfd1648 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -1,29 +1,41 @@ use crate::macro_api::attributes::prelude::*; -use crate::macro_api::attributes::{AllowFn, AllowStructOrEnum, GenericsCap, ItemAttribute}; +use crate::macro_api::attributes::{ + AllowFn, AllowStructOrEnum, GenericsCap, ItemAttribute, ItemAttributeParse, +}; use crate::macro_api::composed::Composed; -use crate::macro_api::context::Context; -use crate::macro_api::input_item::InputItem; use crate::macro_api::mixins::generics::none::WithNoGenerics; use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; use crate::macro_api::mixins::generics::with_single::WithZeroOrOneGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::extensions::lit::LitExt; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ToTokens, format_ident, quote}; +use syn::parse::{Parse, ParseStream}; /// for codegen attaching to bevy app pub(crate) struct Q<'a, T> { pub(crate) args: &'a T, - pub(crate) context: &'a Context, - pub(crate) input_item: &'a InputItem, - pub(crate) app_param: &'a syn::Ident, + // TODO: maybe app params should just be part of another wrapper struct? + pub(crate) app_param: syn::Ident, +} + +impl Q<'_, T> +where + T: ItemAttributeParse, +{ + pub fn from_args(args: &T) -> Q { + Q:: { + args, + app_param: format_ident!("app"), + } + } } pub trait RequiredUseQTokens { fn required_uses(&self) -> Vec { vec![] } - fn to_tokens(&self, tokens: &mut TokenStream); + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident); } impl<'a, T> ToTokens for Q<'a, T> @@ -32,15 +44,15 @@ where { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.extend(self.required_uses()); - RequiredUseQTokens::to_tokens(self, tokens); + RequiredUseQTokens::to_tokens(self, tokens, &self.app_param); } } -impl RequiredUseQTokens - for Q<'_, ItemAttribute, AllowFn>> -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type AddSystem = + ItemAttribute, AllowFn>; +pub type QAddSystemArgs<'a> = Q<'a, AddSystem>; +impl RequiredUseQTokens for QAddSystemArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let schedule = &self.args.args.base.schedule_config.schedule; let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); for concrete_path in self.args.concrete_paths() { @@ -51,17 +63,11 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type AddMessage = + ItemAttribute, AllowStructOrEnum>; +pub type QAddMessageArgs<'a> = Q<'a, AddMessage>; +impl RequiredUseQTokens for QAddMessageArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.add_message::<#concrete_path>(); @@ -70,11 +76,11 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q<'_, ItemAttribute, AllowFn>> -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type AddObserver = + ItemAttribute, AllowFn>; +pub type QAddObserverArgs<'a> = Q<'a, AddObserver>; +impl RequiredUseQTokens for QAddObserverArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.add_observer::<#concrete_path>(); @@ -83,17 +89,11 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type AddPlugin = + ItemAttribute, AllowStructOrEnum>; +pub type QAddPluginArgs<'a> = Q<'a, AddPlugin>; +impl RequiredUseQTokens for QAddPluginArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { if let Some(expr) = &self.args.args.base.init.expr { tokens.extend(quote! { @@ -112,17 +112,13 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type InitResource = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QInitResourceArgs<'a> = Q<'a, InitResource>; +impl RequiredUseQTokens for QInitResourceArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.init_resource::<#concrete_path>(); @@ -131,11 +127,11 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q<'_, ItemAttribute, AllowStructOrEnum>> -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type InitState = + ItemAttribute, AllowStructOrEnum>; +pub type QInitStateArgs<'a> = Q<'a, InitState>; +impl RequiredUseQTokens for QInitStateArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { #app_param.init_state::<#target>(); @@ -143,14 +139,11 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type InitSubState = + ItemAttribute, AllowStructOrEnum>; +pub type QInitSubStateArgs<'a> = Q<'a, InitSubState>; +impl RequiredUseQTokens for QInitSubStateArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { #app_param.init_sub_state::<#target>(); @@ -158,17 +151,13 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type InsertResource = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QInsertResourceArgs<'a> = Q<'a, InsertResource>; +impl RequiredUseQTokens for QInsertResourceArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { #app_param.insert_resource(#concrete_path::default()); @@ -177,17 +166,13 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type RegisterStateType = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QRegisterStateTypeArgs<'a> = Q<'a, RegisterStateType>; +impl RequiredUseQTokens for QRegisterStateTypeArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { let bevy_state = crate::__private::paths::state::root_path(); tokens.extend(quote! { @@ -198,17 +183,13 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type RegisterType = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QRegisterTypeArgs<'a> = Q<'a, RegisterType>; +impl RequiredUseQTokens for QRegisterTypeArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.register_type::<#concrete_path>(); @@ -217,17 +198,11 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type RunOnBuild = + ItemAttribute, AllowStructOrEnum>; +pub type QRunOnBuildArgs<'a> = Q<'a, RunOnBuild>; +impl RequiredUseQTokens for QRunOnBuildArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #concrete_path(#app_param); @@ -236,17 +211,13 @@ impl RequiredUseQTokens } } -impl RequiredUseQTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type ConfigureSystemSet = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QConfigureSystemSetArgs<'a> = Q<'a, ConfigureSystemSet>; +impl RequiredUseQTokens for QConfigureSystemSetArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args; let generics = args.generics(); let base = &self.args.args.base; @@ -300,14 +271,11 @@ impl RequiredUseQTokens } } -impl ToTokens - for Q< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let app_param = self.app_param; +pub type Name = + ItemAttribute, AllowStructOrEnum>; +pub type QNameArgs<'a> = Q<'a, Name>; +impl RequiredUseQTokens for QNameArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args.base; for concrete_path in self.args.concrete_paths() { let name = args diff --git a/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs b/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs index ab56da1a..d5f399ac 100644 --- a/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs +++ b/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs @@ -1,7 +1,9 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::prelude::*; -use crate::macro_api::with_plugin::WithPlugin; +use crate::macro_api::composed::Composed; +use crate::macro_api::mixins::nothing::Nothing; +use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::validated::non_empty_path::NonEmptyPath; use anyhow::anyhow; use darling::ast::NestedMeta; @@ -63,18 +65,19 @@ pub(crate) fn _inject_derive( } #[derive(Debug, Clone)] -pub(crate) struct TestParams { - pub args: WithPlugin, +pub(crate) struct TestParams { + pub args: Composed, pub expected_derives: ExpandAttrs, pub expected_reflect: ExpandAttrs, pub expected_extras: ExpandAttrs, } -impl TestParams +impl TestParams where for<'a> RegisterTypeArgs: From<&'a T>, + T: FromMeta + Clone + RewriteAttribute, { - pub(crate) fn new(args: WithPlugin) -> Self { + pub(crate) fn new(args: Composed) -> Self { Self { args, expected_derives: ExpandAttrs::default(), @@ -84,12 +87,12 @@ where } #[allow(dead_code)] pub(crate) fn from_list(nested_metas: &[NestedMeta]) -> syn::Result { - let args = WithPlugin::::from_list(nested_metas)?; + let args = Composed::::from_list(nested_metas)?; Ok(Self::new(args)) } #[allow(dead_code)] pub(crate) fn from_nested_meta(nested_meta: NestedMeta) -> syn::Result { - let args = WithPlugin::::from_nested_meta(&nested_meta)?; + let args = Composed::::from_nested_meta(&nested_meta)?; Ok(Self::new(args)) } @@ -132,9 +135,10 @@ where /// calling order matters pub(crate) fn with_register(mut self) -> Self { + let plugin_path = NonEmptyPath::new(self.args.plugin().clone()).expect("bad plugin path"); self.expected_extras.attrs.insert( 0, - tokens::auto_register_type(self.args.plugin(), (&self.args.inner).into()), + tokens::auto_register_type(plugin_path, (&self.args.base).into()), ); self } From 2719decfd367594c2e9a1adf3c2570a07dc1eb54 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 16:20:58 -0400 Subject: [PATCH 022/162] fix: add `Mixin` constraint to `test_params` construction function --- crates/bevy_auto_plugin_shared/src/test_util/test_params.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs b/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs index d5f399ac..7b18b3bb 100644 --- a/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs +++ b/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs @@ -2,6 +2,7 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::prelude::*; use crate::macro_api::composed::Composed; +use crate::macro_api::mixins::Mixin; use crate::macro_api::mixins::nothing::Nothing; use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::validated::non_empty_path::NonEmptyPath; @@ -76,6 +77,7 @@ impl TestParams where for<'a> RegisterTypeArgs: From<&'a T>, T: FromMeta + Clone + RewriteAttribute, + G: Mixin + Clone, { pub(crate) fn new(args: Composed) -> Self { Self { From a30db97560a31dd120ae9d1535e4429d69a68784 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 16:28:45 -0400 Subject: [PATCH 023/162] refactor: remove `ArgsBackToTokens` implementations across rewrite attributes --- .../attributes/rewrites/auto_component.rs | 20 ------------------- .../attributes/rewrites/auto_event.rs | 19 ------------------ .../attributes/rewrites/auto_message.rs | 17 ---------------- .../attributes/rewrites/auto_resource.rs | 20 ------------------- .../attributes/rewrites/auto_states.rs | 20 ------------------- .../attributes/rewrites/auto_system.rs | 9 --------- 6 files changed, 105 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index 8241df47..30ea3ed8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -39,26 +39,6 @@ impl<'a> From<&'a ComponentArgs> for NameArgs { } } -impl ArgsBackToTokens for ComponentArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut items = vec![]; - items.extend(self.generics().to_attribute_arg_vec_tokens()); - if self.derive.present { - items.push(self.derive.to_outer_tokens("derive")); - } - if self.reflect.present { - items.push(self.reflect.to_outer_tokens("reflect")); - } - if self.register { - items.push(quote!(register)); - } - if self.auto_name.present { - items.push(self.auto_name.to_outer_tokens("auto_name")); - } - tokens.extend(quote! { #(#items),* }); - } -} - impl RewriteAttribute for ComponentArgs { fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { let mut args = Vec::new(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 0561c6ec..5bef1a6d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -52,25 +52,6 @@ impl<'a> From<&'a EventArgs> for RegisterTypeArgs { } } -impl ArgsBackToTokens for EventArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut items = vec![]; - let target = self.target; - items.push(quote! { target(#target) }); - items.extend(self.generics().to_attribute_arg_vec_tokens()); - if self.derive.present { - items.push(self.derive.to_outer_tokens("derive")); - } - if self.reflect.present { - items.push(self.reflect.to_outer_tokens("reflect")); - } - if self.register { - items.push(quote!(register)); - } - tokens.extend(quote! { #(#items),* }); - } -} - impl RewriteAttribute for EventArgs { fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { let mut args = Vec::new(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 358bbc68..f1648c00 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -35,23 +35,6 @@ impl<'a> From<&'a MessageArgs> for AddMessageArgs { } } -impl ArgsBackToTokens for MessageArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut items = vec![]; - items.extend(self.generics().to_attribute_arg_vec_tokens()); - if self.derive.present { - items.push(self.derive.to_outer_tokens("derive")); - } - if self.reflect.present { - items.push(self.reflect.to_outer_tokens("reflect")); - } - if self.register { - items.push(quote!(register)); - } - tokens.extend(quote! { #(#items),* }); - } -} - impl RewriteAttribute for MessageArgs { fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { let mut args = Vec::new(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 8b1b6d5c..c9998935 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -36,26 +36,6 @@ impl<'a> From<&'a ResourceArgs> for InitResourceArgs { } } -impl ArgsBackToTokens for ResourceArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut items = vec![]; - items.extend(self.generics().to_attribute_arg_vec_tokens()); - if self.derive.present { - items.push(self.derive.to_outer_tokens("derive")); - } - if self.reflect.present { - items.push(self.reflect.to_outer_tokens("reflect")); - } - if self.register { - items.push(quote!(register)); - } - if self.init { - items.push(quote!(init)); - } - tokens.extend(quote! { #(#items),* }); - } -} - impl RewriteAttribute for ResourceArgs { fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { let mut args = Vec::new(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 1548b119..aea439a4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -35,26 +35,6 @@ impl<'a> From<&'a StatesArgs> for InitStateArgs { } } -impl ArgsBackToTokens for StatesArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut items = vec![]; - items.extend(self.generics().to_attribute_arg_vec_tokens()); - if self.derive.present { - items.push(self.derive.to_outer_tokens("derive")); - } - if self.reflect.present { - items.push(self.reflect.to_outer_tokens("reflect")); - } - if self.register { - items.push(quote!(register)); - } - if self.init { - items.push(quote!(init)); - } - tokens.extend(quote! { #(#items),* }); - } -} - impl RewriteAttribute for StatesArgs { fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { let mut args = Vec::new(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index a4a73f5d..7a94db40 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -35,15 +35,6 @@ impl<'a> From<&'a SystemArgs> for AddSystemArgs { } } -impl ArgsBackToTokens for SystemArgs { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream) { - let mut items = vec![]; - items.extend(self.generics().to_attribute_arg_vec_tokens()); - items.extend(self.schedule_config.to_inner_arg_tokens_vec()); - tokens.extend(quote! { #(#items),* }); - } -} - impl RewriteAttribute for SystemArgs { fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { let mut args = Vec::new(); From a731e3350dff53d2c5620d84b1dc05ea5674d1b8 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 16:43:16 -0400 Subject: [PATCH 024/162] fix: missing prelude --- crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs index 54589a3c..2cc746d5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs @@ -30,7 +30,7 @@ where pub mod prelude { use super::*; - pub use generics::*; + pub use generics::prelude::*; pub use nothing::*; pub use with_plugin::*; } From c47e5dff50017eaa1f7845be5ddbe769a22274e7 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 16:50:27 -0400 Subject: [PATCH 025/162] feat: add `prelude` module to simplify imports in `macro_api` --- crates/bevy_auto_plugin_shared/src/macro_api/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 22070e54..43f38f9a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -8,3 +8,11 @@ pub(super) mod mixins; pub(crate) mod q; pub(crate) mod qq; pub mod schedule_config; + +pub(crate) mod prelude { + use super::*; + pub use attributes::*; + pub use composed::*; + pub use mixins::prelude::*; + pub use qq::*; +} From 41f1159e9f4a77fb1df3d6698fb1f83a20788b2a Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 16:51:08 -0400 Subject: [PATCH 026/162] refactor: add QQ ToTokens for each rewrite attribute --- .../macro_api/attributes/rewrites/auto_component.rs | 13 +++++++++++-- .../src/macro_api/attributes/rewrites/auto_event.rs | 11 ++++++++++- .../macro_api/attributes/rewrites/auto_message.rs | 13 +++++++++++-- .../macro_api/attributes/rewrites/auto_observer.rs | 11 +++++++++-- .../macro_api/attributes/rewrites/auto_resource.rs | 13 +++++++++++-- .../macro_api/attributes/rewrites/auto_states.rs | 13 +++++++++++-- .../macro_api/attributes/rewrites/auto_system.rs | 12 +++++++++--- 7 files changed, 72 insertions(+), 14 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index 30ea3ed8..5f21507c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -1,15 +1,15 @@ use crate::__private::attribute::RewriteAttribute; -use crate::codegen::tokens::ArgsBackToTokens; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::ast::flag_or_lit::FlagOrLit; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; -use quote::quote; +use quote::{ToTokens, quote}; use syn::parse_quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] @@ -78,3 +78,12 @@ impl RewriteAttribute for ComponentArgs { expanded_attrs } } + +impl ToTokens + for QQ< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) {} +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 5bef1a6d..04cc247f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -1,9 +1,9 @@ use crate::__private::attribute::RewriteAttribute; -use crate::codegen::tokens::ArgsBackToTokens; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; @@ -91,3 +91,12 @@ impl RewriteAttribute for EventArgs { expanded_attrs } } + +impl ToTokens + for QQ< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) {} +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index f1648c00..1370e8d7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -1,15 +1,15 @@ use crate::__private::attribute::RewriteAttribute; -use crate::codegen::tokens::ArgsBackToTokens; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::actions::auto_add_message::AddMessageArgs; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -73,3 +73,12 @@ impl RewriteAttribute for MessageArgs { expanded_attrs } } + +impl ToTokens + for QQ< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) {} +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index f2c79f94..f46aeac4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -3,10 +3,11 @@ use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::prelude::*; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; -use proc_macro2::TokenStream as MacroStream; -use quote::quote; +use proc_macro2::{TokenStream as MacroStream, TokenStream}; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -46,3 +47,9 @@ impl RewriteAttribute for ObserverArgs { expanded_attrs } } + +impl ToTokens + for QQ<'_, ItemAttribute, AllowFn>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) {} +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index c9998935..0032e12e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -1,14 +1,14 @@ use crate::__private::attribute::RewriteAttribute; -use crate::codegen::tokens::ArgsBackToTokens; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; -use quote::quote; +use quote::{ToTokens, quote}; use syn::parse_quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] @@ -75,3 +75,12 @@ impl RewriteAttribute for ResourceArgs { expanded_attrs } } + +impl ToTokens + for QQ< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) {} +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index aea439a4..3d11cc97 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -1,14 +1,14 @@ use crate::__private::attribute::RewriteAttribute; -use crate::codegen::tokens::ArgsBackToTokens; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -70,3 +70,12 @@ impl RewriteAttribute for StatesArgs { expanded_attrs } } + +impl ToTokens + for QQ< + '_, + ItemAttribute, AllowStructOrEnum>, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) {} +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 7a94db40..75393fd7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -1,14 +1,14 @@ use crate::__private::attribute::RewriteAttribute; -use crate::codegen::tokens::ArgsBackToTokens; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::AttributeIdent; use crate::macro_api::attributes::prelude::GenericsArgs; use crate::macro_api::attributes::prelude::*; +use crate::macro_api::attributes::{AttributeIdent, ItemAttribute}; +use crate::macro_api::prelude::*; use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; use proc_macro2::{TokenStream as MacroStream, TokenStream}; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -53,3 +53,9 @@ impl RewriteAttribute for SystemArgs { expanded_attrs } } + +impl ToTokens + for QQ<'_, ItemAttribute, AllowFn>> +{ + fn to_tokens(&self, tokens: &mut TokenStream) {} +} From 1cfadab20a86ac17d6dde8cb13105dd10001e4a0 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 16:57:45 -0400 Subject: [PATCH 027/162] refactor: move all Q impls into their respective files --- .../attributes/actions/auto_add_message.rs | 21 +- .../attributes/actions/auto_add_observer.rs | 21 +- .../attributes/actions/auto_add_plugin.rs | 31 +- .../attributes/actions/auto_add_system.rs | 23 +- .../actions/auto_configure_system_set.rs | 67 ++++- .../attributes/actions/auto_init_resource.rs | 23 +- .../attributes/actions/auto_init_state.rs | 20 +- .../attributes/actions/auto_init_sub_state.rs | 20 +- .../actions/auto_insert_resource.rs | 23 +- .../macro_api/attributes/actions/auto_name.rs | 38 ++- .../actions/auto_register_state_type.rs | 25 +- .../attributes/actions/auto_register_type.rs | 23 +- .../attributes/actions/auto_run_on_build.rs | 21 +- .../src/macro_api/q.rs | 266 +----------------- 14 files changed, 346 insertions(+), 276 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index c48023aa..435c24af 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -1,5 +1,10 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -8,3 +13,17 @@ pub struct AddMessageArgs {} impl AttributeIdent for AddMessageArgs { const IDENT: &'static str = "auto_add_message"; } + +pub type AddMessage = + ItemAttribute, AllowStructOrEnum>; +pub type QAddMessageArgs<'a> = Q<'a, AddMessage>; + +impl RequiredUseQTokens for QAddMessageArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { + #app_param.add_message::<#concrete_path>(); + }); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 913ccb44..57b4386c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -1,5 +1,10 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowFn, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -8,3 +13,17 @@ pub struct AddObserverArgs {} impl AttributeIdent for AddObserverArgs { const IDENT: &'static str = "auto_add_observer"; } + +pub type AddObserver = + ItemAttribute, AllowFn>; +pub type QAddObserverArgs<'a> = Q<'a, AddObserver>; + +impl RequiredUseQTokens for QAddObserverArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { + #app_param.add_observer::<#concrete_path>(); + }); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index a356b74d..30aaa328 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -1,6 +1,11 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use crate::syntax::ast::flag_or_expr::FlagOrExpr; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -12,3 +17,27 @@ pub struct AddPluginArgs { impl AttributeIdent for AddPluginArgs { const IDENT: &'static str = "auto_add_plugin"; } + +pub type AddPlugin = + ItemAttribute, AllowStructOrEnum>; +pub type QAddPluginArgs<'a> = Q<'a, AddPlugin>; + +impl RequiredUseQTokens for QAddPluginArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + for concrete_path in self.args.concrete_paths() { + if let Some(expr) = &self.args.args.base.init.expr { + tokens.extend(quote! { + #app_param.add_plugins({ let plugin: #concrete_path = #expr; plugin }); + }); + } else if self.args.args.base.init.present { + tokens.extend(quote! { + #app_param.add_plugins(#concrete_path::default()); + }); + } else { + tokens.extend(quote! { + #app_param.add_plugins(#concrete_path); + }); + } + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index 012e531a..86379d3f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -1,6 +1,11 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowFn, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -12,3 +17,19 @@ pub struct AddSystemArgs { impl AttributeIdent for AddSystemArgs { const IDENT: &'static str = "auto_add_system"; } + +pub type AddSystem = + ItemAttribute, AllowFn>; +pub type QAddSystemArgs<'a> = Q<'a, AddSystem>; + +impl RequiredUseQTokens for QAddSystemArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + let schedule = &self.args.args.base.schedule_config.schedule; + let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { + #app_param.add_systems(#schedule, #concrete_path #config_tokens); + }); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 89195589..72e592cb 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,4 +1,7 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use crate::macro_api::schedule_config::{ScheduleConfigArgs, ScheduleWithScheduleConfigArgs}; use crate::syntax::analysis::item::resolve_ident_from_struct_or_enum; use crate::syntax::ast::flag::Flag; @@ -6,6 +9,7 @@ use crate::syntax::parse::item::ts_item_has_attr; use crate::syntax::parse::scrub_helpers::{AttrSite, scrub_helpers_and_ident_with_filter}; use darling::FromMeta; use proc_macro2::{Ident, TokenStream}; +use quote::{ToTokens, quote}; use syn::spanned::Spanned; use syn::{Attribute, Item, parse_quote}; @@ -589,3 +593,64 @@ mod tests { } } } + +pub type ConfigureSystemSet = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QConfigureSystemSetArgs<'a> = Q<'a, ConfigureSystemSet>; + +impl RequiredUseQTokens for QConfigureSystemSetArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + let args = &self.args.args; + let generics = args.generics(); + let base = &self.args.args.base; + let schedule = &args.base.schedule_config.schedule; + let config_tokens = args.base.schedule_config.config.to_token_stream(); + for concrete_path in self.args.concrete_paths() { + if let Some(inner) = &base.inner { + // enum + let chained = if base.chain.is_present() { + quote! { .chain() } + } else if base.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let mut entries = vec![]; + for (ident, entry) in inner.entries.iter() { + let chained = if entry.chain.is_present() { + quote! { .chain() } + } else if entry.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let config_tokens = entry.config.to_token_stream(); + entries.push(quote! { + #concrete_path :: #ident #chained #config_tokens + }); + } + if !entries.is_empty() { + tokens.extend(quote! { + #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); + }); + } + } else { + // struct + if generics.is_empty() { + tokens.extend(quote! { + #app_param.configure_sets(#schedule, #concrete_path #config_tokens); + }); + } else { + // TODO: generics are kind of silly here + // but if someone does use them we'll assume its just a marker type + // that can be initialized via `Default::default()` + tokens.extend(quote! { + #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); + }); + } + } + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index bc39a9ef..dcdc805a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -1,5 +1,10 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -8,3 +13,19 @@ pub struct InitResourceArgs {} impl AttributeIdent for InitResourceArgs { const IDENT: &'static str = "auto_init_resource"; } + +pub type InitResource = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QInitResourceArgs<'a> = Q<'a, InitResource>; + +impl RequiredUseQTokens for QInitResourceArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { + #app_param.init_resource::<#concrete_path>(); + }); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index 28c9302b..0a592759 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -1,5 +1,10 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithNoGenerics, WithPlugin}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -8,3 +13,16 @@ pub struct InitStateArgs {} impl AttributeIdent for InitStateArgs { const IDENT: &'static str = "auto_init_state"; } + +pub type InitState = + ItemAttribute, AllowStructOrEnum>; +pub type QInitStateArgs<'a> = Q<'a, InitState>; + +impl RequiredUseQTokens for QInitStateArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + let target = &self.args.target; + tokens.extend(quote! { + #app_param.init_state::<#target>(); + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index f57c4c20..0496babe 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -1,5 +1,10 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithNoGenerics, WithPlugin}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -8,3 +13,16 @@ pub struct InitSubStateArgs {} impl AttributeIdent for InitSubStateArgs { const IDENT: &'static str = "auto_init_sub_state"; } + +pub type InitSubState = + ItemAttribute, AllowStructOrEnum>; +pub type QInitSubStateArgs<'a> = Q<'a, InitSubState>; + +impl RequiredUseQTokens for QInitSubStateArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + let target = &self.args.target; + tokens.extend(quote! { + #app_param.init_sub_state::<#target>(); + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 5651b0fc..5cacf837 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -1,6 +1,11 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrOneGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use crate::syntax::ast::any_expr::AnyExprCallClosureMacroPath; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -11,3 +16,19 @@ pub struct InsertResourceArgs { impl AttributeIdent for InsertResourceArgs { const IDENT: &'static str = "auto_insert_resource"; } + +pub type InsertResource = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QInsertResourceArgs<'a> = Q<'a, InsertResource>; + +impl RequiredUseQTokens for QInsertResourceArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { |app| { + #app_param.insert_resource(#concrete_path::default()); + }}); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index b3aeb7a8..f9a10245 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -1,5 +1,11 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::syntax::extensions::lit::LitExt; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -10,3 +16,33 @@ pub struct NameArgs { impl AttributeIdent for NameArgs { const IDENT: &'static str = "auto_name"; } + +pub type Name = + ItemAttribute, AllowStructOrEnum>; +pub type QNameArgs<'a> = Q<'a, Name>; + +impl RequiredUseQTokens for QNameArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + let args = &self.args.args.base; + for concrete_path in self.args.concrete_paths() { + let name = args + .name + .as_ref() + .map(|name| name.unquoted_string()) + .unwrap_or_else(|| { + // TODO: move to util fn + quote!(#concrete_path) + .to_string() + .replace(" < ", "<") + .replace(" >", ">") + .replace(" ,", ",") + // TODO: offer option to only remove all spaces? + // .replace(" ", "") + }); + let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); + tokens.extend(quote! { + #app_param.register_required_components_with::<#concrete_path, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new(#name)); + }); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 7a1c0ec6..79e0f3e2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -1,5 +1,10 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -8,3 +13,21 @@ pub struct RegisterStateTypeArgs {} impl AttributeIdent for RegisterStateTypeArgs { const IDENT: &'static str = "auto_register_state_type"; } + +pub type RegisterStateType = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QRegisterStateTypeArgs<'a> = Q<'a, RegisterStateType>; + +impl RequiredUseQTokens for QRegisterStateTypeArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + for concrete_path in self.args.concrete_paths() { + let bevy_state = crate::__private::paths::state::root_path(); + tokens.extend(quote! { + #app_param.register_type :: < #bevy_state::prelude::State< #concrete_path > >(); + #app_param.register_type :: < #bevy_state::prelude::NextState< #concrete_path > >(); + }); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 4ad04b05..d1269a5c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -1,5 +1,10 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -8,3 +13,19 @@ pub struct RegisterTypeArgs {} impl AttributeIdent for RegisterTypeArgs { const IDENT: &'static str = "auto_register_type"; } + +pub type RegisterType = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QRegisterTypeArgs<'a> = Q<'a, RegisterType>; + +impl RequiredUseQTokens for QRegisterTypeArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { + #app_param.register_type::<#concrete_path>(); + }); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index 2ffe29e7..e8115978 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -1,5 +1,10 @@ -use crate::macro_api::attributes::AttributeIdent; +use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; +use crate::macro_api::composed::Composed; +use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; +use proc_macro2::TokenStream; +use quote::quote; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -8,3 +13,17 @@ pub struct RunOnBuildArgs {} impl AttributeIdent for RunOnBuildArgs { const IDENT: &'static str = "auto_run_on_build"; } + +pub type RunOnBuild = + ItemAttribute, AllowStructOrEnum>; +pub type QRunOnBuildArgs<'a> = Q<'a, RunOnBuild>; + +impl RequiredUseQTokens for QRunOnBuildArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + for concrete_path in self.args.concrete_paths() { + tokens.extend(quote! { + #concrete_path(#app_param); + }); + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 0dfd1648..3793b46c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -1,16 +1,8 @@ use crate::macro_api::attributes::prelude::*; -use crate::macro_api::attributes::{ - AllowFn, AllowStructOrEnum, GenericsCap, ItemAttribute, ItemAttributeParse, -}; -use crate::macro_api::composed::Composed; -use crate::macro_api::mixins::generics::none::WithNoGenerics; -use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; -use crate::macro_api::mixins::generics::with_single::WithZeroOrOneGenerics; -use crate::macro_api::mixins::with_plugin::WithPlugin; -use crate::syntax::extensions::lit::LitExt; +use crate::macro_api::attributes::{GenericsCap, ItemAttributeParse}; use proc_macro2::TokenStream; -use quote::{ToTokens, format_ident, quote}; -use syn::parse::{Parse, ParseStream}; +use quote::{ToTokens, format_ident}; +use syn::parse::Parse; /// for codegen attaching to bevy app pub(crate) struct Q<'a, T> { @@ -47,255 +39,3 @@ where RequiredUseQTokens::to_tokens(self, tokens, &self.app_param); } } - -pub type AddSystem = - ItemAttribute, AllowFn>; -pub type QAddSystemArgs<'a> = Q<'a, AddSystem>; -impl RequiredUseQTokens for QAddSystemArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - let schedule = &self.args.args.base.schedule_config.schedule; - let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { - #app_param.add_systems(#schedule, #concrete_path #config_tokens); - }); - } - } -} - -pub type AddMessage = - ItemAttribute, AllowStructOrEnum>; -pub type QAddMessageArgs<'a> = Q<'a, AddMessage>; -impl RequiredUseQTokens for QAddMessageArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { - #app_param.add_message::<#concrete_path>(); - }); - } - } -} - -pub type AddObserver = - ItemAttribute, AllowFn>; -pub type QAddObserverArgs<'a> = Q<'a, AddObserver>; -impl RequiredUseQTokens for QAddObserverArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { - #app_param.add_observer::<#concrete_path>(); - }); - } - } -} - -pub type AddPlugin = - ItemAttribute, AllowStructOrEnum>; -pub type QAddPluginArgs<'a> = Q<'a, AddPlugin>; -impl RequiredUseQTokens for QAddPluginArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - for concrete_path in self.args.concrete_paths() { - if let Some(expr) = &self.args.args.base.init.expr { - tokens.extend(quote! { - #app_param.add_plugins({ let plugin: #concrete_path = #expr; plugin }); - }); - } else if self.args.args.base.init.present { - tokens.extend(quote! { - #app_param.add_plugins(#concrete_path::default()); - }); - } else { - tokens.extend(quote! { - #app_param.add_plugins(#concrete_path); - }); - } - } - } -} - -pub type InitResource = ItemAttribute< - Composed, - AllowStructOrEnum, ->; -pub type QInitResourceArgs<'a> = Q<'a, InitResource>; -impl RequiredUseQTokens for QInitResourceArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { - #app_param.init_resource::<#concrete_path>(); - }); - } - } -} - -pub type InitState = - ItemAttribute, AllowStructOrEnum>; -pub type QInitStateArgs<'a> = Q<'a, InitState>; -impl RequiredUseQTokens for QInitStateArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - let target = &self.args.target; - tokens.extend(quote! { - #app_param.init_state::<#target>(); - }); - } -} - -pub type InitSubState = - ItemAttribute, AllowStructOrEnum>; -pub type QInitSubStateArgs<'a> = Q<'a, InitSubState>; -impl RequiredUseQTokens for QInitSubStateArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - let target = &self.args.target; - tokens.extend(quote! { - #app_param.init_sub_state::<#target>(); - }); - } -} - -pub type InsertResource = ItemAttribute< - Composed, - AllowStructOrEnum, ->; -pub type QInsertResourceArgs<'a> = Q<'a, InsertResource>; -impl RequiredUseQTokens for QInsertResourceArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - #app_param.insert_resource(#concrete_path::default()); - }}); - } - } -} - -pub type RegisterStateType = ItemAttribute< - Composed, - AllowStructOrEnum, ->; -pub type QRegisterStateTypeArgs<'a> = Q<'a, RegisterStateType>; -impl RequiredUseQTokens for QRegisterStateTypeArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - for concrete_path in self.args.concrete_paths() { - let bevy_state = crate::__private::paths::state::root_path(); - tokens.extend(quote! { - #app_param.register_type :: < #bevy_state::prelude::State< #concrete_path > >(); - #app_param.register_type :: < #bevy_state::prelude::NextState< #concrete_path > >(); - }); - } - } -} - -pub type RegisterType = ItemAttribute< - Composed, - AllowStructOrEnum, ->; -pub type QRegisterTypeArgs<'a> = Q<'a, RegisterType>; -impl RequiredUseQTokens for QRegisterTypeArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { - #app_param.register_type::<#concrete_path>(); - }); - } - } -} - -pub type RunOnBuild = - ItemAttribute, AllowStructOrEnum>; -pub type QRunOnBuildArgs<'a> = Q<'a, RunOnBuild>; -impl RequiredUseQTokens for QRunOnBuildArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { - #concrete_path(#app_param); - }); - } - } -} - -pub type ConfigureSystemSet = ItemAttribute< - Composed, - AllowStructOrEnum, ->; -pub type QConfigureSystemSetArgs<'a> = Q<'a, ConfigureSystemSet>; -impl RequiredUseQTokens for QConfigureSystemSetArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - let args = &self.args.args; - let generics = args.generics(); - let base = &self.args.args.base; - let schedule = &args.base.schedule_config.schedule; - let config_tokens = args.base.schedule_config.config.to_token_stream(); - for concrete_path in self.args.concrete_paths() { - if let Some(inner) = &base.inner { - // enum - let chained = if base.chain.is_present() { - quote! { .chain() } - } else if base.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let mut entries = vec![]; - for (ident, entry) in inner.entries.iter() { - let chained = if entry.chain.is_present() { - quote! { .chain() } - } else if entry.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let config_tokens = entry.config.to_token_stream(); - entries.push(quote! { - #concrete_path :: #ident #chained #config_tokens - }); - } - if !entries.is_empty() { - tokens.extend(quote! { - #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); - }); - } - } else { - // struct - if generics.is_empty() { - tokens.extend(quote! { - #app_param.configure_sets(#schedule, #concrete_path #config_tokens); - }); - } else { - // TODO: generics are kind of silly here - // but if someone does use them we'll assume its just a marker type - // that can be initialized via `Default::default()` - tokens.extend(quote! { - #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); - }); - } - } - } - } -} - -pub type Name = - ItemAttribute, AllowStructOrEnum>; -pub type QNameArgs<'a> = Q<'a, Name>; -impl RequiredUseQTokens for QNameArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - let args = &self.args.args.base; - for concrete_path in self.args.concrete_paths() { - let name = args - .name - .as_ref() - .map(|name| name.unquoted_string()) - .unwrap_or_else(|| { - // TODO: move to util fn - quote!(#concrete_path) - .to_string() - .replace(" < ", "<") - .replace(" >", ">") - .replace(" ,", ",") - // TODO: offer option to only remove all spaces? - // .replace(" ", "") - }); - let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); - tokens.extend(quote! { - #app_param.register_required_components_with::<#concrete_path, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new(#name)); - }); - } - } -} From 2efbbd2e185ca01e785e659f67c9954846275446 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 17:06:26 -0400 Subject: [PATCH 028/162] fix: `QQ` implementation to use `ComponentArgs` in `auto_component` rewrite --- .../src/macro_api/attributes/rewrites/auto_component.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index 5f21507c..da39e255 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -82,7 +82,10 @@ impl RewriteAttribute for ComponentArgs { impl ToTokens for QQ< '_, - ItemAttribute, AllowStructOrEnum>, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, > { fn to_tokens(&self, tokens: &mut TokenStream) {} From b8ca090652a5067d96e9594a2e2bc278aaf32150 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 17:09:43 -0400 Subject: [PATCH 029/162] fix: re-export `q` in `macro_api` prelude for consistency --- crates/bevy_auto_plugin_shared/src/macro_api/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 43f38f9a..bfe22fe8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -14,5 +14,6 @@ pub(crate) mod prelude { pub use attributes::*; pub use composed::*; pub use mixins::prelude::*; + pub use q::*; pub use qq::*; } From 2d221163be0b98c6210c4ce91c20ce2cc78e9c86 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 21 Oct 2025 17:09:50 -0400 Subject: [PATCH 030/162] refactor: replace `QQ` with `Q` in ToTokens implementations across rewrite attributes --- .../src/macro_api/attributes/rewrites/auto_component.rs | 2 +- .../src/macro_api/attributes/rewrites/auto_event.rs | 2 +- .../src/macro_api/attributes/rewrites/auto_message.rs | 2 +- .../src/macro_api/attributes/rewrites/auto_observer.rs | 2 +- .../src/macro_api/attributes/rewrites/auto_resource.rs | 2 +- .../src/macro_api/attributes/rewrites/auto_states.rs | 2 +- .../src/macro_api/attributes/rewrites/auto_system.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index da39e255..8dc43b5f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -80,7 +80,7 @@ impl RewriteAttribute for ComponentArgs { } impl ToTokens - for QQ< + for Q< '_, ItemAttribute< Composed, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 04cc247f..844d205b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -93,7 +93,7 @@ impl RewriteAttribute for EventArgs { } impl ToTokens - for QQ< + for Q< '_, ItemAttribute, AllowStructOrEnum>, > diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 1370e8d7..d6998291 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -75,7 +75,7 @@ impl RewriteAttribute for MessageArgs { } impl ToTokens - for QQ< + for Q< '_, ItemAttribute, AllowStructOrEnum>, > diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index f46aeac4..01698486 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -49,7 +49,7 @@ impl RewriteAttribute for ObserverArgs { } impl ToTokens - for QQ<'_, ItemAttribute, AllowFn>> + for Q<'_, ItemAttribute, AllowFn>> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 0032e12e..7a011929 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -77,7 +77,7 @@ impl RewriteAttribute for ResourceArgs { } impl ToTokens - for QQ< + for Q< '_, ItemAttribute, AllowStructOrEnum>, > diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 3d11cc97..86e54b15 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -72,7 +72,7 @@ impl RewriteAttribute for StatesArgs { } impl ToTokens - for QQ< + for Q< '_, ItemAttribute, AllowStructOrEnum>, > diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 75393fd7..42e186b8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -55,7 +55,7 @@ impl RewriteAttribute for SystemArgs { } impl ToTokens - for QQ<'_, ItemAttribute, AllowFn>> + for Q<'_, ItemAttribute, AllowFn>> { fn to_tokens(&self, tokens: &mut TokenStream) {} } From 1417c7e728a701a022a6e05fd0f778c3fb1ca46b Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 23 Oct 2025 15:12:58 -0400 Subject: [PATCH 031/162] refactor: move QQ ToTokens into their own files --- .../src/__private/expand/attr/mod.rs | 7 +- .../attributes/actions/auto_add_message.rs | 16 +- .../attributes/actions/auto_add_observer.rs | 16 +- .../attributes/actions/auto_add_plugin.rs | 23 +- .../attributes/actions/auto_add_system.rs | 22 +- .../actions/auto_configure_system_set.rs | 144 ++++++----- .../attributes/actions/auto_init_resource.rs | 15 +- .../attributes/actions/auto_init_state.rs | 16 +- .../attributes/actions/auto_init_sub_state.rs | 16 +- .../actions/auto_insert_resource.rs | 18 +- .../macro_api/attributes/actions/auto_name.rs | 19 +- .../actions/auto_register_state_type.rs | 16 +- .../attributes/actions/auto_register_type.rs | 15 +- .../attributes/actions/auto_run_on_build.rs | 16 +- .../src/macro_api/qq.rs | 224 ------------------ 15 files changed, 243 insertions(+), 340 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index c639afe2..fc7144f8 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -2,16 +2,11 @@ use crate::__private::auto_plugin_registry::_plugin_entry_block; use crate::macro_api::attributes::prelude::*; use crate::macro_api::attributes::{ItemAttribute, ItemAttributeInput, PluginCap}; use crate::macro_api::attributes::{ItemAttributeArgs, ItemAttributeParse}; -use crate::macro_api::composed::Composed; -use crate::macro_api::context::Context; -use crate::macro_api::mixins::prelude::*; -use crate::macro_api::q::*; +use crate::macro_api::prelude::*; use crate::util::macros::ok_or_emit_with; use proc_macro2::{Ident, TokenStream as MacroStream}; use quote::{ToTokens, format_ident, quote}; use std::hash::Hash; -use syn::Item; -use syn::parse::Parse; pub mod auto_bind_plugin; pub mod auto_plugin; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index 435c24af..20d34e22 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -1,10 +1,8 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -17,6 +15,7 @@ impl AttributeIdent for AddMessageArgs { pub type AddMessage = ItemAttribute, AllowStructOrEnum>; pub type QAddMessageArgs<'a> = Q<'a, AddMessage>; +pub type QQAddMessageArgs<'a> = QQ<'a, AddMessage>; impl RequiredUseQTokens for QAddMessageArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -27,3 +26,12 @@ impl RequiredUseQTokens for QAddMessageArgs<'_> { } } } + +impl ToTokens for QQAddMessageArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 57b4386c..13c79a79 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -1,10 +1,8 @@ use crate::macro_api::attributes::{AllowFn, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -17,6 +15,7 @@ impl AttributeIdent for AddObserverArgs { pub type AddObserver = ItemAttribute, AllowFn>; pub type QAddObserverArgs<'a> = Q<'a, AddObserver>; +pub type QQAddObserverArgs<'a> = QQ<'a, AddObserver>; impl RequiredUseQTokens for QAddObserverArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -27,3 +26,12 @@ impl RequiredUseQTokens for QAddObserverArgs<'_> { } } } + +impl ToTokens for QQAddObserverArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index 30aaa328..b7b6352b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -1,11 +1,9 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_expr::FlagOrExpr; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -41,3 +39,20 @@ impl RequiredUseQTokens for QAddPluginArgs<'_> { } } } + +impl ToTokens + for QQ< + '_, + ItemAttribute< + Composed, + AllowStructOrEnum, + >, + > +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index 86379d3f..ed4da8a5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -1,7 +1,5 @@ use crate::macro_api::attributes::{AllowFn, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; use darling::FromMeta; use proc_macro2::TokenStream; @@ -21,6 +19,7 @@ impl AttributeIdent for AddSystemArgs { pub type AddSystem = ItemAttribute, AllowFn>; pub type QAddSystemArgs<'a> = Q<'a, AddSystem>; +pub type QQAddSystem<'a> = QQ<'a, AddSystem>; impl RequiredUseQTokens for QAddSystemArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -33,3 +32,20 @@ impl RequiredUseQTokens for QAddSystemArgs<'_> { } } } + +impl ToTokens for QQAddSystem<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut args = self.args.args.extra_args(); + // TODO: cleanup + args.extend( + self.args + .args + .base + .schedule_config + .to_inner_arg_tokens_vec(), + ); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 72e592cb..508b960c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,7 +1,5 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use crate::macro_api::schedule_config::{ScheduleConfigArgs, ScheduleWithScheduleConfigArgs}; use crate::syntax::analysis::item::resolve_ident_from_struct_or_enum; use crate::syntax::ast::flag::Flag; @@ -94,6 +92,85 @@ impl AttributeIdent for ConfigureSystemSetArgs { const IDENT: &'static str = "auto_configure_system_set"; } +pub type ConfigureSystemSet = ItemAttribute< + Composed, + AllowStructOrEnum, +>; +pub type QConfigureSystemSetArgs<'a> = Q<'a, ConfigureSystemSet>; +pub type QQConfigureSystemSetArgs<'a> = QQ<'a, ConfigureSystemSet>; + +impl RequiredUseQTokens for QConfigureSystemSetArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + let args = &self.args.args; + let generics = args.generics(); + let base = &self.args.args.base; + let schedule = &args.base.schedule_config.schedule; + let config_tokens = args.base.schedule_config.config.to_token_stream(); + for concrete_path in self.args.concrete_paths() { + if let Some(inner) = &base.inner { + // enum + let chained = if base.chain.is_present() { + quote! { .chain() } + } else if base.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let mut entries = vec![]; + for (ident, entry) in inner.entries.iter() { + let chained = if entry.chain.is_present() { + quote! { .chain() } + } else if entry.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let config_tokens = entry.config.to_token_stream(); + entries.push(quote! { + #concrete_path :: #ident #chained #config_tokens + }); + } + if !entries.is_empty() { + tokens.extend(quote! { + #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); + }); + } + } else { + // struct + if generics.is_empty() { + tokens.extend(quote! { + #app_param.configure_sets(#schedule, #concrete_path #config_tokens); + }); + } else { + // TODO: generics are kind of silly here + // but if someone does use them we'll assume its just a marker type + // that can be initialized via `Default::default()` + tokens.extend(quote! { + #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); + }); + } + } + } + } +} + +impl ToTokens for QQConfigureSystemSetArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut args = self.args.args.extra_args(); + // TODO: cleanup + args.extend( + self.args + .args + .base + .schedule_config + .to_inner_arg_tokens_vec(), + ); + tokens.extend(quote! { + #(#args),* + }); + } +} + /// HACK - if the item doesn't have anymore `auto_configure_system_set` - set a flag to strip out the helper attributes fn check_strip_helpers(input: TokenStream, args: &mut ConfigureSystemSetArgs) -> syn::Result<()> { if !ts_item_has_attr(input, &parse_quote!(auto_configure_system_set))? { @@ -593,64 +670,3 @@ mod tests { } } } - -pub type ConfigureSystemSet = ItemAttribute< - Composed, - AllowStructOrEnum, ->; -pub type QConfigureSystemSetArgs<'a> = Q<'a, ConfigureSystemSet>; - -impl RequiredUseQTokens for QConfigureSystemSetArgs<'_> { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - let args = &self.args.args; - let generics = args.generics(); - let base = &self.args.args.base; - let schedule = &args.base.schedule_config.schedule; - let config_tokens = args.base.schedule_config.config.to_token_stream(); - for concrete_path in self.args.concrete_paths() { - if let Some(inner) = &base.inner { - // enum - let chained = if base.chain.is_present() { - quote! { .chain() } - } else if base.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let mut entries = vec![]; - for (ident, entry) in inner.entries.iter() { - let chained = if entry.chain.is_present() { - quote! { .chain() } - } else if entry.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let config_tokens = entry.config.to_token_stream(); - entries.push(quote! { - #concrete_path :: #ident #chained #config_tokens - }); - } - if !entries.is_empty() { - tokens.extend(quote! { - #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); - }); - } - } else { - // struct - if generics.is_empty() { - tokens.extend(quote! { - #app_param.configure_sets(#schedule, #concrete_path #config_tokens); - }); - } else { - // TODO: generics are kind of silly here - // but if someone does use them we'll assume its just a marker type - // that can be initialized via `Default::default()` - tokens.extend(quote! { - #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); - }); - } - } - } - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index dcdc805a..27553e6f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -1,10 +1,9 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; +use crate::macro_api::prelude::*; use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -19,6 +18,7 @@ pub type InitResource = ItemAttribute< AllowStructOrEnum, >; pub type QInitResourceArgs<'a> = Q<'a, InitResource>; +pub type QQInitResourceArgs<'a> = QQ<'a, InitResource>; impl RequiredUseQTokens for QInitResourceArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -29,3 +29,12 @@ impl RequiredUseQTokens for QInitResourceArgs<'_> { } } } + +impl ToTokens for QQInitResourceArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index 0a592759..e752631d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -1,10 +1,8 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithNoGenerics, WithPlugin}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -17,6 +15,7 @@ impl AttributeIdent for InitStateArgs { pub type InitState = ItemAttribute, AllowStructOrEnum>; pub type QInitStateArgs<'a> = Q<'a, InitState>; +pub type QQInitStateArgs<'a> = QQ<'a, InitState>; impl RequiredUseQTokens for QInitStateArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -26,3 +25,12 @@ impl RequiredUseQTokens for QInitStateArgs<'_> { }); } } + +impl ToTokens for QQInitStateArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 0496babe..458353f2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -1,10 +1,8 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithNoGenerics, WithPlugin}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -17,6 +15,7 @@ impl AttributeIdent for InitSubStateArgs { pub type InitSubState = ItemAttribute, AllowStructOrEnum>; pub type QInitSubStateArgs<'a> = Q<'a, InitSubState>; +pub type QQInitSubStateArgs<'a> = QQ<'a, InitSubState>; impl RequiredUseQTokens for QInitSubStateArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -26,3 +25,12 @@ impl RequiredUseQTokens for QInitSubStateArgs<'_> { }); } } + +impl ToTokens for QQInitSubStateArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 5cacf837..c1cb9d2f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -1,11 +1,9 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrOneGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use crate::syntax::ast::any_expr::AnyExprCallClosureMacroPath; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -22,6 +20,7 @@ pub type InsertResource = ItemAttribute< AllowStructOrEnum, >; pub type QInsertResourceArgs<'a> = Q<'a, InsertResource>; +pub type QQInsertResourceArgs<'a> = QQ<'a, InsertResource>; impl RequiredUseQTokens for QInsertResourceArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -32,3 +31,14 @@ impl RequiredUseQTokens for QInsertResourceArgs<'_> { } } } + +impl ToTokens for QQInsertResourceArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut args = self.args.args.extra_args(); + let resource = &self.args.args.base.resource; + args.push(quote! { resource = #resource }); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index f9a10245..ab0fee8f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -1,11 +1,9 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use crate::syntax::extensions::lit::LitExt; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -20,6 +18,7 @@ impl AttributeIdent for NameArgs { pub type Name = ItemAttribute, AllowStructOrEnum>; pub type QNameArgs<'a> = Q<'a, Name>; +pub type QQNameArgs<'a> = QQ<'a, Name>; impl RequiredUseQTokens for QNameArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -46,3 +45,15 @@ impl RequiredUseQTokens for QNameArgs<'_> { } } } + +impl ToTokens for QQNameArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut args = self.args.args.extra_args(); + if let Some(name) = &self.args.args.base.name { + args.push(quote! { name = #name }); + } + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 79e0f3e2..11736ae7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -1,10 +1,8 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -19,6 +17,7 @@ pub type RegisterStateType = ItemAttribute< AllowStructOrEnum, >; pub type QRegisterStateTypeArgs<'a> = Q<'a, RegisterStateType>; +pub type QQRegisterStateTypeArgs<'a> = QQ<'a, RegisterStateType>; impl RequiredUseQTokens for QRegisterStateTypeArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -31,3 +30,12 @@ impl RequiredUseQTokens for QRegisterStateTypeArgs<'_> { } } } + +impl ToTokens for QQRegisterStateTypeArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index d1269a5c..46331afc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -1,10 +1,8 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -19,6 +17,7 @@ pub type RegisterType = ItemAttribute< AllowStructOrEnum, >; pub type QRegisterTypeArgs<'a> = Q<'a, RegisterType>; +pub type QQRegisterTypeArgs<'a> = QQ<'a, RegisterType>; impl RequiredUseQTokens for QRegisterTypeArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -29,3 +28,11 @@ impl RequiredUseQTokens for QRegisterTypeArgs<'_> { } } } +impl ToTokens for QQRegisterTypeArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index e8115978..a6b79ea9 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -1,10 +1,8 @@ use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; -use crate::macro_api::composed::Composed; -use crate::macro_api::prelude::{WithPlugin, WithZeroOrManyGenerics}; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::quote; +use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -17,6 +15,7 @@ impl AttributeIdent for RunOnBuildArgs { pub type RunOnBuild = ItemAttribute, AllowStructOrEnum>; pub type QRunOnBuildArgs<'a> = Q<'a, RunOnBuild>; +pub type QQRunOnBuildArgs<'a> = QQ<'a, RunOnBuild>; impl RequiredUseQTokens for QRunOnBuildArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -27,3 +26,12 @@ impl RequiredUseQTokens for QRunOnBuildArgs<'_> { } } } + +impl ToTokens for QQRunOnBuildArgs<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + let args = self.args.args.extra_args(); + tokens.extend(quote! { + #(#args),* + }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 194cf0b2..6b4575fd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -40,227 +40,3 @@ where }) } } - -impl ToTokens - for QQ<'_, ItemAttribute, AllowFn>> -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let mut args = self.args.args.extra_args(); - // TODO: cleanup - args.extend( - self.args - .args - .base - .schedule_config - .to_inner_arg_tokens_vec(), - ); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute, AllowFn>, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let mut args = self.args.args.extra_args(); - let resource = &self.args.args.base.resource; - args.push(quote! { resource = #resource }); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let args = self.args.args.extra_args(); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let mut args = self.args.args.extra_args(); - // TODO: cleanup - args.extend( - self.args - .args - .base - .schedule_config - .to_inner_arg_tokens_vec(), - ); - tokens.extend(quote! { - #(#args),* - }); - } -} - -impl ToTokens - for QQ< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - let mut args = self.args.args.extra_args(); - if let Some(name) = &self.args.args.base.name { - args.push(quote! { name = #name }); - } - tokens.extend(quote! { - #(#args),* - }); - } -} From 2e61a68edc1d0020752295a09d85431e307d41da Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 23 Oct 2025 15:21:13 -0400 Subject: [PATCH 032/162] refactor: simplify imports with preludes --- .../__private/expand/attr/auto_bind_plugin.rs | 6 +-- .../src/__private/expand/attr/mod.rs | 3 -- .../src/codegen/tokens.rs | 3 +- .../src/codegen/with_target_path.rs | 2 +- .../attributes/actions/auto_add_message.rs | 1 - .../attributes/actions/auto_add_observer.rs | 1 - .../attributes/actions/auto_add_plugin.rs | 1 - .../attributes/actions/auto_add_system.rs | 1 - .../actions/auto_configure_system_set.rs | 1 - .../attributes/actions/auto_init_resource.rs | 1 - .../attributes/actions/auto_init_state.rs | 1 - .../attributes/actions/auto_init_sub_state.rs | 1 - .../actions/auto_insert_resource.rs | 1 - .../macro_api/attributes/actions/auto_name.rs | 1 - .../actions/auto_register_state_type.rs | 1 - .../attributes/actions/auto_register_type.rs | 1 - .../attributes/actions/auto_run_on_build.rs | 1 - .../src/macro_api/attributes/actions/mod.rs | 43 ++++++++++----- .../src/macro_api/attributes/auto_plugin.rs | 2 +- .../src/macro_api/attributes/mod.rs | 53 +++++++++++-------- .../attributes/rewrites/auto_component.rs | 3 -- .../attributes/rewrites/auto_event.rs | 3 -- .../attributes/rewrites/auto_message.rs | 4 -- .../attributes/rewrites/auto_observer.rs | 3 -- .../attributes/rewrites/auto_resource.rs | 3 -- .../attributes/rewrites/auto_states.rs | 3 -- .../attributes/rewrites/auto_system.rs | 3 -- .../src/macro_api/attributes/rewrites/mod.rs | 25 ++++++--- .../src/macro_api/mod.rs | 23 ++++---- .../src/syntax/validated/concrete_path.rs | 2 +- .../src/test_util/test_params.rs | 6 +-- 31 files changed, 97 insertions(+), 106 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index 45e29369..55ee2176 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -1,9 +1,5 @@ use crate::__private::expand::attr; -use crate::macro_api::attributes::ItemAttribute; -use crate::macro_api::composed::Composed; -use crate::macro_api::context::Context; -use crate::macro_api::mixins::nothing::Nothing; -use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::macro_api::prelude::*; use crate::syntax::extensions::item::ItemAttrsExt; use crate::util::macros::{compile_error_with, ok_or_emit_with}; use proc_macro2::TokenStream as MacroStream; diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index fc7144f8..49e73752 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,7 +1,4 @@ use crate::__private::auto_plugin_registry::_plugin_entry_block; -use crate::macro_api::attributes::prelude::*; -use crate::macro_api::attributes::{ItemAttribute, ItemAttributeInput, PluginCap}; -use crate::macro_api::attributes::{ItemAttributeArgs, ItemAttributeParse}; use crate::macro_api::prelude::*; use crate::util::macros::ok_or_emit_with; use proc_macro2::{Ident, TokenStream as MacroStream}; diff --git a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs index 2bbae76c..0b289ff2 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs @@ -1,6 +1,5 @@ use crate::codegen::ExpandAttrs; -use crate::macro_api::attributes::AttributeIdent; -use crate::macro_api::attributes::prelude::*; +use crate::macro_api::prelude::*; use crate::syntax::validated::non_empty_path::NonEmptyPath; use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, quote}; diff --git a/crates/bevy_auto_plugin_shared/src/codegen/with_target_path.rs b/crates/bevy_auto_plugin_shared/src/codegen/with_target_path.rs index 4251e1e3..cf05f4e1 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/with_target_path.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/with_target_path.rs @@ -1,4 +1,4 @@ -use crate::macro_api::attributes::prelude::GenericsArgs; +use crate::macro_api::prelude::*; use crate::syntax::validated::concrete_path::{ ConcreteTargetPath, ConcreteTargetPathWithGenericsCollection, }; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index 20d34e22..9cec101b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 13c79a79..ac0ba410 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowFn, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index b7b6352b..05a28fe6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_expr::FlagOrExpr; use darling::FromMeta; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index ed4da8a5..9e6de330 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowFn, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; use darling::FromMeta; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 508b960c..d7a1fa75 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use crate::macro_api::schedule_config::{ScheduleConfigArgs, ScheduleWithScheduleConfigArgs}; use crate::syntax::analysis::item::resolve_ident_from_struct_or_enum; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 27553e6f..20ec4d37 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use crate::macro_api::q::{Q, RequiredUseQTokens}; use darling::FromMeta; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index e752631d..762b90a0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, ItemAttribute}; use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 458353f2..32cae8cb 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, ItemAttribute}; use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index c1cb9d2f..8c5ee1ef 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use crate::syntax::ast::any_expr::AnyExprCallClosureMacroPath; use darling::FromMeta; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index ab0fee8f..b8f574d3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use crate::syntax::extensions::lit::LitExt; use darling::FromMeta; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 11736ae7..3cd57fb6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 46331afc..2e121c00 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index a6b79ea9..cadbb0d5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::{AllowStructOrEnum, AttributeIdent, GenericsCap, ItemAttribute}; use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/mod.rs index d8b72748..137d11e9 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/mod.rs @@ -1,13 +1,30 @@ -pub mod auto_add_message; -pub mod auto_add_observer; -pub mod auto_add_plugin; -pub mod auto_add_system; -pub mod auto_configure_system_set; -pub mod auto_init_resource; -pub mod auto_init_state; -pub mod auto_init_sub_state; -pub mod auto_insert_resource; -pub mod auto_name; -pub mod auto_register_state_type; -pub mod auto_register_type; -pub mod auto_run_on_build; +mod auto_add_message; +mod auto_add_observer; +mod auto_add_plugin; +mod auto_add_system; +mod auto_configure_system_set; +mod auto_init_resource; +mod auto_init_state; +mod auto_init_sub_state; +mod auto_insert_resource; +mod auto_name; +mod auto_register_state_type; +mod auto_register_type; +mod auto_run_on_build; + +pub mod prelude { + use super::*; + pub use auto_add_message::*; + pub use auto_add_observer::*; + pub use auto_add_plugin::*; + pub use auto_add_system::*; + pub use auto_configure_system_set::*; + pub use auto_init_resource::*; + pub use auto_init_state::*; + pub use auto_init_sub_state::*; + pub use auto_insert_resource::*; + pub use auto_name::*; + pub use auto_register_state_type::*; + pub use auto_register_type::*; + pub use auto_run_on_build::*; +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs index dbc8175d..56a1bb97 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs @@ -1,4 +1,4 @@ -use crate::macro_api::attributes::prelude::GenericsArgs; +use crate::macro_api::prelude::*; use crate::syntax::analysis::fn_param::require_fn_param_mutable_reference; use crate::syntax::ast::type_list::TypeList; use darling::FromMeta; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 190a0ef2..d6c98ca3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -2,7 +2,6 @@ use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; use crate::macro_api::mixins::generics::HasGenerics; -use crate::macro_api::mixins::nothing::Nothing; use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; @@ -10,7 +9,7 @@ use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use std::hash::Hash; use std::marker::PhantomData; -use syn::parse::{Parse, ParseStream}; +use syn::parse::Parse; use syn::spanned::Spanned; use syn::{Item, parse_quote, parse2}; @@ -20,29 +19,39 @@ mod rewrites; mod traits; pub mod prelude { + pub use super::AllowFn; + pub use super::AllowStructOrEnum; + pub use super::AttributeIdent; + pub use super::GenericsCap; + pub use super::IdentPathResolver; + pub use super::ItemAttribute; + pub use super::ItemAttributeArgs; + pub use super::ItemAttributeInput; + pub use super::ItemAttributeParse; + pub use super::PluginCap; pub use super::auto_plugin::{ AutoPluginFnArgs, AutoPluginStructOrEnumArgs, resolve_app_param_name, }; - pub use crate::macro_api::attributes::actions::auto_add_message::AddMessageArgs; - pub use crate::macro_api::attributes::actions::auto_add_observer::AddObserverArgs; - pub use crate::macro_api::attributes::actions::auto_add_plugin::AddPluginArgs; - pub use crate::macro_api::attributes::actions::auto_add_system::AddSystemArgs; - pub use crate::macro_api::attributes::actions::auto_configure_system_set::ConfigureSystemSetArgs; - pub use crate::macro_api::attributes::actions::auto_init_resource::InitResourceArgs; - pub use crate::macro_api::attributes::actions::auto_init_state::InitStateArgs; - pub use crate::macro_api::attributes::actions::auto_init_sub_state::InitSubStateArgs; - pub use crate::macro_api::attributes::actions::auto_insert_resource::InsertResourceArgs; - pub use crate::macro_api::attributes::actions::auto_name::NameArgs; - pub use crate::macro_api::attributes::actions::auto_register_state_type::RegisterStateTypeArgs; - pub use crate::macro_api::attributes::actions::auto_register_type::RegisterTypeArgs; - pub use crate::macro_api::attributes::actions::auto_run_on_build::RunOnBuildArgs; - pub use crate::macro_api::attributes::rewrites::auto_component::ComponentArgs; - pub use crate::macro_api::attributes::rewrites::auto_event::EventArgs; - pub use crate::macro_api::attributes::rewrites::auto_message::MessageArgs; - pub use crate::macro_api::attributes::rewrites::auto_observer::ObserverArgs; - pub use crate::macro_api::attributes::rewrites::auto_resource::ResourceArgs; - pub use crate::macro_api::attributes::rewrites::auto_states::StatesArgs; - pub use crate::macro_api::attributes::rewrites::auto_system::SystemArgs; + pub use crate::macro_api::attributes::actions::prelude::AddMessageArgs; + pub use crate::macro_api::attributes::actions::prelude::AddObserverArgs; + pub use crate::macro_api::attributes::actions::prelude::AddPluginArgs; + pub use crate::macro_api::attributes::actions::prelude::AddSystemArgs; + pub use crate::macro_api::attributes::actions::prelude::ConfigureSystemSetArgs; + pub use crate::macro_api::attributes::actions::prelude::InitResourceArgs; + pub use crate::macro_api::attributes::actions::prelude::InitStateArgs; + pub use crate::macro_api::attributes::actions::prelude::InitSubStateArgs; + pub use crate::macro_api::attributes::actions::prelude::InsertResourceArgs; + pub use crate::macro_api::attributes::actions::prelude::NameArgs; + pub use crate::macro_api::attributes::actions::prelude::RegisterStateTypeArgs; + pub use crate::macro_api::attributes::actions::prelude::RegisterTypeArgs; + pub use crate::macro_api::attributes::actions::prelude::RunOnBuildArgs; + pub use crate::macro_api::attributes::rewrites::prelude::ComponentArgs; + pub use crate::macro_api::attributes::rewrites::prelude::EventArgs; + pub use crate::macro_api::attributes::rewrites::prelude::MessageArgs; + pub use crate::macro_api::attributes::rewrites::prelude::ObserverArgs; + pub use crate::macro_api::attributes::rewrites::prelude::ResourceArgs; + pub use crate::macro_api::attributes::rewrites::prelude::StatesArgs; + pub use crate::macro_api::attributes::rewrites::prelude::SystemArgs; pub use crate::macro_api::attributes::traits::prelude::*; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index 8dc43b5f..da07911e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -1,8 +1,5 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::AttributeIdent; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::prelude::*; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::ast::flag_or_lit::FlagOrLit; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 844d205b..885e05c1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -1,8 +1,5 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::AttributeIdent; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::prelude::*; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index d6998291..254b1e03 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -1,9 +1,5 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::AttributeIdent; -use crate::macro_api::attributes::actions::auto_add_message::AddMessageArgs; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::prelude::*; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index 01698486..2fc286fd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -1,8 +1,5 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::AttributeIdent; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::prelude::*; use crate::macro_api::prelude::*; use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 7a011929..99552d3f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -1,8 +1,5 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::AttributeIdent; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::prelude::*; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 86e54b15..dce5087a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -1,8 +1,5 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::AttributeIdent; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::prelude::*; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 42e186b8..56131332 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -1,8 +1,5 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::prelude::GenericsArgs; -use crate::macro_api::attributes::prelude::*; -use crate::macro_api::attributes::{AttributeIdent, ItemAttribute}; use crate::macro_api::prelude::*; use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; use crate::syntax::validated::non_empty_path::NonEmptyPath; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/mod.rs index a379c909..fb09b5cc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/mod.rs @@ -1,7 +1,18 @@ -pub mod auto_component; -pub mod auto_event; -pub mod auto_message; -pub mod auto_observer; -pub mod auto_resource; -pub mod auto_states; -pub mod auto_system; +mod auto_component; +mod auto_event; +mod auto_message; +mod auto_observer; +mod auto_resource; +mod auto_states; +mod auto_system; + +pub mod prelude { + pub use super::*; + pub use auto_component::*; + pub use auto_event::*; + pub use auto_message::*; + pub use auto_observer::*; + pub use auto_resource::*; + pub use auto_states::*; + pub use auto_system::*; +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index bfe22fe8..79975dc0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -1,18 +1,19 @@ -pub(crate) mod attributes; -pub(crate) mod composed; -pub(crate) mod context; -pub mod derives; -pub(crate) mod input_item; -pub(crate) mod macro_paths; -pub(super) mod mixins; -pub(crate) mod q; -pub(crate) mod qq; -pub mod schedule_config; +mod attributes; +mod composed; +mod context; +mod derives; +mod input_item; +mod macro_paths; +mod mixins; +mod q; +mod qq; +mod schedule_config; pub(crate) mod prelude { use super::*; - pub use attributes::*; + pub use attributes::prelude::*; pub use composed::*; + pub use context::*; pub use mixins::prelude::*; pub use q::*; pub use qq::*; diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs index 84b0ff39..d2b5ff15 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs @@ -1,5 +1,5 @@ use crate::codegen::with_target_path::WithTargetPath; -use crate::macro_api::attributes::prelude::GenericsArgs; +use crate::macro_api::prelude::*; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::generics::{Generics, GenericsCollection}; use crate::syntax::validated::path_without_generics::{ diff --git a/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs b/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs index 7b18b3bb..1f38ffa9 100644 --- a/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs +++ b/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs @@ -1,10 +1,6 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::attributes::prelude::*; -use crate::macro_api::composed::Composed; -use crate::macro_api::mixins::Mixin; -use crate::macro_api::mixins::nothing::Nothing; -use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::macro_api::prelude::*; use crate::syntax::validated::non_empty_path::NonEmptyPath; use anyhow::anyhow; use darling::ast::NestedMeta; From 82242c3d0afd9ebdc12825a2594816edb8bf9370 Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 23 Oct 2025 15:28:46 -0400 Subject: [PATCH 033/162] refactor: introduce type aliases for rewrite ItemAttribute --- .../macro_api/attributes/rewrites/auto_component.rs | 13 ++++--------- .../src/macro_api/attributes/rewrites/auto_event.rs | 10 ++++------ .../macro_api/attributes/rewrites/auto_message.rs | 10 ++++------ .../macro_api/attributes/rewrites/auto_observer.rs | 7 ++++--- .../macro_api/attributes/rewrites/auto_resource.rs | 10 ++++------ .../macro_api/attributes/rewrites/auto_states.rs | 10 ++++------ .../macro_api/attributes/rewrites/auto_system.rs | 4 +++- 7 files changed, 27 insertions(+), 37 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index da07911e..dd025940 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -76,14 +76,9 @@ impl RewriteAttribute for ComponentArgs { } } -impl ToTokens - for Q< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ +pub type Component = + ItemAttribute, AllowStructOrEnum>; +pub type QComponentArgs<'a> = Q<'a, Component>; +impl ToTokens for QComponentArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 885e05c1..5835abc6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -89,11 +89,9 @@ impl RewriteAttribute for EventArgs { } } -impl ToTokens - for Q< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ +pub type Event = + ItemAttribute, AllowStructOrEnum>; +pub type QEvent<'a> = Q<'a, Event>; +impl ToTokens for QEvent<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 254b1e03..9a87ef59 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -70,11 +70,9 @@ impl RewriteAttribute for MessageArgs { } } -impl ToTokens - for Q< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ +pub type Message = + ItemAttribute, AllowStructOrEnum>; +pub type QMessage<'a> = Q<'a, Message>; +impl ToTokens for QMessage<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index 2fc286fd..46a18ca0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -45,8 +45,9 @@ impl RewriteAttribute for ObserverArgs { } } -impl ToTokens - for Q<'_, ItemAttribute, AllowFn>> -{ +pub type Observer = + ItemAttribute, AllowFn>; +pub type QObserver<'a> = Q<'a, Observer>; +impl ToTokens for QObserver<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 99552d3f..6c2a504d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -73,11 +73,9 @@ impl RewriteAttribute for ResourceArgs { } } -impl ToTokens - for Q< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ +pub type Resource = + ItemAttribute, AllowStructOrEnum>; +pub type QResourceArgs<'a> = Q<'a, Resource>; +impl ToTokens for QResourceArgs<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index dce5087a..0f6a20dc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -68,11 +68,9 @@ impl RewriteAttribute for StatesArgs { } } -impl ToTokens - for Q< - '_, - ItemAttribute, AllowStructOrEnum>, - > -{ +pub type State = + ItemAttribute, AllowStructOrEnum>; +pub type QState<'a> = Q<'a, State>; +impl ToTokens for QState<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 56131332..6138b92e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -51,8 +51,10 @@ impl RewriteAttribute for SystemArgs { } } +pub type System = ItemAttribute, AllowFn> +pub type QSystem<'a> = Q<'a, System>; impl ToTokens - for Q<'_, ItemAttribute, AllowFn>> + for QSystem<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } From 558a2fde4cc2caf038d3eff3108dc66b5cf20981 Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 23 Oct 2025 15:34:32 -0400 Subject: [PATCH 034/162] refactor: rename ItemAttribute type aliases --- .../macro_api/attributes/actions/auto_add_message.rs | 10 +++++----- .../macro_api/attributes/actions/auto_add_observer.rs | 10 +++++----- .../macro_api/attributes/actions/auto_add_plugin.rs | 6 +++--- .../macro_api/attributes/actions/auto_add_system.rs | 8 ++++---- .../attributes/actions/auto_configure_system_set.rs | 10 +++++----- .../macro_api/attributes/actions/auto_init_resource.rs | 10 +++++----- .../macro_api/attributes/actions/auto_init_state.rs | 10 +++++----- .../attributes/actions/auto_init_sub_state.rs | 10 +++++----- .../attributes/actions/auto_insert_resource.rs | 10 +++++----- .../src/macro_api/attributes/actions/auto_name.rs | 10 +++++----- .../attributes/actions/auto_register_state_type.rs | 10 +++++----- .../macro_api/attributes/actions/auto_register_type.rs | 10 +++++----- .../macro_api/attributes/actions/auto_run_on_build.rs | 10 +++++----- .../macro_api/attributes/rewrites/auto_component.rs | 6 +++--- .../src/macro_api/attributes/rewrites/auto_event.rs | 4 ++-- .../src/macro_api/attributes/rewrites/auto_message.rs | 4 ++-- .../src/macro_api/attributes/rewrites/auto_observer.rs | 4 ++-- .../src/macro_api/attributes/rewrites/auto_resource.rs | 6 +++--- .../src/macro_api/attributes/rewrites/auto_states.rs | 4 ++-- .../src/macro_api/attributes/rewrites/auto_system.rs | 4 ++-- 20 files changed, 78 insertions(+), 78 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index 9cec101b..a758973b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -11,12 +11,12 @@ impl AttributeIdent for AddMessageArgs { const IDENT: &'static str = "auto_add_message"; } -pub type AddMessage = +pub type IaAddMessage = ItemAttribute, AllowStructOrEnum>; -pub type QAddMessageArgs<'a> = Q<'a, AddMessage>; -pub type QQAddMessageArgs<'a> = QQ<'a, AddMessage>; +pub type QAddMessage<'a> = Q<'a, IaAddMessage>; +pub type QQAddMessage<'a> = QQ<'a, IaAddMessage>; -impl RequiredUseQTokens for QAddMessageArgs<'_> { +impl RequiredUseQTokens for QAddMessage<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl RequiredUseQTokens for QAddMessageArgs<'_> { } } -impl ToTokens for QQAddMessageArgs<'_> { +impl ToTokens for QQAddMessage<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index ac0ba410..febfc301 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -11,12 +11,12 @@ impl AttributeIdent for AddObserverArgs { const IDENT: &'static str = "auto_add_observer"; } -pub type AddObserver = +pub type IaAddObserver = ItemAttribute, AllowFn>; -pub type QAddObserverArgs<'a> = Q<'a, AddObserver>; -pub type QQAddObserverArgs<'a> = QQ<'a, AddObserver>; +pub type QAddObserver<'a> = Q<'a, IaAddObserver>; +pub type QQAddObserver<'a> = QQ<'a, IaAddObserver>; -impl RequiredUseQTokens for QAddObserverArgs<'_> { +impl RequiredUseQTokens for QAddObserver<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl RequiredUseQTokens for QAddObserverArgs<'_> { } } -impl ToTokens for QQAddObserverArgs<'_> { +impl ToTokens for QQAddObserver<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index 05a28fe6..1cac1c26 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -15,11 +15,11 @@ impl AttributeIdent for AddPluginArgs { const IDENT: &'static str = "auto_add_plugin"; } -pub type AddPlugin = +pub type IaAddPlugin = ItemAttribute, AllowStructOrEnum>; -pub type QAddPluginArgs<'a> = Q<'a, AddPlugin>; +pub type QAddPlugin<'a> = Q<'a, IaAddPlugin>; -impl RequiredUseQTokens for QAddPluginArgs<'_> { +impl RequiredUseQTokens for QAddPlugin<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { if let Some(expr) = &self.args.args.base.init.expr { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index 9e6de330..7c9882a8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -15,12 +15,12 @@ impl AttributeIdent for AddSystemArgs { const IDENT: &'static str = "auto_add_system"; } -pub type AddSystem = +pub type IaAddSystem = ItemAttribute, AllowFn>; -pub type QAddSystemArgs<'a> = Q<'a, AddSystem>; -pub type QQAddSystem<'a> = QQ<'a, AddSystem>; +pub type QAddSystem<'a> = Q<'a, IaAddSystem>; +pub type QQAddSystem<'a> = QQ<'a, IaAddSystem>; -impl RequiredUseQTokens for QAddSystemArgs<'_> { +impl RequiredUseQTokens for QAddSystem<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let schedule = &self.args.args.base.schedule_config.schedule; let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index d7a1fa75..3bf58d89 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -91,14 +91,14 @@ impl AttributeIdent for ConfigureSystemSetArgs { const IDENT: &'static str = "auto_configure_system_set"; } -pub type ConfigureSystemSet = ItemAttribute< +pub type IaConfigureSystemSet = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QConfigureSystemSetArgs<'a> = Q<'a, ConfigureSystemSet>; -pub type QQConfigureSystemSetArgs<'a> = QQ<'a, ConfigureSystemSet>; +pub type QConfigureSystemSet<'a> = Q<'a, IaConfigureSystemSet>; +pub type QQConfigureSystemSet<'a> = QQ<'a, IaConfigureSystemSet>; -impl RequiredUseQTokens for QConfigureSystemSetArgs<'_> { +impl RequiredUseQTokens for QConfigureSystemSet<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args; let generics = args.generics(); @@ -153,7 +153,7 @@ impl RequiredUseQTokens for QConfigureSystemSetArgs<'_> { } } -impl ToTokens for QQConfigureSystemSetArgs<'_> { +impl ToTokens for QQConfigureSystemSet<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); // TODO: cleanup diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 20ec4d37..6cfb0e52 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -12,14 +12,14 @@ impl AttributeIdent for InitResourceArgs { const IDENT: &'static str = "auto_init_resource"; } -pub type InitResource = ItemAttribute< +pub type IaInitResource = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QInitResourceArgs<'a> = Q<'a, InitResource>; -pub type QQInitResourceArgs<'a> = QQ<'a, InitResource>; +pub type QInitResource<'a> = Q<'a, IaInitResource>; +pub type QQInitResource<'a> = QQ<'a, IaInitResource>; -impl RequiredUseQTokens for QInitResourceArgs<'_> { +impl RequiredUseQTokens for QInitResource<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -29,7 +29,7 @@ impl RequiredUseQTokens for QInitResourceArgs<'_> { } } -impl ToTokens for QQInitResourceArgs<'_> { +impl ToTokens for QQInitResource<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index 762b90a0..481164d3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -11,12 +11,12 @@ impl AttributeIdent for InitStateArgs { const IDENT: &'static str = "auto_init_state"; } -pub type InitState = +pub type IaInitState = ItemAttribute, AllowStructOrEnum>; -pub type QInitStateArgs<'a> = Q<'a, InitState>; -pub type QQInitStateArgs<'a> = QQ<'a, InitState>; +pub type QInitState<'a> = Q<'a, IaInitState>; +pub type QQInitState<'a> = QQ<'a, IaInitState>; -impl RequiredUseQTokens for QInitStateArgs<'_> { +impl RequiredUseQTokens for QInitState<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { @@ -25,7 +25,7 @@ impl RequiredUseQTokens for QInitStateArgs<'_> { } } -impl ToTokens for QQInitStateArgs<'_> { +impl ToTokens for QQInitState<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 32cae8cb..9a85fd8c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -11,12 +11,12 @@ impl AttributeIdent for InitSubStateArgs { const IDENT: &'static str = "auto_init_sub_state"; } -pub type InitSubState = +pub type IaInitSubState = ItemAttribute, AllowStructOrEnum>; -pub type QInitSubStateArgs<'a> = Q<'a, InitSubState>; -pub type QQInitSubStateArgs<'a> = QQ<'a, InitSubState>; +pub type QInitSubState<'a> = Q<'a, IaInitSubState>; +pub type QQInitSubState<'a> = QQ<'a, IaInitSubState>; -impl RequiredUseQTokens for QInitSubStateArgs<'_> { +impl RequiredUseQTokens for QInitSubState<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { @@ -25,7 +25,7 @@ impl RequiredUseQTokens for QInitSubStateArgs<'_> { } } -impl ToTokens for QQInitSubStateArgs<'_> { +impl ToTokens for QQInitSubState<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 8c5ee1ef..7f811cc0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -14,14 +14,14 @@ impl AttributeIdent for InsertResourceArgs { const IDENT: &'static str = "auto_insert_resource"; } -pub type InsertResource = ItemAttribute< +pub type IaInsertResource = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QInsertResourceArgs<'a> = Q<'a, InsertResource>; -pub type QQInsertResourceArgs<'a> = QQ<'a, InsertResource>; +pub type QInsertResource<'a> = Q<'a, IaInsertResource>; +pub type QQInsertResource<'a> = QQ<'a, IaInsertResource>; -impl RequiredUseQTokens for QInsertResourceArgs<'_> { +impl RequiredUseQTokens for QInsertResource<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { @@ -31,7 +31,7 @@ impl RequiredUseQTokens for QInsertResourceArgs<'_> { } } -impl ToTokens for QQInsertResourceArgs<'_> { +impl ToTokens for QQInsertResource<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); let resource = &self.args.args.base.resource; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index b8f574d3..54adb042 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -14,12 +14,12 @@ impl AttributeIdent for NameArgs { const IDENT: &'static str = "auto_name"; } -pub type Name = +pub type IaName = ItemAttribute, AllowStructOrEnum>; -pub type QNameArgs<'a> = Q<'a, Name>; -pub type QQNameArgs<'a> = QQ<'a, Name>; +pub type QName<'a> = Q<'a, IaName>; +pub type QQName<'a> = QQ<'a, IaName>; -impl RequiredUseQTokens for QNameArgs<'_> { +impl RequiredUseQTokens for QName<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args.base; for concrete_path in self.args.concrete_paths() { @@ -45,7 +45,7 @@ impl RequiredUseQTokens for QNameArgs<'_> { } } -impl ToTokens for QQNameArgs<'_> { +impl ToTokens for QQName<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); if let Some(name) = &self.args.args.base.name { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 3cd57fb6..674d6d31 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -11,14 +11,14 @@ impl AttributeIdent for RegisterStateTypeArgs { const IDENT: &'static str = "auto_register_state_type"; } -pub type RegisterStateType = ItemAttribute< +pub type IaRegisterStateType = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QRegisterStateTypeArgs<'a> = Q<'a, RegisterStateType>; -pub type QQRegisterStateTypeArgs<'a> = QQ<'a, RegisterStateType>; +pub type QRegisterStateType<'a> = Q<'a, IaRegisterStateType>; +pub type QQRegisterStateType<'a> = QQ<'a, IaRegisterStateType>; -impl RequiredUseQTokens for QRegisterStateTypeArgs<'_> { +impl RequiredUseQTokens for QRegisterStateType<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { let bevy_state = crate::__private::paths::state::root_path(); @@ -30,7 +30,7 @@ impl RequiredUseQTokens for QRegisterStateTypeArgs<'_> { } } -impl ToTokens for QQRegisterStateTypeArgs<'_> { +impl ToTokens for QQRegisterStateType<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 2e121c00..7a06b255 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -11,14 +11,14 @@ impl AttributeIdent for RegisterTypeArgs { const IDENT: &'static str = "auto_register_type"; } -pub type RegisterType = ItemAttribute< +pub type IaRegisterType = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QRegisterTypeArgs<'a> = Q<'a, RegisterType>; -pub type QQRegisterTypeArgs<'a> = QQ<'a, RegisterType>; +pub type QRegisterType<'a> = Q<'a, IaRegisterType>; +pub type QQRegisterType<'a> = QQ<'a, IaRegisterType>; -impl RequiredUseQTokens for QRegisterTypeArgs<'_> { +impl RequiredUseQTokens for QRegisterType<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -27,7 +27,7 @@ impl RequiredUseQTokens for QRegisterTypeArgs<'_> { } } } -impl ToTokens for QQRegisterTypeArgs<'_> { +impl ToTokens for QQRegisterType<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index cadbb0d5..c41c7138 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -11,12 +11,12 @@ impl AttributeIdent for RunOnBuildArgs { const IDENT: &'static str = "auto_run_on_build"; } -pub type RunOnBuild = +pub type IaRunOnBuild = ItemAttribute, AllowStructOrEnum>; -pub type QRunOnBuildArgs<'a> = Q<'a, RunOnBuild>; -pub type QQRunOnBuildArgs<'a> = QQ<'a, RunOnBuild>; +pub type QRunOnBuild<'a> = Q<'a, IaRunOnBuild>; +pub type QQRunOnBuild<'a> = QQ<'a, IaRunOnBuild>; -impl RequiredUseQTokens for QRunOnBuildArgs<'_> { +impl RequiredUseQTokens for QRunOnBuild<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl RequiredUseQTokens for QRunOnBuildArgs<'_> { } } -impl ToTokens for QQRunOnBuildArgs<'_> { +impl ToTokens for QQRunOnBuild<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index dd025940..edb55de6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -76,9 +76,9 @@ impl RewriteAttribute for ComponentArgs { } } -pub type Component = +pub type IaComponent = ItemAttribute, AllowStructOrEnum>; -pub type QComponentArgs<'a> = Q<'a, Component>; -impl ToTokens for QComponentArgs<'_> { +pub type QComponent<'a> = Q<'a, IaComponent>; +impl ToTokens for QComponent<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 5835abc6..4729b190 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -89,9 +89,9 @@ impl RewriteAttribute for EventArgs { } } -pub type Event = +pub type IaEvent = ItemAttribute, AllowStructOrEnum>; -pub type QEvent<'a> = Q<'a, Event>; +pub type QEvent<'a> = Q<'a, IaEvent>; impl ToTokens for QEvent<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 9a87ef59..7c2456c1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -70,9 +70,9 @@ impl RewriteAttribute for MessageArgs { } } -pub type Message = +pub type IaMessage = ItemAttribute, AllowStructOrEnum>; -pub type QMessage<'a> = Q<'a, Message>; +pub type QMessage<'a> = Q<'a, IaMessage>; impl ToTokens for QMessage<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index 46a18ca0..d7cb4ba0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -45,9 +45,9 @@ impl RewriteAttribute for ObserverArgs { } } -pub type Observer = +pub type IaObserver = ItemAttribute, AllowFn>; -pub type QObserver<'a> = Q<'a, Observer>; +pub type QObserver<'a> = Q<'a, IaObserver>; impl ToTokens for QObserver<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 6c2a504d..d6e14838 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -73,9 +73,9 @@ impl RewriteAttribute for ResourceArgs { } } -pub type Resource = +pub type IaResource = ItemAttribute, AllowStructOrEnum>; -pub type QResourceArgs<'a> = Q<'a, Resource>; -impl ToTokens for QResourceArgs<'_> { +pub type QResource<'a> = Q<'a, IaResource>; +impl ToTokens for QResource<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 0f6a20dc..3787de68 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -68,9 +68,9 @@ impl RewriteAttribute for StatesArgs { } } -pub type State = +pub type IaState = ItemAttribute, AllowStructOrEnum>; -pub type QState<'a> = Q<'a, State>; +pub type QState<'a> = Q<'a, IaState>; impl ToTokens for QState<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 6138b92e..86e7067a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -51,8 +51,8 @@ impl RewriteAttribute for SystemArgs { } } -pub type System = ItemAttribute, AllowFn> -pub type QSystem<'a> = Q<'a, System>; +pub type IaSystem = ItemAttribute, AllowFn> +pub type QSystem<'a> = Q<'a, IaSystem>; impl ToTokens for QSystem<'_> { From 22741cb16a1f0160d222e18e4fc7a22c6ca91fd2 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 15:42:25 -0400 Subject: [PATCH 035/162] fix: formatting and missing semicolon --- .../src/macro_api/attributes/rewrites/auto_system.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 86e7067a..28ffa3d2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -51,10 +51,9 @@ impl RewriteAttribute for SystemArgs { } } -pub type IaSystem = ItemAttribute, AllowFn> -pub type QSystem<'a> = Q<'a, IaSystem>; -impl ToTokens - for QSystem<'_> -{ +pub type IaSystem = + ItemAttribute, AllowFn>; +pub type QSystem<'a> = Q<'a, IaSystem>; +impl ToTokens for QSystem<'_> { fn to_tokens(&self, tokens: &mut TokenStream) {} } From bbc36c4f87e4849569e4418ef60b62373c72cc5d Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 15:45:15 -0400 Subject: [PATCH 036/162] refactor: remove RewriteAttribute expand_args --- .../bevy_auto_plugin_shared/src/__private/attribute.rs | 1 - .../src/macro_api/attributes/rewrites/auto_component.rs | 9 --------- .../src/macro_api/attributes/rewrites/auto_event.rs | 9 --------- .../src/macro_api/attributes/rewrites/auto_message.rs | 9 --------- .../src/macro_api/attributes/rewrites/auto_observer.rs | 9 --------- .../src/macro_api/attributes/rewrites/auto_resource.rs | 9 --------- .../src/macro_api/attributes/rewrites/auto_states.rs | 9 --------- .../src/macro_api/attributes/rewrites/auto_system.rs | 9 --------- 8 files changed, 64 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/attribute.rs b/crates/bevy_auto_plugin_shared/src/__private/attribute.rs index e3aefe17..9b8f9b4c 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/attribute.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/attribute.rs @@ -3,6 +3,5 @@ use crate::syntax::validated::non_empty_path::NonEmptyPath; use proc_macro2::TokenStream as MacroStream; pub trait RewriteAttribute { - fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream; fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index edb55de6..ec44c74c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -37,15 +37,6 @@ impl<'a> From<&'a ComponentArgs> for NameArgs { } impl RewriteAttribute for ComponentArgs { - fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { - let mut args = Vec::new(); - args.push(quote! { plugin = #plugin }); - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - quote! { #(#args),* } - } - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { let mut expanded_attrs = ExpandAttrs::default(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 4729b190..41055f71 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -50,15 +50,6 @@ impl<'a> From<&'a EventArgs> for RegisterTypeArgs { } impl RewriteAttribute for EventArgs { - fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { - let mut args = Vec::new(); - args.push(quote! { plugin = #plugin }); - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - quote! { #(#args),* } - } - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { let mut expanded_attrs = ExpandAttrs::default(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 7c2456c1..5374d7f7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -32,15 +32,6 @@ impl<'a> From<&'a MessageArgs> for AddMessageArgs { } impl RewriteAttribute for MessageArgs { - fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { - let mut args = Vec::new(); - args.push(quote! { plugin = #plugin }); - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - quote! { #(#args),* } - } - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { let mut expanded_attrs = ExpandAttrs::default(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index d7cb4ba0..6f86e4d2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -27,15 +27,6 @@ impl<'a> From<&'a ObserverArgs> for AddObserverArgs { } impl RewriteAttribute for ObserverArgs { - fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { - let mut args = Vec::new(); - args.push(quote! { plugin = #plugin }); - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - quote! { #(#args),* } - } - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { let mut expanded_attrs = ExpandAttrs::default(); expanded_attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index d6e14838..4a4a7df8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -34,15 +34,6 @@ impl<'a> From<&'a ResourceArgs> for InitResourceArgs { } impl RewriteAttribute for ResourceArgs { - fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { - let mut args = Vec::new(); - args.push(quote! { plugin = #plugin }); - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - quote! { #(#args),* } - } - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { let mut expanded_attrs = ExpandAttrs::default(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 3787de68..193e5c18 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -33,15 +33,6 @@ impl<'a> From<&'a StatesArgs> for InitStateArgs { } impl RewriteAttribute for StatesArgs { - fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { - let mut args = Vec::new(); - args.push(quote! { plugin = #plugin }); - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - quote! { #(#args),* } - } - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { let mut expanded_attrs = ExpandAttrs::default(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 28ffa3d2..0b20db36 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -33,15 +33,6 @@ impl<'a> From<&'a SystemArgs> for AddSystemArgs { } impl RewriteAttribute for SystemArgs { - fn expand_args(&self, plugin: &NonEmptyPath) -> MacroStream { - let mut args = Vec::new(); - args.push(quote! { plugin = #plugin }); - if !self.generics().is_empty() { - args.extend(self.generics().to_attribute_arg_vec_tokens()); - } - quote! { #(#args),* } - } - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { let mut expanded_attrs = ExpandAttrs::default(); expanded_attrs From 8d271547bedd7b30a357475b8da2de0b055f37d4 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 15:58:10 -0400 Subject: [PATCH 037/162] refactor: introduce `AllowAny` and export it in `macro_api` prelude --- .../src/macro_api/attributes/mod.rs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index d6c98ca3..454ea008 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -19,6 +19,7 @@ mod rewrites; mod traits; pub mod prelude { + pub use super::AllowAny; pub use super::AllowFn; pub use super::AllowStructOrEnum; pub use super::AttributeIdent; @@ -97,6 +98,32 @@ impl IdentPathResolver for AllowFn { } } +pub struct AllowAny; +impl IdentPathResolver for AllowAny { + fn resolve_ident_path(item: &Item) -> Option { + Some(match item { + Item::Const(item) => item.ident.clone().into(), + Item::Enum(item) => item.ident.clone().into(), + Item::ExternCrate(item) => item.ident.clone().into(), + Item::Fn(item) => item.sig.ident.clone().into(), + Item::ForeignMod(_) => return None, + Item::Impl(_) => return None, + Item::Macro(item) => return item.ident.clone().map(Into::into), + Item::Mod(item) => item.ident.clone().into(), + Item::Static(item) => item.ident.clone().into(), + Item::Struct(item) => item.ident.clone().into(), + Item::Trait(item) => item.ident.clone().into(), + Item::TraitAlias(item) => item.ident.clone().into(), + Item::Type(item) => item.ident.clone().into(), + Item::Union(item) => item.ident.clone().into(), + // TODO: implement + Item::Use(_) => return None, + Item::Verbatim(_) => return None, + _ => return None, + }) + } +} + pub trait PluginCap { fn plugin_path(&self) -> &syn::Path; } From 3455228f1d0713efbbddc78731b9ce98a8d42680 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 15:58:15 -0400 Subject: [PATCH 038/162] refactor: use `AllowAny` resolver in auto_bind_plugin --- .../src/__private/expand/attr/auto_bind_plugin.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index 55ee2176..b97aa9ea 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -12,15 +12,15 @@ pub fn auto_bind_plugin_inner( context: Context, ) -> syn::Result { // TODO: need to determine correct flow to maintain input tokens for errors - let mut item_attribute = ItemAttribute::, _>::from_attr_input( - attr, - input.clone(), - context, - ) - .map_err(|err| compile_error_with!(err, input.clone()))?; + let mut item_attribute = + ItemAttribute::, AllowAny>::from_attr_input( + attr, + input.clone(), + context, + )?; let plugin_path = item_attribute.args.plugin(); - let mut item = item_attribute.input_item.ensure_ast_mut()?; + let item = item_attribute.input_item.ensure_ast_mut()?; let mut attrs = item .take_attrs() .map_err(|err| syn::Error::new(item.span(), err))?; From 122ecf6f9917273a428b65e72af0cc0df5bbed0f Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 15:59:46 -0400 Subject: [PATCH 039/162] fix: imports in auto_plugin --- .../src/__private/expand/attr/auto_plugin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs index 03bf43f0..de7c104d 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs @@ -3,7 +3,7 @@ use proc_macro2::TokenStream as MacroStream; use syn::ItemFn; pub fn expand_auto_plugin(attr: MacroStream, input: MacroStream) -> MacroStream { - use crate::macro_api::attributes::prelude::{AutoPluginFnArgs, resolve_app_param_name}; + use crate::macro_api::prelude::*; use crate::syntax::analysis::fn_param::require_fn_param_mutable_reference; use proc_macro2::Ident; use quote::quote; From 7b03ea9224bd7839a1ff47b44a6a73f3995ffe3a Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 16:01:21 -0400 Subject: [PATCH 040/162] fix: prelude not exporting all relevant items --- .../src/macro_api/attributes/mod.rs | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 454ea008..41f96fa7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -33,26 +33,8 @@ pub mod prelude { pub use super::auto_plugin::{ AutoPluginFnArgs, AutoPluginStructOrEnumArgs, resolve_app_param_name, }; - pub use crate::macro_api::attributes::actions::prelude::AddMessageArgs; - pub use crate::macro_api::attributes::actions::prelude::AddObserverArgs; - pub use crate::macro_api::attributes::actions::prelude::AddPluginArgs; - pub use crate::macro_api::attributes::actions::prelude::AddSystemArgs; - pub use crate::macro_api::attributes::actions::prelude::ConfigureSystemSetArgs; - pub use crate::macro_api::attributes::actions::prelude::InitResourceArgs; - pub use crate::macro_api::attributes::actions::prelude::InitStateArgs; - pub use crate::macro_api::attributes::actions::prelude::InitSubStateArgs; - pub use crate::macro_api::attributes::actions::prelude::InsertResourceArgs; - pub use crate::macro_api::attributes::actions::prelude::NameArgs; - pub use crate::macro_api::attributes::actions::prelude::RegisterStateTypeArgs; - pub use crate::macro_api::attributes::actions::prelude::RegisterTypeArgs; - pub use crate::macro_api::attributes::actions::prelude::RunOnBuildArgs; - pub use crate::macro_api::attributes::rewrites::prelude::ComponentArgs; - pub use crate::macro_api::attributes::rewrites::prelude::EventArgs; - pub use crate::macro_api::attributes::rewrites::prelude::MessageArgs; - pub use crate::macro_api::attributes::rewrites::prelude::ObserverArgs; - pub use crate::macro_api::attributes::rewrites::prelude::ResourceArgs; - pub use crate::macro_api::attributes::rewrites::prelude::StatesArgs; - pub use crate::macro_api::attributes::rewrites::prelude::SystemArgs; + pub use crate::macro_api::attributes::actions::prelude::*; + pub use crate::macro_api::attributes::rewrites::prelude::*; pub use crate::macro_api::attributes::traits::prelude::*; } From 6c2730372f71b475859dbf5254331d1e2572f6f6 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 16:01:30 -0400 Subject: [PATCH 041/162] fix: rename auto attribute aliases to Ia-prefixed versions --- .../src/__private/expand/attr/mod.rs | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 49e73752..2b7acbfb 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -156,19 +156,19 @@ macro_rules! gen_auto_outers { } gen_auto_attribute_outers! { - auto_run_on_build => RunOnBuild, - auto_register_type => RegisterType, - auto_add_message => AddMessage, - auto_init_resource => InitResource, - auto_insert_resource => InsertResource, - auto_init_state => InitState, - auto_init_sub_state => InitSubState, - auto_name => Name, - auto_register_state_type => RegisterStateType, - auto_add_system => AddSystem, - auto_add_observer => AddObserver, - auto_add_plugin => AddPlugin, - auto_configure_system_set => ConfigureSystemSet, + auto_run_on_build => IaRunOnBuild, + auto_register_type => IaRegisterType, + auto_add_message => IaAddMessage, + auto_init_resource => IaInitResource, + auto_insert_resource => IaInsertResource, + auto_init_state => IaInitState, + auto_init_sub_state => IaInitSubState, + auto_name => IaName, + auto_register_state_type => IaRegisterStateType, + auto_add_system => IaAddSystem, + auto_add_observer => IaAddObserver, + auto_add_plugin => IaAddPlugin, + auto_configure_system_set => IaConfigureSystemSet, } gen_auto_outers! { From 546a6e2326f1a3171ab039d264ed2561da721c05 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 16:07:01 -0400 Subject: [PATCH 042/162] fix: prelude exports missing AutoPluginDeriveArgs --- .../src/__private/expand/derive/auto_plugin.rs | 2 +- .../bevy_auto_plugin_shared/src/macro_api/derives/mod.rs | 8 +++++++- crates/bevy_auto_plugin_shared/src/macro_api/mod.rs | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs index 3a703048..ada8e8c6 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs @@ -3,7 +3,7 @@ use proc_macro2::TokenStream as MacroStream; use syn::spanned::Spanned; pub fn expand_derive_auto_plugin(input: MacroStream) -> MacroStream { - use crate::macro_api::derives::auto_plugin::AutoPluginDeriveArgs; + use crate::macro_api::prelude::*; use crate::syntax::extensions::generics; use darling::FromDeriveInput; use quote::quote; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs index 9d9eb9d6..794fb44e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs @@ -2,7 +2,7 @@ use darling::{FromField, FromVariant}; use proc_macro2::Ident; use syn::Type; -pub mod auto_plugin; +mod auto_plugin; #[allow(dead_code)] #[derive(Debug, FromField)] @@ -17,3 +17,9 @@ pub struct VariantData { pub ident: Ident, pub fields: darling::ast::Fields, } + +pub mod prelude { + pub use super::FieldData; + pub use super::VariantData; + pub use super::auto_plugin::*; +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 79975dc0..898836e4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -14,6 +14,7 @@ pub(crate) mod prelude { pub use attributes::prelude::*; pub use composed::*; pub use context::*; + pub use derives::prelude::*; pub use mixins::prelude::*; pub use q::*; pub use qq::*; From 3dd5656c4ecf6bfa9181eb54946d7301f38f9f0e Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 16:53:32 -0400 Subject: [PATCH 043/162] refactor(wip): restructuring Q/QQ structs and traits --- .../src/codegen/tokens.rs | 77 ++++--------------- .../attributes/actions/auto_add_message.rs | 2 +- .../attributes/actions/auto_add_observer.rs | 2 +- .../attributes/actions/auto_add_plugin.rs | 2 +- .../attributes/actions/auto_add_system.rs | 2 +- .../actions/auto_configure_system_set.rs | 2 +- .../attributes/actions/auto_init_resource.rs | 4 +- .../attributes/actions/auto_init_state.rs | 2 +- .../attributes/actions/auto_init_sub_state.rs | 2 +- .../actions/auto_insert_resource.rs | 2 +- .../macro_api/attributes/actions/auto_name.rs | 2 +- .../actions/auto_register_state_type.rs | 2 +- .../attributes/actions/auto_register_type.rs | 2 +- .../attributes/actions/auto_run_on_build.rs | 2 +- .../src/macro_api/attributes/mod.rs | 16 +++- .../attributes/rewrites/auto_component.rs | 45 +++++------ .../src/macro_api/mod.rs | 2 + .../src/macro_api/q.rs | 14 +--- .../src/macro_api/qq.rs | 39 ++++++++-- .../src/macro_api/rewrite_q.rs | 45 +++++++++++ 20 files changed, 145 insertions(+), 121 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs diff --git a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs index 0b289ff2..e94462bf 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs @@ -5,55 +5,6 @@ use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, quote}; use syn::parse_quote; -#[derive(Debug, Clone)] -pub struct ArgsWithPlugin { - pub plugin: NonEmptyPath, - pub args: T, -} - -impl ArgsWithPlugin -where - T: ArgsBackToTokens, -{ - pub fn new(plugin: NonEmptyPath, args: T) -> Self { - Self { plugin, args } - } - fn back_to_tokens(&self, tokens: &mut TokenStream) { - let macro_path = T::full_attribute_path(); - let inner_args = self.args.back_to_inner_arg_token_stream(); - let args = { - let plugin = &self.plugin; - let mut plugin_args = quote! { plugin = #plugin }; - if !inner_args.is_empty() { - plugin_args.extend(quote! { , #inner_args }); - } - plugin_args - }; - tokens.extend(quote! { - #[#macro_path(#args)] - }); - } -} - -// TODO: break this out so theres one for attributes and generic one for just args in general -pub trait ArgsBackToTokens: AttributeIdent { - fn back_to_inner_arg_tokens(&self, tokens: &mut TokenStream); - fn back_to_inner_arg_token_stream(&self) -> TokenStream { - let mut tokens = TokenStream::new(); - self.back_to_inner_arg_tokens(&mut tokens); - tokens - } -} - -impl ToTokens for ArgsWithPlugin -where - T: ArgsBackToTokens, -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - self.back_to_tokens(tokens); - } -} - pub fn reflect<'a>(idents: impl IntoIterator) -> ExpandAttrs { let idents = idents.into_iter().collect::>(); let use_items = idents @@ -205,24 +156,24 @@ pub fn use_bevy_state_app_ext_states() -> syn::ItemUse { parse_quote! { use #root::app::AppExtStates as _; } } -pub fn auto_register_type(plugin: NonEmptyPath, args: RegisterTypeArgs) -> TokenStream { - ArgsWithPlugin::new(plugin, args).to_token_stream() +pub fn auto_register_type(args: QQRegisterType) -> TokenStream { + args.to_token_stream() } -pub fn auto_name(plugin: NonEmptyPath, args: NameArgs) -> TokenStream { - ArgsWithPlugin::new(plugin, args).to_token_stream() +pub fn auto_name(args: QQName) -> TokenStream { + args.to_token_stream() } -pub fn auto_init_resource(plugin: NonEmptyPath, args: InitResourceArgs) -> TokenStream { - ArgsWithPlugin::new(plugin, args).to_token_stream() +pub fn auto_init_resource(args: QQInitResource) -> TokenStream { + args.to_token_stream() } -pub fn auto_init_states(plugin: NonEmptyPath, args: InitStateArgs) -> TokenStream { - ArgsWithPlugin::new(plugin, args).to_token_stream() +pub fn auto_init_states(args: QQInitState) -> TokenStream { + args.to_token_stream() } -pub fn auto_add_systems(plugin: NonEmptyPath, args: AddSystemArgs) -> TokenStream { - ArgsWithPlugin::new(plugin, args).to_token_stream() +pub fn auto_add_systems(args: QQAddSystem) -> TokenStream { + args.to_token_stream() } -pub fn auto_add_observer(plugin: NonEmptyPath, args: AddObserverArgs) -> TokenStream { - ArgsWithPlugin::new(plugin, args).to_token_stream() +pub fn auto_add_observer(args: QQAddObserver) -> TokenStream { + args.to_token_stream() } -pub fn auto_add_message(plugin: NonEmptyPath, args: AddMessageArgs) -> TokenStream { - ArgsWithPlugin::new(plugin, args).to_token_stream() +pub fn auto_add_message(args: QQAddMessage) -> TokenStream { + args.to_token_stream() } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index a758973b..93f305cc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -16,7 +16,7 @@ pub type IaAddMessage = pub type QAddMessage<'a> = Q<'a, IaAddMessage>; pub type QQAddMessage<'a> = QQ<'a, IaAddMessage>; -impl RequiredUseQTokens for QAddMessage<'_> { +impl ToTokensWithAppParam for QAddMessage<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index febfc301..c5520a46 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -16,7 +16,7 @@ pub type IaAddObserver = pub type QAddObserver<'a> = Q<'a, IaAddObserver>; pub type QQAddObserver<'a> = QQ<'a, IaAddObserver>; -impl RequiredUseQTokens for QAddObserver<'_> { +impl ToTokensWithAppParam for QAddObserver<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index 1cac1c26..61dd50f0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -19,7 +19,7 @@ pub type IaAddPlugin = ItemAttribute, AllowStructOrEnum>; pub type QAddPlugin<'a> = Q<'a, IaAddPlugin>; -impl RequiredUseQTokens for QAddPlugin<'_> { +impl ToTokensWithAppParam for QAddPlugin<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { if let Some(expr) = &self.args.args.base.init.expr { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index 7c9882a8..6b2909be 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -20,7 +20,7 @@ pub type IaAddSystem = pub type QAddSystem<'a> = Q<'a, IaAddSystem>; pub type QQAddSystem<'a> = QQ<'a, IaAddSystem>; -impl RequiredUseQTokens for QAddSystem<'_> { +impl ToTokensWithAppParam for QAddSystem<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let schedule = &self.args.args.base.schedule_config.schedule; let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 3bf58d89..e3a71b56 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -98,7 +98,7 @@ pub type IaConfigureSystemSet = ItemAttribute< pub type QConfigureSystemSet<'a> = Q<'a, IaConfigureSystemSet>; pub type QQConfigureSystemSet<'a> = QQ<'a, IaConfigureSystemSet>; -impl RequiredUseQTokens for QConfigureSystemSet<'_> { +impl ToTokensWithAppParam for QConfigureSystemSet<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args; let generics = args.generics(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 6cfb0e52..aa2fc3a6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -1,5 +1,5 @@ use crate::macro_api::prelude::*; -use crate::macro_api::q::{Q, RequiredUseQTokens}; +use crate::macro_api::q::{Q, ToTokensWithAppParam}; use darling::FromMeta; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; @@ -19,7 +19,7 @@ pub type IaInitResource = ItemAttribute< pub type QInitResource<'a> = Q<'a, IaInitResource>; pub type QQInitResource<'a> = QQ<'a, IaInitResource>; -impl RequiredUseQTokens for QInitResource<'_> { +impl ToTokensWithAppParam for QInitResource<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index 481164d3..d453ec51 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -16,7 +16,7 @@ pub type IaInitState = pub type QInitState<'a> = Q<'a, IaInitState>; pub type QQInitState<'a> = QQ<'a, IaInitState>; -impl RequiredUseQTokens for QInitState<'_> { +impl ToTokensWithAppParam for QInitState<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 9a85fd8c..9793e5e5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -16,7 +16,7 @@ pub type IaInitSubState = pub type QInitSubState<'a> = Q<'a, IaInitSubState>; pub type QQInitSubState<'a> = QQ<'a, IaInitSubState>; -impl RequiredUseQTokens for QInitSubState<'_> { +impl ToTokensWithAppParam for QInitSubState<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 7f811cc0..17e802ea 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -21,7 +21,7 @@ pub type IaInsertResource = ItemAttribute< pub type QInsertResource<'a> = Q<'a, IaInsertResource>; pub type QQInsertResource<'a> = QQ<'a, IaInsertResource>; -impl RequiredUseQTokens for QInsertResource<'_> { +impl ToTokensWithAppParam for QInsertResource<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index 54adb042..568e2e91 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -19,7 +19,7 @@ pub type IaName = pub type QName<'a> = Q<'a, IaName>; pub type QQName<'a> = QQ<'a, IaName>; -impl RequiredUseQTokens for QName<'_> { +impl ToTokensWithAppParam for QName<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args.base; for concrete_path in self.args.concrete_paths() { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 674d6d31..4da263e7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -18,7 +18,7 @@ pub type IaRegisterStateType = ItemAttribute< pub type QRegisterStateType<'a> = Q<'a, IaRegisterStateType>; pub type QQRegisterStateType<'a> = QQ<'a, IaRegisterStateType>; -impl RequiredUseQTokens for QRegisterStateType<'_> { +impl ToTokensWithAppParam for QRegisterStateType<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { let bevy_state = crate::__private::paths::state::root_path(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 7a06b255..5900f456 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -18,7 +18,7 @@ pub type IaRegisterType = ItemAttribute< pub type QRegisterType<'a> = Q<'a, IaRegisterType>; pub type QQRegisterType<'a> = QQ<'a, IaRegisterType>; -impl RequiredUseQTokens for QRegisterType<'_> { +impl ToTokensWithAppParam for QRegisterType<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index c41c7138..a3540539 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -16,7 +16,7 @@ pub type IaRunOnBuild = pub type QRunOnBuild<'a> = Q<'a, IaRunOnBuild>; pub type QQRunOnBuild<'a> = QQ<'a, IaRunOnBuild>; -impl RequiredUseQTokens for QRunOnBuild<'_> { +impl ToTokensWithAppParam for QRunOnBuild<'_> { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 41f96fa7..71ee1bfa 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -146,14 +146,28 @@ where } } +pub trait ItemAttributeContext { + fn context(&self) -> &Context; +} + +impl ItemAttributeContext for ItemAttribute { + fn context(&self) -> &Context { + &self.context + } +} + pub trait ItemAttributeInput { fn input_item(&self) -> &InputItem; + fn input_item_mut(&mut self) -> &mut InputItem; } impl ItemAttributeInput for ItemAttribute { fn input_item(&self) -> &InputItem { &self.input_item } + fn input_item_mut(&mut self) -> &mut InputItem { + &mut self.input_item + } } pub trait ItemAttributeParse { @@ -163,7 +177,7 @@ pub trait ItemAttributeParse { context: Context, ) -> syn::Result where - Self: Sized; + Self: Sized + ItemAttributeInput + ItemAttributeContext + ItemAttributeArgs; } impl ItemAttributeParse for ItemAttribute diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index ec44c74c..8f297fa2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -36,40 +36,33 @@ impl<'a> From<&'a ComponentArgs> for NameArgs { } } -impl RewriteAttribute for ComponentArgs { - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { - let mut expanded_attrs = ExpandAttrs::default(); +pub type IaComponent = + ItemAttribute, AllowStructOrEnum>; +pub type RewriteQComponent<'a> = RewriteQ<'a, IaComponent>; - if self.derive.present { - expanded_attrs +impl RewriteQToExpandAttr for RewriteQComponent<'_> { + fn to_expand_attr(&self, expand_attrs: &mut ExpandAttrs) { + if self.args.args.base.derive.present { + expand_attrs .attrs - .push(tokens::derive_component(&self.derive.items)); + .push(tokens::derive_component(&self.args.args.base.derive.items)); } - if self.reflect.present { - if self.derive.present { - expanded_attrs.attrs.push(tokens::derive_reflect()); + if self.args.args.base.reflect.present { + if self.args.args.base.derive.present { + expand_attrs.attrs.push(tokens::derive_reflect()); } let component_ident: Ident = parse_quote!(Component); - let items = std::iter::once(&component_ident).chain(self.reflect.items.iter()); - expanded_attrs.append(tokens::reflect(items)) + let items = + std::iter::once(&component_ident).chain(self.args.args.base.reflect.items.iter()); + expand_attrs.append(tokens::reflect(items)) } - if self.register { - expanded_attrs + if self.args.args.base.register { + expand_attrs .attrs - .push(tokens::auto_register_type(plugin.clone(), self.into())); + .push(tokens::auto_register_type(self.into())); } - if self.auto_name.present { - expanded_attrs - .attrs - .push(tokens::auto_name(plugin.clone(), self.into())); + if self.args.args.base.auto_name.present { + expand_attrs.attrs.push(tokens::auto_name(self.into())); } - expanded_attrs } } - -pub type IaComponent = - ItemAttribute, AllowStructOrEnum>; -pub type QComponent<'a> = Q<'a, IaComponent>; -impl ToTokens for QComponent<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) {} -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 898836e4..3b34e1b4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -7,6 +7,7 @@ mod macro_paths; mod mixins; mod q; mod qq; +mod rewrite_q; mod schedule_config; pub(crate) mod prelude { @@ -18,4 +19,5 @@ pub(crate) mod prelude { pub use mixins::prelude::*; pub use q::*; pub use qq::*; + pub use rewrite_q::*; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 3793b46c..145bb786 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -1,8 +1,6 @@ -use crate::macro_api::attributes::prelude::*; -use crate::macro_api::attributes::{GenericsCap, ItemAttributeParse}; +use crate::macro_api::attributes::ItemAttributeParse; use proc_macro2::TokenStream; use quote::{ToTokens, format_ident}; -use syn::parse::Parse; /// for codegen attaching to bevy app pub(crate) struct Q<'a, T> { @@ -23,19 +21,15 @@ where } } -pub trait RequiredUseQTokens { - fn required_uses(&self) -> Vec { - vec![] - } +pub trait ToTokensWithAppParam { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident); } impl<'a, T> ToTokens for Q<'a, T> where - Self: RequiredUseQTokens, + Self: ToTokensWithAppParam, { fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(self.required_uses()); - RequiredUseQTokens::to_tokens(self, tokens, &self.app_param); + ToTokensWithAppParam::to_tokens(self, tokens, &self.app_param); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 6b4575fd..5d2edea2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -1,5 +1,8 @@ +use crate::codegen::ExpandAttrs; use crate::macro_api::attributes::prelude::*; -use crate::macro_api::attributes::{AllowFn, AllowStructOrEnum, ItemAttribute}; +use crate::macro_api::attributes::{ + AllowFn, AllowStructOrEnum, ItemAttribute, ItemAttributeContext, +}; use crate::macro_api::composed::Composed; use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; @@ -16,20 +19,42 @@ use syn::spanned::Spanned; /// for codegen re-emitting macro args pub(crate) struct QQ<'a, T> { - pub(crate) args: &'a T, - pub(crate) context: &'a Context, - pub(crate) input_item: &'a mut InputItem, + pub(crate) args: &'a mut T, +} + +impl<'a, T> QQ<'a, T> +where + T: ItemAttributeInput, +{ + pub(crate) fn from_args(args: &'a mut T) -> QQ<'a, T> { + QQ::<'a, T> { args } + } +} + +pub trait QQToExpandAttr { + fn to_expand_attr(&self, expand_attrs: &mut ExpandAttrs); +} + +impl<'a, T> ToTokens for QQ<'a, T> +where + Self: QQToExpandAttr, +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut expand_attr = ExpandAttrs::default(); + QQToExpandAttr::to_expand_attr(self, &mut expand_attr); + expand_attr.to_tokens(tokens); + } } impl QQ<'_, T> where - T: MacroPathProvider, + T: MacroPathProvider + ItemAttributeInput + ItemAttributeContext, Self: ToTokens, { pub fn inject_attribute_macro(&mut self) -> syn::Result<()> { let args = self.to_token_stream(); - self.input_item.map_ast(|item| { - let macro_path = T::macro_path(self.context); + let macro_path = T::macro_path(self.args.context()).clone(); + self.args.input_item_mut().map_ast(|item| { // insert attribute tokens let mut attrs = item .take_attrs() diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs new file mode 100644 index 00000000..b4824757 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs @@ -0,0 +1,45 @@ +use crate::codegen::ExpandAttrs; +use crate::macro_api::prelude::*; +use proc_macro2::TokenStream; +use quote::ToTokens; + +/// for codegen rewriting attrs +pub(crate) struct RewriteQ<'a, T> { + pub(crate) args: &'a mut T, +} + +impl RewriteQ<'_, T> +where + T: ItemAttributeParse, +{ + pub fn from_item_attribute(item_attribute: &mut T) -> RewriteQ { + RewriteQ:: { + args: item_attribute, + } + } +} + +pub trait RewriteQToExpandAttr { + fn to_expand_attr(&self, expand_attrs: &mut ExpandAttrs); +} + +impl<'a, T> ToTokens for RewriteQ<'a, T> +where + Self: RewriteQToExpandAttr, +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + let mut expand_attr = ExpandAttrs::default(); + RewriteQToExpandAttr::to_expand_attr(self, &mut expand_attr); + expand_attr.to_tokens(tokens); + } +} + +impl<'a, TFrom, TTo, P, G, R> From, R>>> + for QQ<'a, ItemAttribute, R>> +where + TTo: From, +{ + fn from(value: RewriteQ<'a, ItemAttribute, R>>) -> Self { + QQ::<'a, ItemAttribute, R>>::from_args(TTo::from(value.args)) + } +} From cda48247636217d96c42b6d7090e55bc018c49dc Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 19:22:12 -0400 Subject: [PATCH 044/162] feat: add `impl_from_default` macro to simplify trait implementations --- crates/bevy_auto_plugin_shared/src/util/macros.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/util/macros.rs b/crates/bevy_auto_plugin_shared/src/util/macros.rs index e954cc31..939b6d77 100644 --- a/crates/bevy_auto_plugin_shared/src/util/macros.rs +++ b/crates/bevy_auto_plugin_shared/src/util/macros.rs @@ -121,6 +121,18 @@ macro_rules! bevy_crate_path { }}; } +macro_rules! impl_from_default { + ($from:ident => ($($to:ident),* $(,)?)) => { + $( + impl From<$from> for $to { + fn from(_: $from) -> Self { + Self::default() + } + } + )* + }; +} + #[allow(unused_imports)] #[rustfmt::skip] pub(crate) use { @@ -131,6 +143,7 @@ pub(crate) use { parse_macro_input2_or_emit_with, as_cargo_alias, bevy_crate_path, + impl_from_default, }; #[cfg(test)] From 3fb42e157b3862e62525a88181da7f27cd1cd307 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 19:22:28 -0400 Subject: [PATCH 045/162] refactor: remove lifetime annotations from Q/QQ types and update trait implementations --- .../src/__private/expand/attr/mod.rs | 12 ++-- .../attributes/actions/auto_add_message.rs | 8 +-- .../attributes/actions/auto_add_observer.rs | 8 +-- .../attributes/actions/auto_add_plugin.rs | 15 ++--- .../attributes/actions/auto_add_system.rs | 8 +-- .../actions/auto_configure_system_set.rs | 8 +-- .../attributes/actions/auto_init_resource.rs | 8 +-- .../attributes/actions/auto_init_state.rs | 8 +-- .../attributes/actions/auto_init_sub_state.rs | 8 +-- .../actions/auto_insert_resource.rs | 8 +-- .../macro_api/attributes/actions/auto_name.rs | 8 +-- .../actions/auto_register_state_type.rs | 8 +-- .../attributes/actions/auto_register_type.rs | 8 +-- .../attributes/actions/auto_run_on_build.rs | 8 +-- .../src/macro_api/attributes/mod.rs | 67 ++++++++++++++++++- .../attributes/rewrites/auto_component.rs | 9 ++- .../attributes/rewrites/auto_event.rs | 51 +++++++------- .../attributes/rewrites/auto_message.rs | 42 ++++++------ .../attributes/rewrites/auto_observer.rs | 22 +++--- .../attributes/rewrites/auto_resource.rs | 47 ++++++------- .../attributes/rewrites/auto_states.rs | 43 ++++++------ .../attributes/rewrites/auto_system.rs | 25 ++++--- .../src/macro_api/composed.rs | 27 ++++++++ .../src/macro_api/context.rs | 2 +- .../src/macro_api/input_item.rs | 26 ++++--- .../src/macro_api/macro_paths.rs | 2 +- .../src/macro_api/mixins/generics/none.rs | 4 ++ .../macro_api/mixins/generics/with_single.rs | 4 ++ .../src/macro_api/mixins/mod.rs | 2 +- .../src/macro_api/mod.rs | 1 + .../src/macro_api/q.rs | 14 ++-- .../src/macro_api/qq.rs | 33 +++------ .../src/macro_api/rewrite_q.rs | 36 +++++++--- 33 files changed, 334 insertions(+), 246 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 2b7acbfb..7a0b0510 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -10,11 +10,11 @@ pub mod auto_plugin; fn body( body: impl Fn(MacroStream) -> MacroStream, -) -> impl Fn(&Ident, Q<'_, ItemAttribute, R>>) -> syn::Result +) -> impl Fn(&Ident, Q, R>>) -> syn::Result where T: ItemAttributeArgs + Hash, G: Hash + Clone, - for<'a> Q<'a, ItemAttribute, R>>: ToTokens, + Q, R>>: ToTokens, { move |ident, params| { let app_param = ¶ms.app_param; @@ -37,15 +37,15 @@ where fn proc_attribute_outer(attr: MacroStream, input: MacroStream) -> MacroStream where - T: ItemAttributeParse + ItemAttributeInput, - for<'a> Q<'a, T>: ToTokens, + T: ItemAttributeArgs + ItemAttributeParse + ItemAttributeInput + ItemAttributeContext, + Q: ToTokens, { let args = ok_or_emit_with!( T::from_attr_input_with_context(attr, input.clone(), Context::default()), input ); - let input = args.input_item(); - let after_item_tokens = Q::from_args(&args).to_token_stream(); + let input = args.input_item().clone(); + let after_item_tokens = Q::from_args(args).to_token_stream(); quote! { #input #after_item_tokens diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index 93f305cc..d122ae8b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -13,10 +13,10 @@ impl AttributeIdent for AddMessageArgs { pub type IaAddMessage = ItemAttribute, AllowStructOrEnum>; -pub type QAddMessage<'a> = Q<'a, IaAddMessage>; -pub type QQAddMessage<'a> = QQ<'a, IaAddMessage>; +pub type QAddMessage = Q; +pub type QQAddMessage = QQ; -impl ToTokensWithAppParam for QAddMessage<'_> { +impl ToTokensWithAppParam for QAddMessage { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl ToTokensWithAppParam for QAddMessage<'_> { } } -impl ToTokens for QQAddMessage<'_> { +impl ToTokens for QQAddMessage { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index c5520a46..279f1d59 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -13,10 +13,10 @@ impl AttributeIdent for AddObserverArgs { pub type IaAddObserver = ItemAttribute, AllowFn>; -pub type QAddObserver<'a> = Q<'a, IaAddObserver>; -pub type QQAddObserver<'a> = QQ<'a, IaAddObserver>; +pub type QAddObserver = Q; +pub type QQAddObserver = QQ; -impl ToTokensWithAppParam for QAddObserver<'_> { +impl ToTokensWithAppParam for QAddObserver { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl ToTokensWithAppParam for QAddObserver<'_> { } } -impl ToTokens for QQAddObserver<'_> { +impl ToTokens for QQAddObserver { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index 61dd50f0..ac9d84d4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -17,9 +17,10 @@ impl AttributeIdent for AddPluginArgs { pub type IaAddPlugin = ItemAttribute, AllowStructOrEnum>; -pub type QAddPlugin<'a> = Q<'a, IaAddPlugin>; +pub type QAddPlugin = Q; +pub type QQAddPlugin = QQ; -impl ToTokensWithAppParam for QAddPlugin<'_> { +impl ToTokensWithAppParam for QAddPlugin { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { if let Some(expr) = &self.args.args.base.init.expr { @@ -39,15 +40,7 @@ impl ToTokensWithAppParam for QAddPlugin<'_> { } } -impl ToTokens - for QQ< - '_, - ItemAttribute< - Composed, - AllowStructOrEnum, - >, - > -{ +impl ToTokens for QQAddPlugin { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index 6b2909be..f133a094 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -17,10 +17,10 @@ impl AttributeIdent for AddSystemArgs { pub type IaAddSystem = ItemAttribute, AllowFn>; -pub type QAddSystem<'a> = Q<'a, IaAddSystem>; -pub type QQAddSystem<'a> = QQ<'a, IaAddSystem>; +pub type QAddSystem = Q; +pub type QQAddSystem = QQ; -impl ToTokensWithAppParam for QAddSystem<'_> { +impl ToTokensWithAppParam for QAddSystem { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let schedule = &self.args.args.base.schedule_config.schedule; let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); @@ -32,7 +32,7 @@ impl ToTokensWithAppParam for QAddSystem<'_> { } } -impl ToTokens for QQAddSystem<'_> { +impl ToTokens for QQAddSystem { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); // TODO: cleanup diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index e3a71b56..a214b01e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -95,10 +95,10 @@ pub type IaConfigureSystemSet = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QConfigureSystemSet<'a> = Q<'a, IaConfigureSystemSet>; -pub type QQConfigureSystemSet<'a> = QQ<'a, IaConfigureSystemSet>; +pub type QConfigureSystemSet = Q; +pub type QQConfigureSystemSet = QQ; -impl ToTokensWithAppParam for QConfigureSystemSet<'_> { +impl ToTokensWithAppParam for QConfigureSystemSet { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args; let generics = args.generics(); @@ -153,7 +153,7 @@ impl ToTokensWithAppParam for QConfigureSystemSet<'_> { } } -impl ToTokens for QQConfigureSystemSet<'_> { +impl ToTokens for QQConfigureSystemSet { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); // TODO: cleanup diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index aa2fc3a6..9ce0dfcd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -16,10 +16,10 @@ pub type IaInitResource = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QInitResource<'a> = Q<'a, IaInitResource>; -pub type QQInitResource<'a> = QQ<'a, IaInitResource>; +pub type QInitResource = Q; +pub type QQInitResource = QQ; -impl ToTokensWithAppParam for QInitResource<'_> { +impl ToTokensWithAppParam for QInitResource { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -29,7 +29,7 @@ impl ToTokensWithAppParam for QInitResource<'_> { } } -impl ToTokens for QQInitResource<'_> { +impl ToTokens for QQInitResource { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index d453ec51..ba246d17 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -13,10 +13,10 @@ impl AttributeIdent for InitStateArgs { pub type IaInitState = ItemAttribute, AllowStructOrEnum>; -pub type QInitState<'a> = Q<'a, IaInitState>; -pub type QQInitState<'a> = QQ<'a, IaInitState>; +pub type QInitState = Q; +pub type QQInitState = QQ; -impl ToTokensWithAppParam for QInitState<'_> { +impl ToTokensWithAppParam for QInitState { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { @@ -25,7 +25,7 @@ impl ToTokensWithAppParam for QInitState<'_> { } } -impl ToTokens for QQInitState<'_> { +impl ToTokens for QQInitState { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 9793e5e5..f01cf606 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -13,10 +13,10 @@ impl AttributeIdent for InitSubStateArgs { pub type IaInitSubState = ItemAttribute, AllowStructOrEnum>; -pub type QInitSubState<'a> = Q<'a, IaInitSubState>; -pub type QQInitSubState<'a> = QQ<'a, IaInitSubState>; +pub type QInitSubState = Q; +pub type QQInitSubState = QQ; -impl ToTokensWithAppParam for QInitSubState<'_> { +impl ToTokensWithAppParam for QInitSubState { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { @@ -25,7 +25,7 @@ impl ToTokensWithAppParam for QInitSubState<'_> { } } -impl ToTokens for QQInitSubState<'_> { +impl ToTokens for QQInitSubState { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 17e802ea..bc8fb4f5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -18,10 +18,10 @@ pub type IaInsertResource = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QInsertResource<'a> = Q<'a, IaInsertResource>; -pub type QQInsertResource<'a> = QQ<'a, IaInsertResource>; +pub type QInsertResource = Q; +pub type QQInsertResource = QQ; -impl ToTokensWithAppParam for QInsertResource<'_> { +impl ToTokensWithAppParam for QInsertResource { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { |app| { @@ -31,7 +31,7 @@ impl ToTokensWithAppParam for QInsertResource<'_> { } } -impl ToTokens for QQInsertResource<'_> { +impl ToTokens for QQInsertResource { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); let resource = &self.args.args.base.resource; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index 568e2e91..32aa57ef 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -16,10 +16,10 @@ impl AttributeIdent for NameArgs { pub type IaName = ItemAttribute, AllowStructOrEnum>; -pub type QName<'a> = Q<'a, IaName>; -pub type QQName<'a> = QQ<'a, IaName>; +pub type QName = Q; +pub type QQName = QQ; -impl ToTokensWithAppParam for QName<'_> { +impl ToTokensWithAppParam for QName { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args.base; for concrete_path in self.args.concrete_paths() { @@ -45,7 +45,7 @@ impl ToTokensWithAppParam for QName<'_> { } } -impl ToTokens for QQName<'_> { +impl ToTokens for QQName { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); if let Some(name) = &self.args.args.base.name { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 4da263e7..9ac9df02 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -15,10 +15,10 @@ pub type IaRegisterStateType = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QRegisterStateType<'a> = Q<'a, IaRegisterStateType>; -pub type QQRegisterStateType<'a> = QQ<'a, IaRegisterStateType>; +pub type QRegisterStateType = Q; +pub type QQRegisterStateType = QQ; -impl ToTokensWithAppParam for QRegisterStateType<'_> { +impl ToTokensWithAppParam for QRegisterStateType { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { let bevy_state = crate::__private::paths::state::root_path(); @@ -30,7 +30,7 @@ impl ToTokensWithAppParam for QRegisterStateType<'_> { } } -impl ToTokens for QQRegisterStateType<'_> { +impl ToTokens for QQRegisterStateType { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 5900f456..7ce64c80 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -15,10 +15,10 @@ pub type IaRegisterType = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QRegisterType<'a> = Q<'a, IaRegisterType>; -pub type QQRegisterType<'a> = QQ<'a, IaRegisterType>; +pub type QRegisterType = Q; +pub type QQRegisterType = QQ; -impl ToTokensWithAppParam for QRegisterType<'_> { +impl ToTokensWithAppParam for QRegisterType { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -27,7 +27,7 @@ impl ToTokensWithAppParam for QRegisterType<'_> { } } } -impl ToTokens for QQRegisterType<'_> { +impl ToTokens for QQRegisterType { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index a3540539..8460fca2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -13,10 +13,10 @@ impl AttributeIdent for RunOnBuildArgs { pub type IaRunOnBuild = ItemAttribute, AllowStructOrEnum>; -pub type QRunOnBuild<'a> = Q<'a, IaRunOnBuild>; -pub type QQRunOnBuild<'a> = QQ<'a, IaRunOnBuild>; +pub type QRunOnBuild = Q; +pub type QQRunOnBuild = QQ; -impl ToTokensWithAppParam for QRunOnBuild<'_> { +impl ToTokensWithAppParam for QRunOnBuild { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl ToTokensWithAppParam for QRunOnBuild<'_> { } } -impl ToTokens for QQRunOnBuild<'_> { +impl ToTokens for QQRunOnBuild { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 71ee1bfa..0e99c964 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -3,6 +3,7 @@ use crate::macro_api::context::Context; use crate::macro_api::input_item::InputItem; use crate::macro_api::mixins::generics::HasGenerics; use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::macro_api::prelude::ConvertComposed; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use proc_macro2::{Ident, TokenStream}; @@ -27,6 +28,7 @@ pub mod prelude { pub use super::IdentPathResolver; pub use super::ItemAttribute; pub use super::ItemAttributeArgs; + pub use super::ItemAttributeContext; pub use super::ItemAttributeInput; pub use super::ItemAttributeParse; pub use super::PluginCap; @@ -52,11 +54,27 @@ pub trait ItemAttributeArgs: AttributeIdent + Hash + Clone { } } +impl AttributeIdent for ItemAttribute, R> +where + T: AttributeIdent + Hash + Clone, +{ + const IDENT: &'static str = T::IDENT; +} +impl ItemAttributeArgs for ItemAttribute, R> +where + T: AttributeIdent + Hash + Clone, + P: Clone + Hash, + G: Clone + Hash, + R: Clone + Hash, +{ +} + pub trait IdentPathResolver { const NOT_ALLOWED_MESSAGE: &'static str = "Unable to resolve ident path"; fn resolve_ident_path(item: &Item) -> Option; } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AllowStructOrEnum; impl IdentPathResolver for AllowStructOrEnum { const NOT_ALLOWED_MESSAGE: &'static str = "Only allowed on Struct Or Enum items"; @@ -69,6 +87,7 @@ impl IdentPathResolver for AllowStructOrEnum { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AllowFn; impl IdentPathResolver for AllowFn { const NOT_ALLOWED_MESSAGE: &'static str = "Only allowed on Fn items"; @@ -80,6 +99,7 @@ impl IdentPathResolver for AllowFn { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AllowAny; impl IdentPathResolver for AllowAny { fn resolve_ident_path(item: &Item) -> Option { @@ -115,6 +135,7 @@ pub trait GenericsCap { fn concrete_paths(&self) -> Vec; } +#[derive(Debug, Clone, PartialEq)] pub struct ItemAttribute { pub args: T, pub context: Context, @@ -123,6 +144,19 @@ pub struct ItemAttribute { pub _resolver: PhantomData, } +impl Hash for ItemAttribute +where + T: Hash, + R: Hash, +{ + fn hash(&self, state: &mut H) { + self.args.hash(state); + self.context.hash(state); + self.target.hash(state); + self._resolver.hash(state); + } +} + // TODO: where should this live? impl ItemAttribute where @@ -204,7 +238,7 @@ where input: TokenStream, context: Context, ) -> syn::Result { - let mut input_item = InputItem::new(input); + let mut input_item = InputItem::Tokens(input); let item = input_item.ensure_ast()?; let Some(target) = Resolver::resolve_ident_path(item) else { return Err(syn::Error::new( @@ -264,3 +298,34 @@ where } } } + +impl From, R>> + for ItemAttribute>, R> +where + TTo: From, +{ + fn from(value: ItemAttribute, R>) -> Self { + ItemAttribute { + args: ConvertComposed::from(value.args), + context: value.context, + input_item: value.input_item, + target: value.target, + _resolver: PhantomData, + } + } +} + +impl From, R>> for ItemAttribute +where + T: From>, +{ + fn from(value: ItemAttribute, R>) -> Self { + ItemAttribute { + args: T::from(value.args), + context: value.context, + input_item: value.input_item, + target: value.target, + _resolver: PhantomData, + } + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index 8f297fa2..e32d9552 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -4,6 +4,7 @@ use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::ast::flag_or_lit::FlagOrLit; use crate::syntax::validated::non_empty_path::NonEmptyPath; +use crate::util::macros::impl_from_default; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; use quote::{ToTokens, quote}; @@ -38,10 +39,10 @@ impl<'a> From<&'a ComponentArgs> for NameArgs { pub type IaComponent = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQComponent<'a> = RewriteQ<'a, IaComponent>; +pub type RewriteQComponent = RewriteQ; -impl RewriteQToExpandAttr for RewriteQComponent<'_> { - fn to_expand_attr(&self, expand_attrs: &mut ExpandAttrs) { +impl RewriteQToExpandAttr for RewriteQComponent { + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs .attrs @@ -66,3 +67,5 @@ impl RewriteQToExpandAttr for RewriteQComponent<'_> { } } } + +impl_from_default!(ComponentArgs => (RegisterTypeArgs, NameArgs)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 41055f71..c47cdc43 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -1,10 +1,10 @@ -use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; +use crate::util::macros::impl_from_default; use darling::FromMeta; -use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; +use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, quote}; #[derive(FromMeta, Default, Debug, Copy, Clone, PartialEq, Hash)] @@ -49,40 +49,35 @@ impl<'a> From<&'a EventArgs> for RegisterTypeArgs { } } -impl RewriteAttribute for EventArgs { - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { - let mut expanded_attrs = ExpandAttrs::default(); - - if self.derive.present { - if matches!(self.target, EventTarget::Global) { - expanded_attrs +pub type IaEvent = + ItemAttribute, AllowStructOrEnum>; +pub type RewriteQEvent = RewriteQ; +impl RewriteQToExpandAttr for RewriteQEvent { + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { + if self.args.args.base.derive.present { + if matches!(self.args.args.base.target, EventTarget::Global) { + expand_attrs .attrs - .push(tokens::derive_event(&self.derive.items)); + .push(tokens::derive_event(&self.args.args.base.derive.items)); } - if matches!(self.target, EventTarget::Entity) { - expanded_attrs - .attrs - .push(tokens::derive_entity_event(&self.derive.items)); + if matches!(self.args.args.base.target, EventTarget::Entity) { + expand_attrs.attrs.push(tokens::derive_entity_event( + &self.args.args.base.derive.items, + )); } } - if self.reflect.present { - if self.derive.present { - expanded_attrs.attrs.push(tokens::derive_reflect()); + if self.args.args.base.reflect.present { + if self.args.args.base.derive.present { + expand_attrs.attrs.push(tokens::derive_reflect()); } - expanded_attrs.append(tokens::reflect(&self.reflect.items)) + expand_attrs.append(tokens::reflect(&self.args.args.base.reflect.items)) } - if self.register { - expanded_attrs + if self.args.args.base.register { + expand_attrs .attrs - .push(tokens::auto_register_type(plugin.clone(), self.into())); + .push(tokens::auto_register_type(self.into())); } - expanded_attrs } } -pub type IaEvent = - ItemAttribute, AllowStructOrEnum>; -pub type QEvent<'a> = Q<'a, IaEvent>; -impl ToTokens for QEvent<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) {} -} +impl_from_default!(EventArgs => (RegisterTypeArgs)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 5374d7f7..b55c7b98 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -3,6 +3,7 @@ use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; +use crate::util::macros::impl_from_default; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; use quote::{ToTokens, quote}; @@ -31,39 +32,34 @@ impl<'a> From<&'a MessageArgs> for AddMessageArgs { } } -impl RewriteAttribute for MessageArgs { - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { - let mut expanded_attrs = ExpandAttrs::default(); +pub type IaMessage = + ItemAttribute, AllowStructOrEnum>; +pub type RewriteQMessage = RewriteQ; - if self.derive.present { - expanded_attrs +impl RewriteQToExpandAttr for RewriteQMessage { + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { + if self.args.args.base.derive.present { + expand_attrs .attrs - .push(tokens::derive_message(&self.derive.items)); + .push(tokens::derive_message(&self.args.args.base.derive.items)); } - if self.reflect.present { - if self.derive.present { - expanded_attrs.attrs.push(tokens::derive_reflect()); + if self.args.args.base.reflect.present { + if self.args.args.base.derive.present { + expand_attrs.attrs.push(tokens::derive_reflect()); } - expanded_attrs.append(tokens::reflect(&self.reflect.items)) + expand_attrs.append(tokens::reflect(&self.args.args.base.reflect.items)) } - if self.register { - expanded_attrs + if self.args.args.base.register { + expand_attrs .attrs - .push(tokens::auto_register_type(plugin.clone(), self.into())); + .push(tokens::auto_register_type(self.into())); } // TODO: should this be gated behind a flag? - expanded_attrs + expand_attrs .attrs - .push(tokens::auto_add_message(plugin.clone(), self.into())); - - expanded_attrs + .push(tokens::auto_add_message(self.into())); } } -pub type IaMessage = - ItemAttribute, AllowStructOrEnum>; -pub type QMessage<'a> = Q<'a, IaMessage>; -impl ToTokens for QMessage<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) {} -} +impl_from_default!(MessageArgs => (RegisterTypeArgs, AddMessageArgs)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index 6f86e4d2..d3379da0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -2,6 +2,7 @@ use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::validated::non_empty_path::NonEmptyPath; +use crate::util::macros::impl_from_default; use darling::FromMeta; use proc_macro2::{TokenStream as MacroStream, TokenStream}; use quote::{ToTokens, quote}; @@ -26,19 +27,16 @@ impl<'a> From<&'a ObserverArgs> for AddObserverArgs { } } -impl RewriteAttribute for ObserverArgs { - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { - let mut expanded_attrs = ExpandAttrs::default(); - expanded_attrs +pub type IaObserver = + ItemAttribute, AllowFn>; +pub type RewriteQObserver = RewriteQ; + +impl RewriteQToExpandAttr for RewriteQObserver { + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { + expand_attrs .attrs - .push(tokens::auto_add_observer(plugin.clone(), self.into())); - expanded_attrs + .push(tokens::auto_add_observer(self.into())); } } -pub type IaObserver = - ItemAttribute, AllowFn>; -pub type QObserver<'a> = Q<'a, IaObserver>; -impl ToTokens for QObserver<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) {} -} +impl_from_default!(ObserverArgs => (AddObserverArgs)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 4a4a7df8..cad2756d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -3,6 +3,7 @@ use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; +use crate::util::macros::impl_from_default; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; use quote::{ToTokens, quote}; @@ -33,40 +34,36 @@ impl<'a> From<&'a ResourceArgs> for InitResourceArgs { } } -impl RewriteAttribute for ResourceArgs { - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { - let mut expanded_attrs = ExpandAttrs::default(); - - if self.derive.present { - expanded_attrs +pub type IaResource = + ItemAttribute, AllowStructOrEnum>; +pub type RewriteQResource = RewriteQ; +impl RewriteQToExpandAttr for RewriteQResource { + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { + if self.args.args.base.derive.present { + expand_attrs .attrs - .push(tokens::derive_resource(&self.derive.items)); + .push(tokens::derive_resource(&self.args.args.base.derive.items)); } - if self.reflect.present { - if self.derive.present { - expanded_attrs.attrs.push(tokens::derive_reflect()); + if self.args.args.base.reflect.present { + if self.args.args.base.derive.present { + expand_attrs.attrs.push(tokens::derive_reflect()); } let component_ident: Ident = parse_quote!(Resource); - let items = std::iter::once(&component_ident).chain(self.reflect.items.iter()); - expanded_attrs.append(tokens::reflect(items)) + let items = + std::iter::once(&component_ident).chain(self.args.args.base.reflect.items.iter()); + expand_attrs.append(tokens::reflect(items)) } - if self.register { - expanded_attrs + if self.args.args.base.register { + expand_attrs .attrs - .push(tokens::auto_register_type(plugin.clone(), self.into())); + .push(tokens::auto_register_type(self.into())); } - if self.init { - expanded_attrs + if self.args.args.base.init { + expand_attrs .attrs - .push(tokens::auto_init_resource(plugin.clone(), self.into())); + .push(tokens::auto_init_resource(self.into())); } - expanded_attrs } } -pub type IaResource = - ItemAttribute, AllowStructOrEnum>; -pub type QResource<'a> = Q<'a, IaResource>; -impl ToTokens for QResource<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) {} -} +impl_from_default!(ResourceArgs => (RegisterTypeArgs, InitResourceArgs)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 193e5c18..76e50632 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -3,6 +3,7 @@ use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; +use crate::util::macros::impl_from_default; use darling::FromMeta; use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; use quote::{ToTokens, quote}; @@ -31,37 +32,31 @@ impl<'a> From<&'a StatesArgs> for InitStateArgs { Self::default() } } - -impl RewriteAttribute for StatesArgs { - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { - let mut expanded_attrs = ExpandAttrs::default(); - - if self.derive.present { - expanded_attrs.append(tokens::derive_states(&self.derive.items)); +pub type IaState = + ItemAttribute, AllowStructOrEnum>; +pub type RewriteQState = RewriteQ; +impl RewriteQToExpandAttr for RewriteQState { + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { + if self.args.args.base.derive.present { + expand_attrs.append(tokens::derive_states(&self.args.args.base.derive.items)); } - if self.reflect.present { - if self.derive.present { - expanded_attrs.attrs.push(tokens::derive_reflect()); + if self.args.args.base.reflect.present { + if self.args.args.base.derive.present { + expand_attrs.attrs.push(tokens::derive_reflect()); } - expanded_attrs.append(tokens::reflect(&self.reflect.items)) + expand_attrs.append(tokens::reflect(&self.args.args.base.reflect.items)) } - if self.register { - expanded_attrs + if self.args.args.base.register { + expand_attrs .attrs - .push(tokens::auto_register_type(plugin.clone(), self.into())); + .push(tokens::auto_register_type(self.into())); } - if self.init { - expanded_attrs + if self.args.args.base.init { + expand_attrs .attrs - .push(tokens::auto_init_states(plugin.clone(), self.into())); + .push(tokens::auto_init_states(self.into())); } - expanded_attrs } } -pub type IaState = - ItemAttribute, AllowStructOrEnum>; -pub type QState<'a> = Q<'a, IaState>; -impl ToTokens for QState<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) {} -} +impl_from_default!(StatesArgs => (RegisterTypeArgs, InitStateArgs)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 0b20db36..5bfd3012 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -32,19 +32,22 @@ impl<'a> From<&'a SystemArgs> for AddSystemArgs { } } -impl RewriteAttribute for SystemArgs { - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs { - let mut expanded_attrs = ExpandAttrs::default(); - expanded_attrs +pub type IaSystem = + ItemAttribute, AllowFn>; +pub type RewriteQSystem = RewriteQ; + +impl RewriteQToExpandAttr for RewriteQSystem { + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { + expand_attrs .attrs - .push(tokens::auto_add_systems(plugin.clone(), self.into())); - expanded_attrs + .push(tokens::auto_add_systems(self.into())); } } -pub type IaSystem = - ItemAttribute, AllowFn>; -pub type QSystem<'a> = Q<'a, IaSystem>; -impl ToTokens for QSystem<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) {} +impl From for AddSystemArgs { + fn from(value: SystemArgs) -> Self { + Self { + schedule_config: value.schedule_config, + } + } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 67f8bb1f..bf15b671 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -170,3 +170,30 @@ where CBase::macro_path(context) } } + +pub struct ConvertComposed(T); + +impl ConvertComposed> { + pub fn new(value: impl Into>) -> Self { + Self(value.into()) + } +} + +impl From> + for ConvertComposed> +where + CBaseTo: From, +{ + fn from(value: Composed) -> Self { + Self(Composed { + base: value.base.into(), + plugin: value.plugin, + generics: value.generics, + }) + } +} +impl From>> for Composed { + fn from(value: ConvertComposed>) -> Self { + value.0 + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context.rs index 233eeda8..0aade644 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/context.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/context.rs @@ -1,6 +1,6 @@ use crate::macro_api::macro_paths::MacroPaths; -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, PartialEq, Hash)] pub struct Context { pub macros: MacroPaths, } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs index c3227823..c664b6e6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs @@ -2,33 +2,41 @@ use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::parse2; -pub enum InputItem { +#[derive(Debug, Clone)] +pub(crate) enum InputItem { Tokens(TokenStream), - Ast(Box), + Item(Box), +} + +impl PartialEq for InputItem { + fn eq(&self, other: &Self) -> bool { + let self_tokens = self.to_token_stream(); + let other_tokens = other.to_token_stream(); + self_tokens.to_string() == other_tokens.to_string() + } } impl InputItem { - pub fn new(item_ts: TokenStream) -> Self { + pub fn from_mut_ref(item_ts: TokenStream) -> Self { Self::Tokens(item_ts) } fn _upgrade(&mut self) -> syn::Result<()> { - if let Self::Tokens(ts) = &self { - let parsed: syn::Item = parse2(ts.clone())?; - *self = Self::Ast(Box::new(parsed)); + if let Self::Tokens(tokens) = self { + *self = Self::Item(parse2(tokens.clone())?); } Ok(()) } pub fn ensure_ast(&mut self) -> syn::Result<&syn::Item> { self._upgrade()?; Ok(match &*self { - Self::Ast(ast) => ast.as_ref(), + Self::Item(item) => item.as_ref(), _ => unreachable!(), }) } pub fn ensure_ast_mut(&mut self) -> syn::Result<&mut syn::Item> { self._upgrade()?; Ok(match &mut *self { - Self::Ast(ast) => ast.as_mut(), + Self::Item(item) => item.as_mut(), _ => unreachable!(), }) } @@ -69,7 +77,7 @@ impl ToTokens for InputItem { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.extend(match self { InputItem::Tokens(ts) => ts.clone(), - InputItem::Ast(ast) => quote! { #ast }, + InputItem::Item(item) => quote! { #item }, }) } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs index 491371d2..fe2b0df1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs @@ -2,7 +2,7 @@ use crate::macro_api::attributes::prelude::*; use crate::macro_api::context::Context; use syn::parse_quote; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Hash)] pub struct MacroPaths { /// resolved absolute path to `auto_add_system` pub emit_add_system_macro: syn::Path, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs index 8662800a..1338748d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs @@ -1,4 +1,6 @@ use crate::macro_api::mixins::HasKeys; +use crate::macro_api::prelude::{WithZeroOrManyGenerics, WithZeroOrOneGenerics}; +use crate::util::macros::impl_from_default; use darling::FromMeta; use darling::ast::NestedMeta; use proc_macro2::TokenStream; @@ -47,3 +49,5 @@ impl Parse for WithNoGenerics { Ok(Self::default()) } } + +impl_from_default!(WithNoGenerics => (WithZeroOrOneGenerics, WithZeroOrManyGenerics)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index 99160fc5..353c46ba 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -1,6 +1,8 @@ use crate::macro_api::mixins::HasKeys; use crate::macro_api::mixins::generics::HasGenerics; +use crate::macro_api::prelude::WithZeroOrManyGenerics; use crate::syntax::ast::type_list::TypeList; +use crate::util::macros::impl_from_default; use darling::FromMeta; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; @@ -37,6 +39,8 @@ impl ToTokens for WithZeroOrOneGenerics { } } +impl_from_default!(WithZeroOrOneGenerics => (WithZeroOrManyGenerics)); + #[cfg(test)] mod tests { use super::*; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs index 2cc746d5..77c227ba 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/mod.rs @@ -29,7 +29,7 @@ where } pub mod prelude { - use super::*; + pub use super::*; pub use generics::prelude::*; pub use nothing::*; pub use with_plugin::*; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 3b34e1b4..099af087 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -16,6 +16,7 @@ pub(crate) mod prelude { pub use composed::*; pub use context::*; pub use derives::prelude::*; + pub use macro_paths::*; pub use mixins::prelude::*; pub use q::*; pub use qq::*; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 145bb786..125db5b3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -3,17 +3,15 @@ use proc_macro2::TokenStream; use quote::{ToTokens, format_ident}; /// for codegen attaching to bevy app -pub(crate) struct Q<'a, T> { - pub(crate) args: &'a T, +#[derive(Debug, Clone)] +pub(crate) struct Q { + pub(crate) args: T, // TODO: maybe app params should just be part of another wrapper struct? pub(crate) app_param: syn::Ident, } -impl Q<'_, T> -where - T: ItemAttributeParse, -{ - pub fn from_args(args: &T) -> Q { +impl Q { + pub fn from_args(args: T) -> Q { Q:: { args, app_param: format_ident!("app"), @@ -25,7 +23,7 @@ pub trait ToTokensWithAppParam { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident); } -impl<'a, T> ToTokens for Q<'a, T> +impl ToTokens for Q where Self: ToTokensWithAppParam, { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 5d2edea2..3318fa0c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -1,33 +1,20 @@ use crate::codegen::ExpandAttrs; -use crate::macro_api::attributes::prelude::*; -use crate::macro_api::attributes::{ - AllowFn, AllowStructOrEnum, ItemAttribute, ItemAttributeContext, -}; -use crate::macro_api::composed::Composed; -use crate::macro_api::context::Context; -use crate::macro_api::input_item::InputItem; -use crate::macro_api::macro_paths::MacroPathProvider; -use crate::macro_api::mixins::generics::none::WithNoGenerics; -use crate::macro_api::mixins::generics::with_many::WithZeroOrManyGenerics; -use crate::macro_api::mixins::generics::with_single::WithZeroOrOneGenerics; -use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::macro_api::prelude::*; use crate::syntax::extensions::item::ItemAttrsExt; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::ToTokens; use syn::parse_quote; use syn::spanned::Spanned; /// for codegen re-emitting macro args -pub(crate) struct QQ<'a, T> { - pub(crate) args: &'a mut T, +#[derive(Debug, Clone)] +pub(crate) struct QQ { + pub(crate) args: T, } -impl<'a, T> QQ<'a, T> -where - T: ItemAttributeInput, -{ - pub(crate) fn from_args(args: &'a mut T) -> QQ<'a, T> { - QQ::<'a, T> { args } +impl QQ { + pub(crate) fn from_args(args: T) -> QQ { + QQ:: { args } } } @@ -35,7 +22,7 @@ pub trait QQToExpandAttr { fn to_expand_attr(&self, expand_attrs: &mut ExpandAttrs); } -impl<'a, T> ToTokens for QQ<'a, T> +impl ToTokens for QQ where Self: QQToExpandAttr, { @@ -46,7 +33,7 @@ where } } -impl QQ<'_, T> +impl QQ where T: MacroPathProvider + ItemAttributeInput + ItemAttributeContext, Self: ToTokens, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs index b4824757..417650b4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs @@ -4,15 +4,16 @@ use proc_macro2::TokenStream; use quote::ToTokens; /// for codegen rewriting attrs -pub(crate) struct RewriteQ<'a, T> { - pub(crate) args: &'a mut T, +#[derive(Debug, Clone)] +pub(crate) struct RewriteQ { + pub(crate) args: T, } -impl RewriteQ<'_, T> +impl RewriteQ where T: ItemAttributeParse, { - pub fn from_item_attribute(item_attribute: &mut T) -> RewriteQ { + pub fn from_item_attribute(item_attribute: T) -> RewriteQ { RewriteQ:: { args: item_attribute, } @@ -20,26 +21,39 @@ where } pub trait RewriteQToExpandAttr { - fn to_expand_attr(&self, expand_attrs: &mut ExpandAttrs); + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs); } -impl<'a, T> ToTokens for RewriteQ<'a, T> +impl ToTokens for RewriteQ where Self: RewriteQToExpandAttr, { fn to_tokens(&self, tokens: &mut TokenStream) { let mut expand_attr = ExpandAttrs::default(); - RewriteQToExpandAttr::to_expand_attr(self, &mut expand_attr); + RewriteQToExpandAttr::to_expand_attrs(self, &mut expand_attr); expand_attr.to_tokens(tokens); } } -impl<'a, TFrom, TTo, P, G, R> From, R>>> - for QQ<'a, ItemAttribute, R>> +impl From, R>>> + for QQ, R>> where TTo: From, { - fn from(value: RewriteQ<'a, ItemAttribute, R>>) -> Self { - QQ::<'a, ItemAttribute, R>>::from_args(TTo::from(value.args)) + fn from(value: RewriteQ, R>>) -> Self { + let args = ItemAttribute::>, R>::from(value.args); + let args = ItemAttribute::, R>::from(args); + Self::from_args(args) + } +} + +impl From<&RewriteQ, R>>> + for QQ, R>> +where + TTo: From, + RewriteQ, R>>: Clone, +{ + fn from(value: &RewriteQ, R>>) -> Self { + Self::from(value.clone()) } } From 9d631f6cdcc2568c2b913c9102841d33dcdd7e96 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 19:26:28 -0400 Subject: [PATCH 046/162] refactor: update `From` implementations to support additional generic conversions --- .../src/macro_api/attributes/mod.rs | 16 ++++++++----- .../src/macro_api/composed.rs | 10 ++++---- .../src/macro_api/rewrite_q.rs | 24 ++++++++++++------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 0e99c964..2afc2280 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -6,6 +6,7 @@ use crate::macro_api::mixins::with_plugin::WithPlugin; use crate::macro_api::prelude::ConvertComposed; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; +use crate::util::macros::impl_from_default; use proc_macro2::{Ident, TokenStream}; use quote::format_ident; use std::hash::Hash; @@ -74,7 +75,7 @@ pub trait IdentPathResolver { fn resolve_ident_path(item: &Item) -> Option; } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] pub struct AllowStructOrEnum; impl IdentPathResolver for AllowStructOrEnum { const NOT_ALLOWED_MESSAGE: &'static str = "Only allowed on Struct Or Enum items"; @@ -87,7 +88,7 @@ impl IdentPathResolver for AllowStructOrEnum { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] pub struct AllowFn; impl IdentPathResolver for AllowFn { const NOT_ALLOWED_MESSAGE: &'static str = "Only allowed on Fn items"; @@ -99,7 +100,7 @@ impl IdentPathResolver for AllowFn { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] pub struct AllowAny; impl IdentPathResolver for AllowAny { fn resolve_ident_path(item: &Item) -> Option { @@ -125,6 +126,7 @@ impl IdentPathResolver for AllowAny { }) } } +impl_from_default!(AllowAny => (AllowStructOrEnum, AllowFn)); pub trait PluginCap { fn plugin_path(&self) -> &syn::Path; @@ -299,12 +301,14 @@ where } } -impl From, R>> - for ItemAttribute>, R> +impl From, RFrom>> + for ItemAttribute>, RTo> where TTo: From, + GTo: From, + RTo: From, { - fn from(value: ItemAttribute, R>) -> Self { + fn from(value: ItemAttribute, RFrom>) -> Self { ItemAttribute { args: ConvertComposed::from(value.args), context: value.context, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index bf15b671..142b48cc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -179,16 +179,18 @@ impl ConvertComposed From> - for ConvertComposed> +impl + From> + for ConvertComposed> where CBaseTo: From, + MGenericsTo: From, { - fn from(value: Composed) -> Self { + fn from(value: Composed) -> Self { Self(Composed { base: value.base.into(), plugin: value.plugin, - generics: value.generics, + generics: value.generics.into(), }) } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs index 417650b4..5c1b1817 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs @@ -35,25 +35,31 @@ where } } -impl From, R>>> - for QQ, R>> +impl + From, RFrom>>> + for QQ, RTo>> where TTo: From, + GTo: From, + RTo: From, { - fn from(value: RewriteQ, R>>) -> Self { - let args = ItemAttribute::>, R>::from(value.args); - let args = ItemAttribute::, R>::from(args); + fn from(value: RewriteQ, RFrom>>) -> Self { + let args = ItemAttribute::>, RTo>::from(value.args); + let args = ItemAttribute::, RTo>::from(args); Self::from_args(args) } } -impl From<&RewriteQ, R>>> - for QQ, R>> +impl + From<&RewriteQ, RFrom>>> + for QQ, RTo>> where TTo: From, - RewriteQ, R>>: Clone, + GTo: From, + RTo: From, + RewriteQ, RFrom>>: Clone, { - fn from(value: &RewriteQ, R>>) -> Self { + fn from(value: &RewriteQ, RFrom>>) -> Self { Self::from(value.clone()) } } From 4c892123afd1e97e79d91b37844659bf0e9c53e7 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 19:32:17 -0400 Subject: [PATCH 047/162] refactor: remove with_target_path --- .../src/codegen/mod.rs | 1 - .../src/codegen/with_target_path.rs | 104 ------------------ .../src/syntax/validated/concrete_path.rs | 8 -- 3 files changed, 113 deletions(-) delete mode 100644 crates/bevy_auto_plugin_shared/src/codegen/with_target_path.rs diff --git a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs index c11edc45..48aa619a 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs @@ -1,5 +1,4 @@ pub mod tokens; -pub mod with_target_path; use proc_macro2::TokenStream as MacroStream; use quote::{ToTokens, quote}; diff --git a/crates/bevy_auto_plugin_shared/src/codegen/with_target_path.rs b/crates/bevy_auto_plugin_shared/src/codegen/with_target_path.rs deleted file mode 100644 index cf05f4e1..00000000 --- a/crates/bevy_auto_plugin_shared/src/codegen/with_target_path.rs +++ /dev/null @@ -1,104 +0,0 @@ -use crate::macro_api::prelude::*; -use crate::syntax::validated::concrete_path::{ - ConcreteTargetPath, ConcreteTargetPathWithGenericsCollection, -}; -use crate::syntax::validated::path_without_generics::{ - PathWithoutGenerics, TryFromPathWithoutGenericsError, -}; -use proc_macro2::TokenStream; -use syn::Path; - -pub trait ToTokensWithConcreteTargetPath: GenericsArgs { - fn to_tokens_with_concrete_target_path( - &self, - tokens: &mut TokenStream, - target: &ConcreteTargetPath, - ); - fn to_token_stream_with_concrete_target_path( - &self, - target: &ConcreteTargetPath, - ) -> TokenStream { - let mut tokens = TokenStream::new(); - self.to_tokens_with_concrete_target_path(&mut tokens, target); - tokens - } - fn required_use_statements(&self) -> Vec { - vec![] - } -} - -#[derive(Debug, Clone)] -pub struct ToTokensIterItem { - pub required_uses: Vec, - pub main_tokens: TokenStream, -} - -impl ToTokensIterItem { - #[cfg(test)] - pub fn into_main_tokens(self) -> TokenStream { - self.main_tokens - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct WithTargetPath { - target: PathWithoutGenerics, - pub inner: T, -} - -impl WithTargetPath { - pub fn target(&self) -> &PathWithoutGenerics { - &self.target - } - pub fn inner(&self) -> &T { - &self.inner - } -} - -impl WithTargetPath { - pub fn concrete_target_paths(&self) -> ConcreteTargetPathWithGenericsCollection { - self.clone().into() - } -} - -impl WithTargetPath { - /// used to reconstruct `|app| { #(#required_uses)* #main_tokens }` - pub fn to_tokens_iter_items(&self) -> impl Iterator { - self.concrete_target_paths() - .into_iter() - .map(|concrete_target_path| ToTokensIterItem { - required_uses: self.inner.required_use_statements(), - main_tokens: self - .inner - .to_token_stream_with_concrete_target_path(&concrete_target_path), - }) - } - #[cfg(test)] - /// used in tests checking the output of `ToTokensIterItem::main_tokens` - pub fn to_tokens_iter(&self) -> impl Iterator { - self.to_tokens_iter_items() - .map(ToTokensIterItem::into_main_tokens) - } -} - -impl From<(PathWithoutGenerics, T)> for WithTargetPath { - fn from(value: (PathWithoutGenerics, T)) -> Self { - let (target, inner) = value; - Self { target, inner } - } -} - -impl From> for (PathWithoutGenerics, T) { - fn from(value: WithTargetPath) -> (PathWithoutGenerics, T) { - (value.target, value.inner) - } -} - -impl TryFrom<(Path, T)> for WithTargetPath { - type Error = TryFromPathWithoutGenericsError; - fn try_from(value: (Path, T)) -> Result { - let (path, inner) = value; - let target = PathWithoutGenerics::try_from(path)?; - Ok(Self { target, inner }) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs index d2b5ff15..7c396eb6 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs @@ -1,4 +1,3 @@ -use crate::codegen::with_target_path::WithTargetPath; use crate::macro_api::prelude::*; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::generics::{Generics, GenericsCollection}; @@ -84,13 +83,6 @@ impl TryFrom<(Path, T)> for ConcreteTargetPathWithGenericsColle } } -impl From> for ConcreteTargetPathWithGenericsCollection { - fn from(value: WithTargetPath) -> Self { - let (target, args) = value.into(); - Self::from((target, args)) - } -} - pub fn generics_from_path(path: &Path) -> syn::Result { let mut generics = TypeList::empty(); for segment in &path.segments { From 214ec9361745529c1e9e3a3e69526f31b2848807 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 19:55:29 -0400 Subject: [PATCH 048/162] refactor: extract `output` and fix tests --- .../actions/auto_configure_system_set.rs | 200 ++++++++++-------- 1 file changed, 107 insertions(+), 93 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index a214b01e..1280a477 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -4,11 +4,12 @@ use crate::syntax::analysis::item::resolve_ident_from_struct_or_enum; use crate::syntax::ast::flag::Flag; use crate::syntax::parse::item::ts_item_has_attr; use crate::syntax::parse::scrub_helpers::{AttrSite, scrub_helpers_and_ident_with_filter}; +use crate::syntax::validated::concrete_path::ConcreteTargetPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, quote}; use syn::spanned::Spanned; -use syn::{Attribute, Item, parse_quote}; +use syn::{Attribute, Item, Path, parse_quote}; const CONFIG_ATTR_NAME: &str = "auto_configure_system_set_config"; const CHAIN_CONFLICT_ERR: &str = "`chain` and `chain_ignore_deferred` are mutually exclusive"; @@ -98,57 +99,72 @@ pub type IaConfigureSystemSet = ItemAttribute< pub type QConfigureSystemSet = Q; pub type QQConfigureSystemSet = QQ; +fn output( + args: &ConfigureSystemSetArgs, + app_param: &Ident, + concrete_path: &Path, + has_generics: bool, +) -> TokenStream { + let mut tokens = TokenStream::new(); + let schedule = &args.schedule_config.schedule; + let config_tokens = args.schedule_config.config.to_token_stream(); + if let Some(inner) = &args.inner { + // enum + let chained = if args.chain.is_present() { + quote! { .chain() } + } else if args.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let mut entries = vec![]; + for (ident, entry) in inner.entries.iter() { + let chained = if entry.chain.is_present() { + quote! { .chain() } + } else if entry.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let config_tokens = entry.config.to_token_stream(); + entries.push(quote! { + #concrete_path :: #ident #chained #config_tokens + }); + } + if !entries.is_empty() { + tokens.extend(quote! { + #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); + }); + } + } else { + // struct + if has_generics { + // TODO: generics are kind of silly here + // but if someone does use them we'll assume its just a marker type + // that can be initialized via `Default::default()` + tokens.extend(quote! { + #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); + }); + } else { + tokens.extend(quote! { + #app_param.configure_sets(#schedule, #concrete_path #config_tokens); + }); + } + } + tokens +} + impl ToTokensWithAppParam for QConfigureSystemSet { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args; let generics = args.generics(); - let base = &self.args.args.base; - let schedule = &args.base.schedule_config.schedule; - let config_tokens = args.base.schedule_config.config.to_token_stream(); for concrete_path in self.args.concrete_paths() { - if let Some(inner) = &base.inner { - // enum - let chained = if base.chain.is_present() { - quote! { .chain() } - } else if base.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let mut entries = vec![]; - for (ident, entry) in inner.entries.iter() { - let chained = if entry.chain.is_present() { - quote! { .chain() } - } else if entry.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let config_tokens = entry.config.to_token_stream(); - entries.push(quote! { - #concrete_path :: #ident #chained #config_tokens - }); - } - if !entries.is_empty() { - tokens.extend(quote! { - #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); - }); - } - } else { - // struct - if generics.is_empty() { - tokens.extend(quote! { - #app_param.configure_sets(#schedule, #concrete_path #config_tokens); - }); - } else { - // TODO: generics are kind of silly here - // but if someone does use them we'll assume its just a marker type - // that can be initialized via `Default::default()` - tokens.extend(quote! { - #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); - }); - } - } + tokens.extend(output( + &args.base, + app_param, + &concrete_path, + !generics.is_empty(), + )); } } } @@ -371,7 +387,6 @@ pub fn args_with_plugin_from_args_input( #[cfg(test)] mod tests { use super::*; - use crate::codegen::with_target_path::WithTargetPath; use internal_test_proc_macro::xtest; use syn::{Path, parse_quote, parse2}; @@ -404,62 +419,68 @@ mod tests { fn test_to_tokens_no_generics() -> syn::Result<()> { let args = parse2::(quote!(schedule = Update))?; let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); + let app_param = parse_quote!(app); + let tokens = output(&args, &app_param, &path, false); assert_eq!( - token_iter.next().expect("token_iter").to_string(), + tokens.to_string(), quote! { - . configure_sets (Update , FooTarget) + #app_param . configure_sets (Update , FooTarget) } .to_string() ); - assert!(token_iter.next().is_none()); Ok(()) } #[xtest] fn test_to_tokens_single() -> syn::Result<()> { - let args = - parse2::(quote!(schedule = Update, generics(u8, bool)))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); + let args = parse2::(quote!(schedule = Update))?; + let app_param = parse_quote!(app); + let tokens = output( + &args, + &app_param, + &parse_quote!(FooTarget::), + true, + ); assert_eq!( - token_iter.next().expect("token_iter").to_string(), + tokens.to_string(), quote! { - . configure_sets (Update , FooTarget :: ::default() ) + #app_param . configure_sets (Update , FooTarget :: ::default() ) } .to_string() ); - assert!(token_iter.next().is_none()); Ok(()) } #[xtest] fn test_to_tokens_multiple() -> syn::Result<()> { - let args = parse2::(quote!( - schedule = Update, - generics(u8, bool), - generics(bool, bool) - ))?; - let path: Path = parse_quote!(FooTarget); - let args_with_target = WithTargetPath::try_from((path, args))?; - let mut token_iter = args_with_target.to_tokens_iter(); + let args = parse2::(quote!(schedule = Update))?; + let app_param = parse_quote!(app); + let tokens = output( + &args, + &app_param, + &parse_quote!(FooTarget::), + true, + ); assert_eq!( - token_iter.next().expect("token_iter").to_string(), + tokens.to_string(), quote! { - . configure_sets (Update , FooTarget :: ::default() ) + #app_param . configure_sets (Update , FooTarget :: ::default() ) } .to_string() ); + let tokens = output( + &args, + &app_param, + &parse_quote!(FooTarget::), + true, + ); assert_eq!( - token_iter.next().expect("token_iter").to_string(), + tokens.to_string(), quote! { - . configure_sets (Update , FooTarget :: ::default() ) + #app_param . configure_sets (Update , FooTarget :: ::default() ) } .to_string() ); - assert!(token_iter.next().is_none()); Ok(()) } } @@ -480,17 +501,15 @@ mod tests { } }, )?; - let args_with_target = - WithTargetPath::try_from((PathWithoutGenerics::from(ident), args)).unwrap(); // infallible - let mut token_iter = args_with_target.to_tokens_iter(); + let app_param = parse_quote!(app); + let output = output(&args, &app_param, &(ident.into()), false); assert_eq!( - token_iter.next().expect("token_iter").to_string(), + output.to_string(), quote! { - . configure_sets (Update , ( Foo::A , Foo::B )) + #app_param . configure_sets (Update , ( Foo::A , Foo::B )) } .to_string() ); - assert!(token_iter.next().is_none()); Ok(()) } @@ -505,17 +524,15 @@ mod tests { } }, )?; - let args_with_target = - WithTargetPath::try_from((PathWithoutGenerics::from(ident), args)).unwrap(); // infallible - let mut token_iter = args_with_target.to_tokens_iter(); + let app_param = parse_quote!(app); + let tokens = output(&args, &app_param, &(ident.into()), false); assert_eq!( - token_iter.next().expect("token_iter").to_string(), + tokens.to_string(), quote! { - . configure_sets (Update , ( Foo::A , Foo::B )) + #app_param . configure_sets (Update , ( Foo::A , Foo::B )) } .to_string() ); - assert!(token_iter.next().is_none()); Ok(()) } @@ -532,17 +549,15 @@ mod tests { } }, )?; - let args_with_target = - WithTargetPath::try_from((PathWithoutGenerics::from(ident), args)).unwrap(); // infallible - let mut token_iter = args_with_target.to_tokens_iter(); + let app_param = parse_quote!(app); + let tokens = output(&args, &app_param, &(ident.into()), false); assert_eq!( - token_iter.next().expect("token_iter").to_string(), + tokens.to_string(), quote! { - . configure_sets (Update , ( Foo::A , Foo::B )) + #app_param . configure_sets (Update , ( Foo::A , Foo::B )) } .to_string() ); - assert!(token_iter.next().is_none()); Ok(()) } @@ -592,7 +607,6 @@ mod tests { ] }), group: Some(parse_quote!(A)), - generics: vec![], chain: Flag::from(false), chain_ignore_deferred: Flag::from(false), _strip_helpers: true, From a3787e74523d167ad7d7e538ff132ac1e36c17d0 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 19:56:15 -0400 Subject: [PATCH 049/162] refactor: default context for now --- .../src/__private/expand/attr/auto_bind_plugin.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index b97aa9ea..7d38e1d6 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -34,12 +34,8 @@ pub fn auto_bind_plugin_inner( Ok(item_attribute.input_item.to_token_stream()) } -pub fn auto_bind_plugin_outer( - attr: MacroStream, - input: MacroStream, - context: Context, -) -> MacroStream { +pub fn auto_bind_plugin_outer(attr: MacroStream, input: MacroStream) -> MacroStream { let og_input = input.clone(); - auto_bind_plugin_inner(attr, input, context) + auto_bind_plugin_inner(attr, input, Context::default()) .unwrap_or_else(|err| compile_error_with!(err, og_input)) } From d7d823299149693f2ac493efd86f71e5aa4fdee3 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 20:07:57 -0400 Subject: [PATCH 050/162] fix: prelude exports --- .../src/macro_api/attributes/mod.rs | 7 +------ .../src/macro_api/mixins/generics/mod.rs | 1 + crates/bevy_auto_plugin_shared/src/macro_api/mod.rs | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 2afc2280..3e172dd7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -1,9 +1,4 @@ -use crate::macro_api::composed::Composed; -use crate::macro_api::context::Context; -use crate::macro_api::input_item::InputItem; -use crate::macro_api::mixins::generics::HasGenerics; -use crate::macro_api::mixins::with_plugin::WithPlugin; -use crate::macro_api::prelude::ConvertComposed; +use crate::macro_api::prelude::*; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use crate::util::macros::impl_from_default; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs index 374cb7cd..5328a49f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/mod.rs @@ -9,6 +9,7 @@ pub trait HasGenerics { } pub mod prelude { + pub use super::HasGenerics; use super::*; pub use none::*; pub use with_many::*; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 099af087..5d9a9d3b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -16,6 +16,7 @@ pub(crate) mod prelude { pub use composed::*; pub use context::*; pub use derives::prelude::*; + pub use input_item::*; pub use macro_paths::*; pub use mixins::prelude::*; pub use q::*; From dc00624f6d366c335bc9f554c17a9cd8c6211fc5 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 20:08:06 -0400 Subject: [PATCH 051/162] refactor: remove unused `test_params` module in test utilities --- .../src/test_util/mod.rs | 1 - .../src/test_util/test_params.rs | 168 ------------------ 2 files changed, 169 deletions(-) delete mode 100644 crates/bevy_auto_plugin_shared/src/test_util/test_params.rs diff --git a/crates/bevy_auto_plugin_shared/src/test_util/mod.rs b/crates/bevy_auto_plugin_shared/src/test_util/mod.rs index a00d214c..ce063de0 100644 --- a/crates/bevy_auto_plugin_shared/src/test_util/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/test_util/mod.rs @@ -1,6 +1,5 @@ pub(crate) mod combo; pub(crate) mod macros; -pub(crate) mod test_params; pub(crate) fn assert_tokens_match( plugin: impl std::fmt::Debug, diff --git a/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs b/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs deleted file mode 100644 index 1f38ffa9..00000000 --- a/crates/bevy_auto_plugin_shared/src/test_util/test_params.rs +++ /dev/null @@ -1,168 +0,0 @@ -use crate::__private::attribute::RewriteAttribute; -use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::prelude::*; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use anyhow::anyhow; -use darling::ast::NestedMeta; -use darling::{FromMeta, ToTokens}; -use proc_macro2::TokenStream; -use syn::__private::quote::quote; -use syn::parse::Parser; -use syn::{Attribute, Meta}; - -pub(crate) enum Side { - Left, - #[allow(dead_code)] - Right, -} - -pub(crate) fn _inject_derive( - derives: &mut Vec, - additional_derive_items: &[NonEmptyPath], - side: Side, -) { - if additional_derive_items.is_empty() { - return; - } - // hacky but works - if let Some(index) = derives - .iter() - .position(|ts| ts.to_string().contains("derive")) - { - let existing_ts = derives.remove(index); - let mut attrs = Attribute::parse_outer - .parse2(existing_ts) - .expect("existing derive not in expected format") - .into_iter(); - let derive_attr = attrs.next().expect("empty - impossible?"); - assert!( - attrs.next().is_none(), - "expected exactly 1 derive per entry" - ); - let list = match &derive_attr.meta { - Meta::List(list) => list, - _ => panic!("expected list attribute #[derive(...)]"), - }; - let path = &list.path; - let inner = &list.tokens; - - // Check if there are existing items for comma placement - let combined = if inner.is_empty() { - quote!(#[#path( #(#additional_derive_items),* )]) - } else { - match side { - Side::Left => quote!(#[#path( #(#additional_derive_items),*, #inner )]), - Side::Right => quote!(#[#path( #inner, #(#additional_derive_items),* )]), - } - }; - derives.insert(index, combined); - } else { - derives.insert(0, tokens::derive_from(additional_derive_items)); - } -} - -#[derive(Debug, Clone)] -pub(crate) struct TestParams { - pub args: Composed, - pub expected_derives: ExpandAttrs, - pub expected_reflect: ExpandAttrs, - pub expected_extras: ExpandAttrs, -} - -impl TestParams -where - for<'a> RegisterTypeArgs: From<&'a T>, - T: FromMeta + Clone + RewriteAttribute, - G: Mixin + Clone, -{ - pub(crate) fn new(args: Composed) -> Self { - Self { - args, - expected_derives: ExpandAttrs::default(), - expected_reflect: ExpandAttrs::default(), - expected_extras: ExpandAttrs::default(), - } - } - #[allow(dead_code)] - pub(crate) fn from_list(nested_metas: &[NestedMeta]) -> syn::Result { - let args = Composed::::from_list(nested_metas)?; - Ok(Self::new(args)) - } - #[allow(dead_code)] - pub(crate) fn from_nested_meta(nested_meta: NestedMeta) -> syn::Result { - let args = Composed::::from_nested_meta(&nested_meta)?; - Ok(Self::new(args)) - } - - pub(crate) fn from_args(args: TokenStream) -> syn::Result { - let items = NestedMeta::parse_meta_list(args)?; - Self::from_list(&items) - } - - #[allow(dead_code)] - pub(crate) fn from_attribute(attr: Attribute) -> syn::Result { - let list = match &attr.meta { - Meta::List(l) => l, - _ => panic!("expected list"), - }; - let nested = NestedMeta::parse_meta_list(list.tokens.clone())?; - Self::from_list(&nested) - } - - /// calling order matters - pub(crate) fn with_derive(mut self, extras: Vec) -> Self { - self.expected_derives - .attrs - .push(tokens::derive_from(&extras)); - self - } - - /// calling order matters - pub(crate) fn with_reflect(mut self, extras: Vec, derive: bool) -> Self { - if derive { - self.expected_derives - .attrs - .push(tokens::derive_from(&[tokens::derive_reflect_path()])); - } - if !extras.is_empty() { - self.expected_reflect - .append(tokens::reflect(extras.iter().map(NonEmptyPath::last_ident))); - } - self - } - - /// calling order matters - pub(crate) fn with_register(mut self) -> Self { - let plugin_path = NonEmptyPath::new(self.args.plugin().clone()).expect("bad plugin path"); - self.expected_extras.attrs.insert( - 0, - tokens::auto_register_type(plugin_path, (&self.args.base).into()), - ); - self - } - - fn build_into(self) -> ExpandAttrs { - ExpandAttrs::default() - .with(self.expected_derives) - .with(self.expected_reflect) - .with(self.expected_extras) - } - - pub(crate) fn build_clone(&self) -> ExpandAttrs { - self.clone().build_into() - } - - pub(crate) fn test(&self) -> anyhow::Result<()> { - let got = self - .args - .inner - .expand_attrs(&self.args.plugin()) - .to_token_stream() - .to_string(); - let expected = self.build_clone().to_token_stream().to_string(); - if got != expected { - return Err(anyhow!("\nexpected: {expected:#?}\n got: {got:#?}")); - } - Ok(()) - } -} From 5bf1539b9a9c0546153bb8d37308ab81b9ad946f Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 20:12:35 -0400 Subject: [PATCH 052/162] feat: add potential util for writing back into token stream when dropped --- .../src/util/after_drop.rs | 49 +++++++++++++++++++ .../bevy_auto_plugin_shared/src/util/mod.rs | 1 + 2 files changed, 50 insertions(+) create mode 100644 crates/bevy_auto_plugin_shared/src/util/after_drop.rs diff --git a/crates/bevy_auto_plugin_shared/src/util/after_drop.rs b/crates/bevy_auto_plugin_shared/src/util/after_drop.rs new file mode 100644 index 00000000..d946da56 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/util/after_drop.rs @@ -0,0 +1,49 @@ +use std::ops::{Deref, DerefMut}; + +pub struct AfterDrop<'a, T, F: FnOnce(&'a mut T)> { + target: Option<&'a mut T>, + on_drop: Option, +} + +impl<'a, T, F: FnOnce(&'a mut T)> AfterDrop<'a, T, F> { + pub fn new(target: &'a mut T, on_drop: F) -> Self { + Self { + target: Some(target), + on_drop: Some(on_drop), + } + } +} + +impl<'a, T, F: FnOnce(&'a mut T)> Deref for AfterDrop<'a, T, F> { + type Target = T; + fn deref(&self) -> &T { + self.target.as_deref().unwrap() + } +} +impl<'a, T, F: FnOnce(&'a mut T)> DerefMut for AfterDrop<'a, T, F> { + fn deref_mut(&mut self) -> &mut T { + self.target.as_deref_mut().unwrap() + } +} + +impl<'a, T, F: FnOnce(&'a mut T)> Drop for AfterDrop<'a, T, F> { + fn drop(&mut self) { + if let (Some(t), Some(f)) = (self.target.take(), self.on_drop.take()) { + f(t); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use internal_test_proc_macro::xtest; + #[xtest] + fn test_after_drop() { + let mut x = 0; + let mut y = AfterDrop::new(&mut x, |x| *x = 1); + *y = 2; + drop(y); + assert_eq!(x, 1); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/util/mod.rs b/crates/bevy_auto_plugin_shared/src/util/mod.rs index eda363d6..5e2d3de2 100644 --- a/crates/bevy_auto_plugin_shared/src/util/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/util/mod.rs @@ -1 +1,2 @@ +mod after_drop; pub mod macros; From fa00757efbb45d605439dc65817d20b45314d824 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 20:16:05 -0400 Subject: [PATCH 053/162] refactor: remove unused imports and traits across macro API and related modules --- crates/bevy_auto_plugin_shared/src/__private/attribute.rs | 1 - .../src/__private/expand/attr/auto_bind_plugin.rs | 2 +- .../macro_api/attributes/actions/auto_configure_system_set.rs | 1 - .../bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs | 2 +- .../src/macro_api/attributes/rewrites/auto_component.rs | 4 +--- .../src/macro_api/attributes/rewrites/auto_message.rs | 4 +--- .../src/macro_api/attributes/rewrites/auto_observer.rs | 4 ---- .../src/macro_api/attributes/rewrites/auto_resource.rs | 4 +--- .../src/macro_api/attributes/rewrites/auto_states.rs | 4 +--- .../src/macro_api/attributes/rewrites/auto_system.rs | 4 ---- crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs | 4 ++-- crates/bevy_auto_plugin_shared/src/macro_api/q.rs | 1 - 12 files changed, 8 insertions(+), 27 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/attribute.rs b/crates/bevy_auto_plugin_shared/src/__private/attribute.rs index 9b8f9b4c..7adccde3 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/attribute.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/attribute.rs @@ -1,6 +1,5 @@ use crate::codegen::ExpandAttrs; use crate::syntax::validated::non_empty_path::NonEmptyPath; -use proc_macro2::TokenStream as MacroStream; pub trait RewriteAttribute { fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs; diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index 7d38e1d6..bbc5d213 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -1,7 +1,7 @@ use crate::__private::expand::attr; use crate::macro_api::prelude::*; use crate::syntax::extensions::item::ItemAttrsExt; -use crate::util::macros::{compile_error_with, ok_or_emit_with}; +use crate::util::macros::compile_error_with; use proc_macro2::TokenStream as MacroStream; use quote::ToTokens; use syn::spanned::Spanned; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 1280a477..0a5ad3ad 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -4,7 +4,6 @@ use crate::syntax::analysis::item::resolve_ident_from_struct_or_enum; use crate::syntax::ast::flag::Flag; use crate::syntax::parse::item::ts_item_has_attr; use crate::syntax::parse::scrub_helpers::{AttrSite, scrub_helpers_and_ident_with_filter}; -use crate::syntax::validated::concrete_path::ConcreteTargetPath; use darling::FromMeta; use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, quote}; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 3e172dd7..887b0cf3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -21,7 +21,7 @@ pub mod prelude { pub use super::AllowStructOrEnum; pub use super::AttributeIdent; pub use super::GenericsCap; - pub use super::IdentPathResolver; + pub use super::ItemAttribute; pub use super::ItemAttributeArgs; pub use super::ItemAttributeContext; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index e32d9552..4c695ded 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -1,4 +1,3 @@ -use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; @@ -6,8 +5,7 @@ use crate::syntax::ast::flag_or_lit::FlagOrLit; use crate::syntax::validated::non_empty_path::NonEmptyPath; use crate::util::macros::impl_from_default; use darling::FromMeta; -use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; -use quote::{ToTokens, quote}; +use proc_macro2::Ident; use syn::parse_quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index b55c7b98..1bd087a4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -1,12 +1,10 @@ -use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use crate::util::macros::impl_from_default; use darling::FromMeta; -use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; -use quote::{ToTokens, quote}; +use proc_macro2::Ident; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index d3379da0..ce2b41e3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -1,11 +1,7 @@ -use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; -use crate::syntax::validated::non_empty_path::NonEmptyPath; use crate::util::macros::impl_from_default; use darling::FromMeta; -use proc_macro2::{TokenStream as MacroStream, TokenStream}; -use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index cad2756d..a23285d5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -1,12 +1,10 @@ -use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use crate::util::macros::impl_from_default; use darling::FromMeta; -use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; -use quote::{ToTokens, quote}; +use proc_macro2::Ident; use syn::parse_quote; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 76e50632..2a32af50 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -1,12 +1,10 @@ -use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::syntax::ast::flag_or_list::FlagOrList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use crate::util::macros::impl_from_default; use darling::FromMeta; -use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; -use quote::{ToTokens, quote}; +use proc_macro2::Ident; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 5bfd3012..87be9f5b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -1,11 +1,7 @@ -use crate::__private::attribute::RewriteAttribute; use crate::codegen::{ExpandAttrs, tokens}; use crate::macro_api::prelude::*; use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; -use crate::syntax::validated::non_empty_path::NonEmptyPath; use darling::FromMeta; -use proc_macro2::{TokenStream as MacroStream, TokenStream}; -use quote::{ToTokens, quote}; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs index 794fb44e..0501984f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs @@ -19,7 +19,7 @@ pub struct VariantData { } pub mod prelude { - pub use super::FieldData; - pub use super::VariantData; + + pub use super::auto_plugin::*; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 125db5b3..8fd7b237 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -1,4 +1,3 @@ -use crate::macro_api::attributes::ItemAttributeParse; use proc_macro2::TokenStream; use quote::{ToTokens, format_ident}; From be55ee96e40af71d0eade6f44d7496f67a3f47f6 Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 20:16:33 -0400 Subject: [PATCH 054/162] refactor: remove unused `attribute` module and related trait --- crates/bevy_auto_plugin_shared/src/__private/attribute.rs | 6 ------ crates/bevy_auto_plugin_shared/src/__private/mod.rs | 1 - 2 files changed, 7 deletions(-) delete mode 100644 crates/bevy_auto_plugin_shared/src/__private/attribute.rs diff --git a/crates/bevy_auto_plugin_shared/src/__private/attribute.rs b/crates/bevy_auto_plugin_shared/src/__private/attribute.rs deleted file mode 100644 index 7adccde3..00000000 --- a/crates/bevy_auto_plugin_shared/src/__private/attribute.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::codegen::ExpandAttrs; -use crate::syntax::validated::non_empty_path::NonEmptyPath; - -pub trait RewriteAttribute { - fn expand_attrs(&self, plugin: &NonEmptyPath) -> ExpandAttrs; -} diff --git a/crates/bevy_auto_plugin_shared/src/__private/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/mod.rs index 51af8759..6dbb24cc 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/mod.rs @@ -1,4 +1,3 @@ -pub mod attribute; pub mod auto_plugin_registry; pub mod expand; From 567447541563b0f2ca36ba78d07ddd3673ae7aab Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 20:21:34 -0400 Subject: [PATCH 055/162] refactor: reimplement proc_attribute_rewrite_outer --- .../src/__private/expand/attr/mod.rs | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 7a0b0510..c70d1fd3 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -52,8 +52,21 @@ where } } -fn proc_attribute_rewrite_outer(attr: MacroStream, input: MacroStream) -> MacroStream { - todo!() +fn proc_attribute_rewrite_outer(attr: MacroStream, input: MacroStream) -> MacroStream +where + RewriteQ: ToTokens, + T: ItemAttributeArgs + ItemAttributeParse + ItemAttributeInput + ItemAttributeContext, +{ + let args = ok_or_emit_with!( + T::from_attr_input_with_context(attr, input.clone(), Context::default()), + input + ); + let input = args.input_item().clone(); + let after_item_tokens = RewriteQ::from_item_attribute(args).to_token_stream(); + quote! { + #input + #after_item_tokens + } } pub fn inject_plugin_arg_for_attributes(attrs: &mut Vec, plugin: &syn::Path) { @@ -172,11 +185,11 @@ gen_auto_attribute_outers! { } gen_auto_outers! { - auto_component => ComponentArgs, - auto_resource => ResourceArgs, - auto_system => SystemArgs, - auto_event => EventArgs, - auto_message => MessageArgs, - auto_observer => ObserverArgs, - auto_states => StatesArgs, + auto_component => IaComponent, + auto_resource => IaResource, + auto_system => IaSystem, + auto_event => IaEvent, + auto_message => IaMessage, + auto_observer => IaObserver, + auto_states => IaState, } From c8655ab57ab46784c753e018d9b97ac129a5cbea Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 24 Oct 2025 21:20:34 -0400 Subject: [PATCH 056/162] refactor: update `ItemAttribute` traits and function signatures --- .../src/__private/expand/attr/mod.rs | 37 ++++++++----- .../src/macro_api/attributes/mod.rs | 54 ++++++++++++++++--- 2 files changed, 73 insertions(+), 18 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index c70d1fd3..4e7e9383 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -4,22 +4,27 @@ use crate::util::macros::ok_or_emit_with; use proc_macro2::{Ident, TokenStream as MacroStream}; use quote::{ToTokens, format_ident, quote}; use std::hash::Hash; +use syn::token::Typeof; pub mod auto_bind_plugin; pub mod auto_plugin; -fn body( - body: impl Fn(MacroStream) -> MacroStream, -) -> impl Fn(&Ident, Q, R>>) -> syn::Result +fn body(body: impl Fn(MacroStream) -> MacroStream) -> impl Fn(Q) -> syn::Result where - T: ItemAttributeArgs + Hash, - G: Hash + Clone, - Q, R>>: ToTokens, + T: ItemAttributeArgs + + ItemAttributeParse + + ItemAttributeInput + + ItemAttributeTarget + + ItemAttributeContext + + ItemAttributeUniqueIdent + + ItemAttributePlugin, + Q: ToTokens, { - move |ident, params| { + move |params| -> syn::Result { + let ident = params.args.target().to_token_stream(); let app_param = ¶ms.app_param; - let unique_ident = params.args.get_unique_ident(ident); - let plugin = params.args.plugin_path().clone(); + let unique_ident = params.args.get_unique_ident(); + let plugin = params.args.plugin().clone(); let body = body(params.to_token_stream()); let expr: syn::ExprClosure = syn::parse_quote!(|#app_param| { #body @@ -37,15 +42,23 @@ where fn proc_attribute_outer(attr: MacroStream, input: MacroStream) -> MacroStream where - T: ItemAttributeArgs + ItemAttributeParse + ItemAttributeInput + ItemAttributeContext, + T: ItemAttributeArgs + + ItemAttributeParse + + ItemAttributeInput + + ItemAttributeTarget + + ItemAttributeUniqueIdent + + ItemAttributeContext + + ItemAttributePlugin, Q: ToTokens, { let args = ok_or_emit_with!( T::from_attr_input_with_context(attr, input.clone(), Context::default()), input ); - let input = args.input_item().clone(); - let after_item_tokens = Q::from_args(args).to_token_stream(); + let body_fn = body(|body| quote! { #body }); + let q = Q::from_args(args); + let input = q.args.input_item().to_token_stream(); + let after_item_tokens = ok_or_emit_with!(body_fn(q), input); quote! { #input #after_item_tokens diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 887b0cf3..6d911982 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -8,7 +8,7 @@ use std::hash::Hash; use std::marker::PhantomData; use syn::parse::Parse; use syn::spanned::Spanned; -use syn::{Item, parse_quote, parse2}; +use syn::{Item, Path, parse_quote, parse2}; mod actions; mod auto_plugin; @@ -21,12 +21,14 @@ pub mod prelude { pub use super::AllowStructOrEnum; pub use super::AttributeIdent; pub use super::GenericsCap; - pub use super::ItemAttribute; pub use super::ItemAttributeArgs; pub use super::ItemAttributeContext; pub use super::ItemAttributeInput; pub use super::ItemAttributeParse; + pub use super::ItemAttributePlugin; + pub use super::ItemAttributeTarget; + pub use super::ItemAttributeUniqueIdent; pub use super::PluginCap; pub use super::auto_plugin::{ AutoPluginFnArgs, AutoPluginStructOrEnumArgs, resolve_app_param_name, @@ -50,7 +52,7 @@ pub trait ItemAttributeArgs: AttributeIdent + Hash + Clone { } } -impl AttributeIdent for ItemAttribute, R> +impl AttributeIdent for ItemAttribute where T: AttributeIdent + Hash + Clone, { @@ -141,12 +143,14 @@ pub struct ItemAttribute { pub _resolver: PhantomData, } +// TODO: this impl doesnt make sense for this context but its required for ItemAttributeArgs impl Hash for ItemAttribute where T: Hash, R: Hash, { fn hash(&self, state: &mut H) { + panic!("ItemAttribute should not be hashed"); self.args.hash(state); self.context.hash(state); self.target.hash(state); @@ -157,7 +161,7 @@ where // TODO: where should this live? impl ItemAttribute where - T: ItemAttributeArgs + Hash, + T: Hash, { pub fn _concat_ident_hash(&self, ident: &Ident) -> String { use std::hash::{Hash, Hasher}; @@ -171,9 +175,15 @@ where let hash = self._concat_ident_hash(ident); format_ident!("{prefix}_{hash}") } +} - pub fn get_unique_ident(&self, ident: &Ident) -> Ident { - self._get_unique_ident(T::global_build_prefix(), ident) +pub trait ItemAttributePlugin { + fn plugin(&self) -> &syn::Path; +} + +impl ItemAttributePlugin for ItemAttribute, Resolver> { + fn plugin(&self) -> &Path { + self.args.plugin() } } @@ -187,6 +197,38 @@ impl ItemAttributeContext for ItemAttribute { } } +pub trait ItemAttributeTarget { + fn target(&self) -> &syn::Path; +} + +impl ItemAttributeTarget for ItemAttribute +where + T: AttributeIdent + Hash + Clone, + Resolver: Hash + Clone, +{ + fn target(&self) -> &syn::Path { + &self.target + } +} + +pub trait ItemAttributeUniqueIdent: ItemAttributeTarget + ItemAttributeArgs { + fn get_unique_ident(&self) -> Ident; +} + +impl ItemAttributeUniqueIdent for ItemAttribute +where + ItemAttribute: ItemAttributeArgs, + T: AttributeIdent + Hash + Clone, + Resolver: Hash + Clone, +{ + fn get_unique_ident(&self) -> Ident { + self._get_unique_ident( + ItemAttribute::::global_build_prefix(), + self.target.get_ident().unwrap(), // infallible + ) + } +} + pub trait ItemAttributeInput { fn input_item(&self) -> &InputItem; fn input_item_mut(&mut self) -> &mut InputItem; From 520e779e47ad438fe9403b3827b11b9971b74257 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 01:25:18 -0400 Subject: [PATCH 057/162] fix: bad token generation and recursion --- .../__private/expand/attr/auto_bind_plugin.rs | 4 +- .../src/__private/expand/attr/mod.rs | 9 +--- .../attributes/actions/auto_add_message.rs | 1 + .../attributes/actions/auto_add_observer.rs | 1 + .../attributes/actions/auto_add_plugin.rs | 1 + .../attributes/actions/auto_add_system.rs | 3 +- .../actions/auto_configure_system_set.rs | 2 + .../attributes/actions/auto_init_resource.rs | 1 + .../attributes/actions/auto_init_state.rs | 1 + .../attributes/actions/auto_init_sub_state.rs | 1 + .../actions/auto_insert_resource.rs | 1 + .../macro_api/attributes/actions/auto_name.rs | 1 + .../actions/auto_register_state_type.rs | 1 + .../attributes/actions/auto_register_type.rs | 1 + .../attributes/actions/auto_run_on_build.rs | 2 +- .../src/macro_api/attributes/mod.rs | 33 ------------- .../src/macro_api/composed.rs | 29 ----------- .../src/macro_api/macro_paths.rs | 40 +++++++++++----- .../macro_api/mixins/generics/with_single.rs | 8 +++- .../src/macro_api/mixins/with_plugin.rs | 3 +- .../src/macro_api/qq.rs | 12 ++++- .../src/macro_api/rewrite_q.rs | 33 +++++++++++-- tests/e2e/auto_component.rs | 48 +++++++++++++++++++ tests/e2e/mod.rs | 1 + 24 files changed, 147 insertions(+), 90 deletions(-) create mode 100644 tests/e2e/auto_component.rs diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index bbc5d213..0377bd57 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -31,7 +31,9 @@ pub fn auto_bind_plugin_inner( unreachable!() }; - Ok(item_attribute.input_item.to_token_stream()) + println!("{}", item.to_token_stream()); + + Ok(item.to_token_stream()) } pub fn auto_bind_plugin_outer(attr: MacroStream, input: MacroStream) -> MacroStream { diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 4e7e9383..622caf18 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,7 +1,7 @@ use crate::__private::auto_plugin_registry::_plugin_entry_block; use crate::macro_api::prelude::*; use crate::util::macros::ok_or_emit_with; -use proc_macro2::{Ident, TokenStream as MacroStream}; +use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; use quote::{ToTokens, format_ident, quote}; use std::hash::Hash; use syn::token::Typeof; @@ -74,12 +74,7 @@ where T::from_attr_input_with_context(attr, input.clone(), Context::default()), input ); - let input = args.input_item().clone(); - let after_item_tokens = RewriteQ::from_item_attribute(args).to_token_stream(); - quote! { - #input - #after_item_tokens - } + RewriteQ::from_item_attribute(args).to_token_stream() } pub fn inject_plugin_arg_for_attributes(attrs: &mut Vec, plugin: &syn::Path) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index d122ae8b..fa740722 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -32,5 +32,6 @@ impl ToTokens for QQAddMessage { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 279f1d59..a6ef03a0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -32,5 +32,6 @@ impl ToTokens for QQAddObserver { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index ac9d84d4..f67db23a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -46,5 +46,6 @@ impl ToTokens for QQAddPlugin { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index f133a094..f78e66d4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -26,7 +26,7 @@ impl ToTokensWithAppParam for QAddSystem { let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { - #app_param.add_systems(#schedule, #concrete_path #config_tokens); + #app_param . add_systems(#schedule, #concrete_path #config_tokens); }); } } @@ -46,5 +46,6 @@ impl ToTokens for QQAddSystem { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 0a5ad3ad..a8f74b5b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -171,6 +171,7 @@ impl ToTokensWithAppParam for QConfigureSystemSet { impl ToTokens for QQConfigureSystemSet { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); + // TODO: scrub input // TODO: cleanup args.extend( self.args @@ -182,6 +183,7 @@ impl ToTokens for QQConfigureSystemSet { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 9ce0dfcd..bc516ac1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -35,5 +35,6 @@ impl ToTokens for QQInitResource { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index ba246d17..0a2fdc7a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -31,5 +31,6 @@ impl ToTokens for QQInitState { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index f01cf606..878e762a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -31,5 +31,6 @@ impl ToTokens for QQInitSubState { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index bc8fb4f5..d7b5dd5b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -39,5 +39,6 @@ impl ToTokens for QQInsertResource { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index 32aa57ef..a2f25f4b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -54,5 +54,6 @@ impl ToTokens for QQName { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 9ac9df02..ea276718 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -36,5 +36,6 @@ impl ToTokens for QQRegisterStateType { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 7ce64c80..cad434cc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -33,5 +33,6 @@ impl ToTokens for QQRegisterType { tokens.extend(quote! { #(#args),* }); + *tokens = self.wrap(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index 8460fca2..17122609 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -12,7 +12,7 @@ impl AttributeIdent for RunOnBuildArgs { } pub type IaRunOnBuild = - ItemAttribute, AllowStructOrEnum>; + ItemAttribute, AllowFn>; pub type QRunOnBuild = Q; pub type QQRunOnBuild = QQ; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 6d911982..6a440513 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -337,36 +337,3 @@ where } } } - -impl From, RFrom>> - for ItemAttribute>, RTo> -where - TTo: From, - GTo: From, - RTo: From, -{ - fn from(value: ItemAttribute, RFrom>) -> Self { - ItemAttribute { - args: ConvertComposed::from(value.args), - context: value.context, - input_item: value.input_item, - target: value.target, - _resolver: PhantomData, - } - } -} - -impl From, R>> for ItemAttribute -where - T: From>, -{ - fn from(value: ItemAttribute, R>) -> Self { - ItemAttribute { - args: T::from(value.args), - context: value.context, - input_item: value.input_item, - target: value.target, - _resolver: PhantomData, - } - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 142b48cc..67f8bb1f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -170,32 +170,3 @@ where CBase::macro_path(context) } } - -pub struct ConvertComposed(T); - -impl ConvertComposed> { - pub fn new(value: impl Into>) -> Self { - Self(value.into()) - } -} - -impl - From> - for ConvertComposed> -where - CBaseTo: From, - MGenericsTo: From, -{ - fn from(value: Composed) -> Self { - Self(Composed { - base: value.base.into(), - plugin: value.plugin, - generics: value.generics.into(), - }) - } -} -impl From>> for Composed { - fn from(value: ConvertComposed>) -> Self { - value.0 - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs index fe2b0df1..c76ece0c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs @@ -26,23 +26,29 @@ pub struct MacroPaths { pub emit_register_type_macro: syn::Path, /// resolved absolute path to `auto_run_on_build` pub emit_run_on_build_macro: syn::Path, + /// resolved absolute path to `auto_name` + pub emit_auto_name_macro: syn::Path, + /// resolved absolute path to `auto_configure_system_set` + pub emit_configure_system_set_macro: syn::Path, } impl Default for MacroPaths { #[rustfmt::skip] fn default() -> Self { Self { - emit_add_system_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_system ), - emit_add_message_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_message ), - emit_add_observer_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_observer ), - emit_add_plugin_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_plugin ), - emit_init_resource_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_resource ), - emit_init_state_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_state ), - emit_init_sub_state_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_sub_state ), - emit_insert_resource_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_insert_resource ), - emit_register_state_type_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_register_state_type ), - emit_register_type_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_register_type ), - emit_run_on_build_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_run_on_build ), + emit_add_system_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_system ), + emit_add_message_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_message ), + emit_add_observer_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_observer ), + emit_add_plugin_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_add_plugin ), + emit_init_resource_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_resource ), + emit_init_state_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_state ), + emit_init_sub_state_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_init_sub_state ), + emit_insert_resource_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_insert_resource ), + emit_register_state_type_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_register_state_type ), + emit_register_type_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_register_type ), + emit_run_on_build_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_run_on_build ), + emit_auto_name_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_name ), + emit_configure_system_set_macro: parse_quote!( ::bevy_auto_plugin::prelude::auto_configure_system_set ), } } } @@ -116,3 +122,15 @@ impl MacroPathProvider for RunOnBuildArgs { &context.macros.emit_run_on_build_macro } } + +impl MacroPathProvider for NameArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_auto_name_macro + } +} + +impl MacroPathProvider for ConfigureSystemSetArgs { + fn macro_path(context: &Context) -> &syn::Path { + &context.macros.emit_configure_system_set_macro + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index 353c46ba..01167fe8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -39,7 +39,13 @@ impl ToTokens for WithZeroOrOneGenerics { } } -impl_from_default!(WithZeroOrOneGenerics => (WithZeroOrManyGenerics)); +impl From for WithZeroOrManyGenerics { + fn from(value: WithZeroOrOneGenerics) -> Self { + Self { + generics: value.generics.as_slice().to_vec(), + } + } +} #[cfg(test)] mod tests { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs index 7dce1352..10d44464 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs @@ -16,7 +16,8 @@ impl WithPlugin { impl ToTokens for WithPlugin { fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(quote! { plugin = #self.plugin }); + let plugin = &self.plugin; + tokens.extend(quote! { plugin = #plugin }); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 3318fa0c..403536c0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -2,7 +2,7 @@ use crate::codegen::ExpandAttrs; use crate::macro_api::prelude::*; use crate::syntax::extensions::item::ItemAttrsExt; use proc_macro2::TokenStream; -use quote::ToTokens; +use quote::{ToTokens, quote}; use syn::parse_quote; use syn::spanned::Spanned; @@ -18,6 +18,16 @@ impl QQ { } } +impl QQ, R>> +where + T: MacroPathProvider, +{ + pub(crate) fn wrap(&self, args: &TokenStream) -> TokenStream { + let macro_path = T::macro_path(self.args.context()); + quote! { #[#macro_path( #args )] } + } +} + pub trait QQToExpandAttr { fn to_expand_attr(&self, expand_attrs: &mut ExpandAttrs); } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs index 5c1b1817..5fc8d6e7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs @@ -2,6 +2,7 @@ use crate::codegen::ExpandAttrs; use crate::macro_api::prelude::*; use proc_macro2::TokenStream; use quote::ToTokens; +use std::marker::PhantomData; /// for codegen rewriting attrs #[derive(Debug, Clone)] @@ -27,11 +28,13 @@ pub trait RewriteQToExpandAttr { impl ToTokens for RewriteQ where Self: RewriteQToExpandAttr, + T: ItemAttributeInput, { fn to_tokens(&self, tokens: &mut TokenStream) { let mut expand_attr = ExpandAttrs::default(); RewriteQToExpandAttr::to_expand_attrs(self, &mut expand_attr); - expand_attr.to_tokens(tokens); + tokens.extend(expand_attr.to_token_stream()); + tokens.extend(self.args.input_item().to_token_stream()); } } @@ -44,8 +47,28 @@ where RTo: From, { fn from(value: RewriteQ, RFrom>>) -> Self { - let args = ItemAttribute::>, RTo>::from(value.args); - let args = ItemAttribute::, RTo>::from(args); + let ItemAttribute { + args, + context, + input_item, + target, + _resolver, + } = value.args; + + let mapped = Composed { + base: args.base.into(), // TTo: From + plugin: args.plugin, // same P + generics: args.generics.into(), // GTo: From + }; + + let args = ItemAttribute::, RTo> { + args: mapped, + context, // RTo: From + input_item, + target, + _resolver: PhantomData, + }; + Self::from_args(args) } } @@ -60,6 +83,8 @@ where RewriteQ, RFrom>>: Clone, { fn from(value: &RewriteQ, RFrom>>) -> Self { - Self::from(value.clone()) + , RFrom>>>>::from( + value.clone(), + ) } } diff --git a/tests/e2e/auto_component.rs b/tests/e2e/auto_component.rs new file mode 100644 index 00000000..07d1f350 --- /dev/null +++ b/tests/e2e/auto_component.rs @@ -0,0 +1,48 @@ +#![allow(dead_code)] + +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; +use bevy_state::app::StatesPlugin; +use internal_test_proc_macro::xtest; +use internal_test_util::{create_minimal_app, type_id_of}; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct Test; + +#[auto_component(plugin = Test, derive, register, reflect, auto_name)] +struct FooComponent; + +fn app() -> App { + let mut app = create_minimal_app(); + app.add_plugins(StatesPlugin); + app.add_plugins(Test); + app +} + +#[xtest] +fn test_auto_register_type_foo_component() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!( + type_registry.contains(type_id_of::()), + "did not auto register type" + ); +} + +#[xtest] +fn test_auto_name_foo_component() { + let mut app = app(); + app.world_mut().spawn(FooComponent); + let name = app + .world_mut() + .query_filtered::<&Name, With>() + .single(app.world()) + .expect("failed to query FooComponent"); + assert_eq!( + name, + &Name::new("FooComponent"), + "did not auto name FooComponent" + ); +} diff --git a/tests/e2e/mod.rs b/tests/e2e/mod.rs index 1c0ba179..47c862e7 100644 --- a/tests/e2e/mod.rs +++ b/tests/e2e/mod.rs @@ -11,6 +11,7 @@ mod auto_add_systems_complex_with_generics; mod auto_add_systems_with_generics; mod auto_add_systems_with_set; mod auto_bind_plugin; +mod auto_component; mod auto_configure_system_set; mod auto_configure_system_set_schedule_config; mod auto_configure_system_set_schedule_config_multiple_groups; From 66ef5e6e9306ddbbc662456d083bd19cc757d5bc Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 02:36:43 -0400 Subject: [PATCH 058/162] fix: several token issues and duplicate input emission --- .../__private/expand/attr/auto_bind_plugin.rs | 2 -- .../src/__private/expand/attr/mod.rs | 8 ++++++-- .../attributes/actions/auto_add_observer.rs | 2 +- .../actions/auto_configure_system_set.rs | 19 +++++++++++++++---- .../src/macro_api/q.rs | 6 ++++++ .../src/syntax/parse/scrub_helpers.rs | 1 + 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index 0377bd57..d803611d 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -31,8 +31,6 @@ pub fn auto_bind_plugin_inner( unreachable!() }; - println!("{}", item.to_token_stream()); - Ok(item.to_token_stream()) } diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 622caf18..a956d29d 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -49,14 +49,18 @@ where + ItemAttributeUniqueIdent + ItemAttributeContext + ItemAttributePlugin, - Q: ToTokens, + Q: ToTokens + ToTokensWithAppParam, { let args = ok_or_emit_with!( T::from_attr_input_with_context(attr, input.clone(), Context::default()), input ); let body_fn = body(|body| quote! { #body }); - let q = Q::from_args(args); + let mut q = Q::from_args(args); + let input = q.args.input_item().to_token_stream(); + // TODO: hack for auto_configure_system_set + // mutates q.args.input_item + ok_or_emit_with!(q.scrub_item(), input); let input = q.args.input_item().to_token_stream(); let after_item_tokens = ok_or_emit_with!(body_fn(q), input); quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index a6ef03a0..8658ac56 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -20,7 +20,7 @@ impl ToTokensWithAppParam for QAddObserver { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { - #app_param.add_observer::<#concrete_path>(); + #app_param.add_observer( #concrete_path ); }); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index a8f74b5b..9e3c780e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -154,12 +154,23 @@ fn output( } impl ToTokensWithAppParam for QConfigureSystemSet { + fn scrub_item(&mut self) -> syn::Result<()> { + let mut input_ts = self.args.input_item.to_token_stream(); + check_strip_helpers(input_ts.clone(), &mut self.args.args.base)?; + args_with_plugin_from_args_input(&mut self.args.args.base, &mut input_ts)?; + self.args.input_item = InputItem::Tokens(input_ts); + Ok(()) + } fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - let args = &self.args.args; - let generics = args.generics(); - for concrete_path in self.args.concrete_paths() { + // TODO: HACK - scrub input + let mut this = self.clone(); + this.scrub_item().unwrap(); + // end hack + + let generics = this.args.args.generics(); + for concrete_path in this.args.concrete_paths() { tokens.extend(output( - &args.base, + &this.args.args.base, app_param, &concrete_path, !generics.is_empty(), diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 8fd7b237..5b6f5bd1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -1,3 +1,4 @@ +use crate::macro_api::prelude::*; use proc_macro2::TokenStream; use quote::{ToTokens, format_ident}; @@ -19,14 +20,19 @@ impl Q { } pub trait ToTokensWithAppParam { + fn scrub_item(&mut self) -> syn::Result<()> { + Ok(()) + } fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident); } impl ToTokens for Q where Self: ToTokensWithAppParam, + T: ItemAttributeInput, { fn to_tokens(&self, tokens: &mut TokenStream) { + // TODO: this mutates item which is already emitted ToTokensWithAppParam::to_tokens(self, tokens, &self.app_param); } } diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index b4aea89f..9ddc54f5 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -1,4 +1,5 @@ #![allow(dead_code)] +use crate::macro_api::prelude::InputItem; use crate::syntax::extensions::item::ItemAttrsExt; use darling::FromMeta; use proc_macro2::TokenStream; From ead7ed24e3789fd8ae80124f75dcc1723e1b5fe8 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 02:49:17 -0400 Subject: [PATCH 059/162] fix: more token issues --- .../__private/expand/attr/auto_bind_plugin.rs | 29 +++++++++++++++++++ .../attributes/actions/auto_init_sub_state.rs | 2 +- .../actions/auto_insert_resource.rs | 7 +++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index d803611d..112a4c99 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -39,3 +39,32 @@ pub fn auto_bind_plugin_outer(attr: MacroStream, input: MacroStream) -> MacroStr auto_bind_plugin_inner(attr, input, Context::default()) .unwrap_or_else(|err| compile_error_with!(err, og_input)) } + +#[cfg(test)] +mod tests { + use super::*; + use internal_test_proc_macro::xtest; + use quote::quote; + #[xtest] + fn test_auto_bind_plugin_inner() { + let attr = quote!(plugin = Test); + let input = quote! { + #[derive(Component, Reflect)] + #[reflect(Component)] + #[auto_register_type] + #[some::path::auto_name] + struct FooComponent; + }; + assert_eq!( + auto_bind_plugin_outer(attr, input).to_string(), + quote! { + # [derive (Component , Reflect)] + # [reflect (Component)] + # [auto_register_type (plugin = Test)] + # [some::path::auto_name (plugin = Test)] + struct FooComponent ; + } + .to_string() + ); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 878e762a..b6b880fd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -20,7 +20,7 @@ impl ToTokensWithAppParam for QInitSubState { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { - #app_param.init_sub_state::<#target>(); + #app_param.add_sub_state::<#target>(); }); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index d7b5dd5b..0e36d11d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -23,10 +23,11 @@ pub type QQInsertResource = QQ; impl ToTokensWithAppParam for QInsertResource { fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + let resource = &self.args.args.base.resource; for concrete_path in self.args.concrete_paths() { - tokens.extend(quote! { |app| { - #app_param.insert_resource(#concrete_path::default()); - }}); + tokens.extend(quote! { + #app_param.insert_resource({ let resource: #concrete_path = #resource; resource}); + }); } } } From 9b81a8c17c79ebe81b63aa5242db1ee2071e0b78 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 02:51:24 -0400 Subject: [PATCH 060/162] fix: add missing semicolons in token assertions and clean up token formatting --- .../actions/auto_configure_system_set.rs | 14 +++++++------- .../src/macro_api/attributes/actions/auto_name.rs | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 9e3c780e..3addbb67 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -436,7 +436,7 @@ mod tests { assert_eq!( tokens.to_string(), quote! { - #app_param . configure_sets (Update , FooTarget) + #app_param . configure_sets (Update , FooTarget); } .to_string() ); @@ -456,7 +456,7 @@ mod tests { assert_eq!( tokens.to_string(), quote! { - #app_param . configure_sets (Update , FooTarget :: ::default() ) + #app_param . configure_sets (Update , FooTarget :: ::default() ); } .to_string() ); @@ -476,7 +476,7 @@ mod tests { assert_eq!( tokens.to_string(), quote! { - #app_param . configure_sets (Update , FooTarget :: ::default() ) + #app_param . configure_sets (Update , FooTarget :: ::default() ); } .to_string() ); @@ -489,7 +489,7 @@ mod tests { assert_eq!( tokens.to_string(), quote! { - #app_param . configure_sets (Update , FooTarget :: ::default() ) + #app_param . configure_sets (Update , FooTarget :: ::default() ); } .to_string() ); @@ -518,7 +518,7 @@ mod tests { assert_eq!( output.to_string(), quote! { - #app_param . configure_sets (Update , ( Foo::A , Foo::B )) + #app_param . configure_sets (Update , ( Foo::A , Foo::B )); } .to_string() ); @@ -541,7 +541,7 @@ mod tests { assert_eq!( tokens.to_string(), quote! { - #app_param . configure_sets (Update , ( Foo::A , Foo::B )) + #app_param . configure_sets (Update , ( Foo::A , Foo::B )); } .to_string() ); @@ -566,7 +566,7 @@ mod tests { assert_eq!( tokens.to_string(), quote! { - #app_param . configure_sets (Update , ( Foo::A , Foo::B )) + #app_param . configure_sets (Update , ( Foo::A , Foo::B )); } .to_string() ); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index a2f25f4b..e17475b4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -31,6 +31,7 @@ impl ToTokensWithAppParam for QName { // TODO: move to util fn quote!(#concrete_path) .to_string() + .replace(" :: < ", "<") .replace(" < ", "<") .replace(" >", ">") .replace(" ,", ",") From 8813c4e8718e7192581d3dc38cf345e4c51f0a8a Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:02:02 -0400 Subject: [PATCH 061/162] fix: bad token output for configure_system_set --- .../src/__private/expand/attr/mod.rs | 15 ++++++++------- .../actions/auto_configure_system_set.rs | 7 +++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index a956d29d..04258c95 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -56,15 +56,16 @@ where input ); let body_fn = body(|body| quote! { #body }); - let mut q = Q::from_args(args); - let input = q.args.input_item().to_token_stream(); + let q = Q::from_args(args); // TODO: hack for auto_configure_system_set - // mutates q.args.input_item - ok_or_emit_with!(q.scrub_item(), input); - let input = q.args.input_item().to_token_stream(); - let after_item_tokens = ok_or_emit_with!(body_fn(q), input); + let scrubbed_input = { + let mut scrubbed = q.clone(); + ok_or_emit_with!(scrubbed.scrub_item(), scrubbed.args.input_item()); + scrubbed.args.input_item().to_token_stream() + }; + let after_item_tokens = ok_or_emit_with!(body_fn(q), scrubbed_input); quote! { - #input + #scrubbed_input #after_item_tokens } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 3addbb67..5013bec9 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -162,10 +162,9 @@ impl ToTokensWithAppParam for QConfigureSystemSet { Ok(()) } fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - // TODO: HACK - scrub input + // TODO: HACK - probably shouldn't be scrubbing here let mut this = self.clone(); this.scrub_item().unwrap(); - // end hack let generics = this.args.args.generics(); for concrete_path in this.args.concrete_paths() { @@ -410,7 +409,7 @@ mod tests { let ident = resolve_ident_from_struct_or_enum(&item).map_err(|err| { syn::Error::new(item.span(), format!("failed to resolve ident: {err}")) })?; - args_from_attr_input(attr, &mut input).and_then(|args| Ok((ident.clone(), args))) + args_from_attr_input(attr, &mut input).map(|args| (ident.clone(), args)) } fn ident_and_args_from_attr_mut_input( @@ -421,7 +420,7 @@ mod tests { let ident = resolve_ident_from_struct_or_enum(&item).map_err(|err| { syn::Error::new(item.span(), format!("failed to resolve ident: {err}")) })?; - args_from_attr_input(attr, input).and_then(|args| Ok((ident.clone(), args))) + args_from_attr_input(attr, input).map(|args| (ident.clone(), args)) } mod test_struct { From d7dc0cc45139147f2afe5b0088a04462cb2fb163 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:05:26 -0400 Subject: [PATCH 062/162] fix: correct `to_tokens` tests to use `assert_eq!` --- .../macro_api/mixins/generics/with_single.rs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index 01167fe8..d9abcc5c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -55,19 +55,23 @@ mod tests { #[xtest] fn test_to_tokens_zero() { - WithZeroOrOneGenerics { generics: None } - .to_token_stream() - .to_string() - == r#""#; + assert_eq!( + WithZeroOrOneGenerics { generics: None } + .to_token_stream() + .to_string(), + quote!().to_string(), + ); } #[xtest] fn test_to_tokens_single() { - WithZeroOrOneGenerics { - generics: Some(TypeList(vec![parse_quote!(bool), parse_quote!(u32)])), - } - .to_token_stream() - .to_string() - == r#"generics(bool, u32)"#; + assert_eq!( + WithZeroOrOneGenerics { + generics: Some(TypeList(vec![parse_quote!(bool), parse_quote!(u32)])), + } + .to_token_stream() + .to_string(), + quote!(generics(bool, u32)).to_string(), + ); } } From 2c98f73b08ae4c01a7c47d001595236caf242242 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:12:35 -0400 Subject: [PATCH 063/162] refactor: remove a lot of dead code and unused imports --- .../src/__private/expand/attr/mod.rs | 4 +--- crates/bevy_auto_plugin_shared/src/codegen/mod.rs | 12 ------------ .../attributes/actions/auto_configure_system_set.rs | 1 - .../src/macro_api/attributes/mod.rs | 7 +------ .../macro_api/attributes/rewrites/auto_component.rs | 4 ++-- .../src/macro_api/attributes/rewrites/auto_event.rs | 2 +- .../macro_api/attributes/rewrites/auto_message.rs | 4 ++-- .../macro_api/attributes/rewrites/auto_observer.rs | 4 ++-- .../macro_api/attributes/rewrites/auto_resource.rs | 2 +- .../src/macro_api/attributes/rewrites/auto_system.rs | 2 +- .../src/macro_api/input_item.rs | 7 ++----- .../src/macro_api/mixins/generics/with_single.rs | 1 - .../src/syntax/parse/scrub_helpers.rs | 1 - crates/bevy_auto_plugin_shared/src/util/macros.rs | 1 - crates/internal_test_util/src/lib.rs | 1 - 15 files changed, 13 insertions(+), 40 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 04258c95..e1546b36 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,10 +1,8 @@ use crate::__private::auto_plugin_registry::_plugin_entry_block; use crate::macro_api::prelude::*; use crate::util::macros::ok_or_emit_with; -use proc_macro2::{Ident, TokenStream as MacroStream, TokenStream}; +use proc_macro2::TokenStream as MacroStream; use quote::{ToTokens, format_ident, quote}; -use std::hash::Hash; -use syn::token::Typeof; pub mod auto_bind_plugin; pub mod auto_plugin; diff --git a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs index 48aa619a..c9cb6ca0 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs @@ -16,18 +16,6 @@ impl PartialEq for ExpandAttrs { } impl ExpandAttrs { - pub fn to_use_attr_ts_tuple(&self) -> (MacroStream, MacroStream) { - let use_items = &self.use_items; - let attrs = &self.attrs; - ( - quote! { - #(#use_items)* - }, - quote! { - #(#attrs)* - }, - ) - } pub fn with(mut self, other: Self) -> Self { self.append(other); self diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 5013bec9..e90c75b6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -498,7 +498,6 @@ mod tests { mod test_enum { use super::*; - use crate::syntax::validated::path_without_generics::PathWithoutGenerics; use quote::quote; #[xtest] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 6a440513..26b2c064 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -29,7 +29,6 @@ pub mod prelude { pub use super::ItemAttributePlugin; pub use super::ItemAttributeTarget; pub use super::ItemAttributeUniqueIdent; - pub use super::PluginCap; pub use super::auto_plugin::{ AutoPluginFnArgs, AutoPluginStructOrEnumArgs, resolve_app_param_name, }; @@ -149,12 +148,8 @@ where T: Hash, R: Hash, { - fn hash(&self, state: &mut H) { + fn hash(&self, _state: &mut H) { panic!("ItemAttribute should not be hashed"); - self.args.hash(state); - self.context.hash(state); - self.target.hash(state); - self._resolver.hash(state); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index 4c695ded..d77718c4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -21,8 +21,8 @@ impl AttributeIdent for ComponentArgs { const IDENT: &'static str = "auto_component"; } -impl<'a> From<&'a ComponentArgs> for RegisterTypeArgs { - fn from(value: &'a ComponentArgs) -> Self { +impl From<&ComponentArgs> for RegisterTypeArgs { + fn from(_: &ComponentArgs) -> Self { Self {} } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index c47cdc43..8b576a1c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -44,7 +44,7 @@ impl AttributeIdent for EventArgs { } impl<'a> From<&'a EventArgs> for RegisterTypeArgs { - fn from(value: &'a EventArgs) -> Self { + fn from(_: &'a EventArgs) -> Self { Self {} } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 1bd087a4..9a9aec44 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -19,13 +19,13 @@ impl AttributeIdent for MessageArgs { } impl<'a> From<&'a MessageArgs> for RegisterTypeArgs { - fn from(value: &'a MessageArgs) -> Self { + fn from(_: &'a MessageArgs) -> Self { Self {} } } impl<'a> From<&'a MessageArgs> for AddMessageArgs { - fn from(value: &'a MessageArgs) -> Self { + fn from(_: &'a MessageArgs) -> Self { Self {} } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index ce2b41e3..cf473dcc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -12,13 +12,13 @@ impl AttributeIdent for ObserverArgs { } impl<'a> From<&'a ObserverArgs> for RegisterTypeArgs { - fn from(value: &'a ObserverArgs) -> Self { + fn from(_: &'a ObserverArgs) -> Self { Self {} } } impl<'a> From<&'a ObserverArgs> for AddObserverArgs { - fn from(value: &'a ObserverArgs) -> Self { + fn from(_: &'a ObserverArgs) -> Self { AddObserverArgs {} } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index a23285d5..059958c6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -21,7 +21,7 @@ impl AttributeIdent for ResourceArgs { } impl<'a> From<&'a ResourceArgs> for RegisterTypeArgs { - fn from(value: &'a ResourceArgs) -> Self { + fn from(_: &'a ResourceArgs) -> Self { Self {} } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 87be9f5b..c2775d9a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -15,7 +15,7 @@ impl AttributeIdent for SystemArgs { } impl<'a> From<&'a SystemArgs> for RegisterTypeArgs { - fn from(value: &'a SystemArgs) -> Self { + fn from(_: &'a SystemArgs) -> Self { Self {} } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs index c664b6e6..25645670 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs @@ -3,7 +3,7 @@ use quote::{ToTokens, quote}; use syn::parse2; #[derive(Debug, Clone)] -pub(crate) enum InputItem { +pub enum InputItem { Tokens(TokenStream), Item(Box), } @@ -17,9 +17,6 @@ impl PartialEq for InputItem { } impl InputItem { - pub fn from_mut_ref(item_ts: TokenStream) -> Self { - Self::Tokens(item_ts) - } fn _upgrade(&mut self) -> syn::Result<()> { if let Self::Tokens(tokens) = self { *self = Self::Item(parse2(tokens.clone())?); @@ -60,7 +57,7 @@ impl InputItem { Item::Union(item) => Some(&item.ident), // TODO: implement Item::Use(_) => None, - Item::Verbatim(item) => None, + Item::Verbatim(_) => None, _ => None, }) } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index d9abcc5c..5261f5c0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -2,7 +2,6 @@ use crate::macro_api::mixins::HasKeys; use crate::macro_api::mixins::generics::HasGenerics; use crate::macro_api::prelude::WithZeroOrManyGenerics; use crate::syntax::ast::type_list::TypeList; -use crate::util::macros::impl_from_default; use darling::FromMeta; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index 9ddc54f5..b4aea89f 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -1,5 +1,4 @@ #![allow(dead_code)] -use crate::macro_api::prelude::InputItem; use crate::syntax::extensions::item::ItemAttrsExt; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/util/macros.rs b/crates/bevy_auto_plugin_shared/src/util/macros.rs index 939b6d77..098c0ac8 100644 --- a/crates/bevy_auto_plugin_shared/src/util/macros.rs +++ b/crates/bevy_auto_plugin_shared/src/util/macros.rs @@ -148,7 +148,6 @@ pub(crate) use { #[cfg(test)] mod tests { - use super::*; use internal_test_proc_macro::xtest; use proc_macro2::{Span, TokenStream}; use quote::{ToTokens, quote}; diff --git a/crates/internal_test_util/src/lib.rs b/crates/internal_test_util/src/lib.rs index 01a48006..4c69cbc2 100644 --- a/crates/internal_test_util/src/lib.rs +++ b/crates/internal_test_util/src/lib.rs @@ -69,7 +69,6 @@ macro_rules! vec_spread { #[cfg(test)] mod tests { - use super::*; use internal_test_proc_macro::xtest; #[xtest] fn test_vec_spread() { From 30ee7fbdea114349d7940a9769cea18f096f6dad Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:34:25 -0400 Subject: [PATCH 064/162] refactor: remove a lot of dead code and unused imports --- .../src/codegen/mod.rs | 4 -- .../src/codegen/tokens.rs | 2 + .../actions/auto_configure_system_set.rs | 1 + .../src/macro_api/attributes/auto_plugin.rs | 17 ------ .../src/macro_api/attributes/mod.rs | 35 +---------- .../macro_api/attributes/traits/generics.rs | 11 ---- .../src/macro_api/attributes/traits/mod.rs | 5 -- .../src/macro_api/composed.rs | 6 -- .../src/macro_api/input_item.rs | 2 + .../src/macro_api/qq.rs | 2 + .../src/syntax/analysis/item.rs | 7 --- .../src/syntax/ast/flag_or_list.rs | 1 + .../src/syntax/ast/flag_or_lit.rs | 1 + .../src/syntax/validated/concrete_path.rs | 25 -------- .../src/test_util/macros.rs | 61 ------------------- .../src/test_util/mod.rs | 20 ------ .../src/util/macros.rs | 2 + 17 files changed, 14 insertions(+), 188 deletions(-) delete mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/attributes/traits/generics.rs delete mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/attributes/traits/mod.rs delete mode 100644 crates/bevy_auto_plugin_shared/src/test_util/macros.rs diff --git a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs index c9cb6ca0..a490b105 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs @@ -16,10 +16,6 @@ impl PartialEq for ExpandAttrs { } impl ExpandAttrs { - pub fn with(mut self, other: Self) -> Self { - self.append(other); - self - } pub fn append(&mut self, other: Self) { self.attrs.extend(other.attrs); self.use_items.extend(other.use_items); diff --git a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs index e94462bf..cb445698 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs @@ -151,6 +151,8 @@ pub fn derive_reflect() -> TokenStream { quote! { #[derive(#derive_reflect_path)] } } +// TODO: we forgot to add this back in, but tests are still passing? +#[allow(dead_code)] pub fn use_bevy_state_app_ext_states() -> syn::ItemUse { let root = crate::__private::paths::state::root_path(); parse_quote! { use #root::app::AppExtStates as _; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index e90c75b6..b19d008f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -223,6 +223,7 @@ pub fn args_with_plugin_from_args_input( input: &mut TokenStream, ) -> syn::Result<()> { fn resolve_ident(item: &Item) -> syn::Result<&Ident> { + // TODO: remove and use ident from higher level resolve_ident_from_struct_or_enum(item) .map_err(|err| syn::Error::new(item.span(), format!("failed to resolve ident: {err}"))) } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs index 56a1bb97..bbe87789 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs @@ -1,4 +1,3 @@ -use crate::macro_api::prelude::*; use crate::syntax::analysis::fn_param::require_fn_param_mutable_reference; use crate::syntax::ast::type_list::TypeList; use darling::FromMeta; @@ -26,14 +25,6 @@ pub struct AutoPluginStructOrEnumArgs { pub impl_generic_plugin_trait: Flag, } -// TODO: remove? -impl GenericsArgs for AutoPluginStructOrEnumArgs { - fn type_lists(&self) -> &[TypeList] { - #[allow(deprecated)] - &self.generics - } -} - #[derive(FromMeta, Debug, Default, Clone, PartialEq)] #[darling(derive_syn_parse, default)] pub struct AutoPluginFnArgs { @@ -43,14 +34,6 @@ pub struct AutoPluginFnArgs { pub app_param: Option, } -// TODO: remove? -impl GenericsArgs for AutoPluginFnArgs { - const TURBOFISH: bool = true; - fn type_lists(&self) -> &[TypeList] { - &self.generics - } -} - pub fn resolve_app_param_name<'a>( input: &'a ItemFn, app_param_name: Option<&'a Ident>, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 26b2c064..5bb3b4b1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -1,5 +1,4 @@ use crate::macro_api::prelude::*; -use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::non_empty_path::NonEmptyPath; use crate::util::macros::impl_from_default; use proc_macro2::{Ident, TokenStream}; @@ -13,7 +12,6 @@ use syn::{Item, Path, parse_quote, parse2}; mod actions; mod auto_plugin; mod rewrites; -mod traits; pub mod prelude { pub use super::AllowAny; @@ -34,11 +32,13 @@ pub mod prelude { }; pub use crate::macro_api::attributes::actions::prelude::*; pub use crate::macro_api::attributes::rewrites::prelude::*; - pub use crate::macro_api::attributes::traits::prelude::*; } pub trait AttributeIdent { const IDENT: &'static str; + #[allow(dead_code)] + // TODO: should we use this over the context macro_paths? + // context macro paths would allow us to resolve aliased versions of this crate fn full_attribute_path() -> NonEmptyPath { let ident = format_ident!("{}", Self::IDENT); parse_quote!( ::bevy_auto_plugin::prelude::#ident ) @@ -124,12 +124,7 @@ impl IdentPathResolver for AllowAny { } impl_from_default!(AllowAny => (AllowStructOrEnum, AllowFn)); -pub trait PluginCap { - fn plugin_path(&self) -> &syn::Path; -} - pub trait GenericsCap { - fn generics(&self) -> &[TypeList]; fn concrete_paths(&self) -> Vec; } @@ -290,34 +285,10 @@ where } } -impl ItemAttribute { - fn convert_into(value: ItemAttribute) -> ItemAttribute - where - T2: From, - { - ItemAttribute { - args: T2::from(value.args), - context: value.context, - input_item: value.input_item, - target: value.target, - _resolver: PhantomData, - } - } -} - -impl PluginCap for ItemAttribute, R> { - fn plugin_path(&self) -> &syn::Path { - &self.args.plugin.plugin - } -} - impl GenericsCap for ItemAttribute, R> where M2: HasGenerics, { - fn generics(&self) -> &[TypeList] { - self.args.generics.generics() - } fn concrete_paths(&self) -> Vec { let target = &self.target; if self.args.generics.generics().is_empty() { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/traits/generics.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/traits/generics.rs deleted file mode 100644 index 0fc0da44..00000000 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/traits/generics.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::generics::GenericsCollection; - -pub trait GenericsArgs { - // TODO: see impl ToTokens for Generics - const TURBOFISH: bool = false; - fn type_lists(&self) -> &[TypeList]; - fn generics(&self) -> GenericsCollection { - GenericsCollection(self.type_lists().to_vec()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/traits/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/traits/mod.rs deleted file mode 100644 index db49589d..00000000 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/traits/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod generics; - -pub mod prelude { - pub use crate::macro_api::attributes::traits::generics::GenericsArgs; -} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 67f8bb1f..322e37bc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -113,12 +113,6 @@ where { } -impl Composed { - pub fn args(&self) -> &CBase { - &self.base - } -} - impl Composed { pub fn plugin(&self) -> &syn::Path { &self.plugin.plugin diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs index 25645670..c6c35b38 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs @@ -37,6 +37,8 @@ impl InputItem { _ => unreachable!(), }) } + // TODO: use instead of analysis/item helpers? + #[allow(dead_code)] pub fn get_ident(&mut self) -> syn::Result> { use syn::Item; let item = self.ensure_ast()?; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 403536c0..419c8d87 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -48,6 +48,8 @@ where T: MacroPathProvider + ItemAttributeInput + ItemAttributeContext, Self: ToTokens, { + // TODO: replace the one ins expand/attr + #[allow(dead_code)] pub fn inject_attribute_macro(&mut self) -> syn::Result<()> { let args = self.to_token_stream(); let macro_path = T::macro_path(self.args.context()).clone(); diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs index 62ffa822..4453844b 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs @@ -28,13 +28,6 @@ impl From> for syn::Error { pub type IdentFromItemResult<'a> = Result<&'a Ident, ResolveIdentFromItemError<'a>>; -pub fn resolve_ident_from_fn(item: &Item) -> IdentFromItemResult<'_> { - match item { - Item::Fn(f) => Ok(&f.sig.ident), - _ => Err(ResolveIdentFromItemError::NotFn(item)), - } -} - pub fn resolve_ident_from_struct_or_enum(item: &Item) -> IdentFromItemResult<'_> { match item { Item::Struct(s) => Ok(&s.ident), diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs index 43f40786..708f44d6 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs @@ -21,6 +21,7 @@ impl FlagOrList where T: ToTokens + Parse, { + #[cfg(test)] pub fn to_outer_tokens(&self, flag_name: &str) -> TokenStream { use syn::spanned::Spanned; let flag_ident = Ident::new(flag_name, self.present.span()); diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs index 7c8ae1ae..3ab77519 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs @@ -14,6 +14,7 @@ pub struct FlagOrLit { } impl FlagOrLit { + #[cfg(test)] pub fn to_outer_tokens(&self, flag_name: &str) -> TokenStream { use syn::spanned::Spanned; let flag_ident = Ident::new(flag_name, self.present.span()); diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs index 7c396eb6..158b41f6 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs @@ -39,16 +39,6 @@ pub struct ConcreteTargetPathWithGenericsCollection { pub turbofish: bool, } -impl ConcreteTargetPathWithGenericsCollection { - pub fn from_args(path: PathWithoutGenerics, args: &T) -> Self { - Self { - target: path, - generics: args.generics(), - turbofish: T::TURBOFISH, - } - } -} - impl IntoIterator for ConcreteTargetPathWithGenericsCollection { type Item = ConcreteTargetPath; type IntoIter = std::vec::IntoIter; @@ -68,21 +58,6 @@ impl IntoIterator for ConcreteTargetPathWithGenericsCollection { } } -impl From<(PathWithoutGenerics, T)> for ConcreteTargetPathWithGenericsCollection { - fn from(value: (PathWithoutGenerics, T)) -> Self { - let (target, args) = value; - Self::from_args(target, &args) - } -} - -impl TryFrom<(Path, T)> for ConcreteTargetPathWithGenericsCollection { - type Error = TryFromPathWithoutGenericsError; - fn try_from(value: (Path, T)) -> Result { - let (target, args) = value; - Ok(Self::from((target.try_into()?, args))) - } -} - pub fn generics_from_path(path: &Path) -> syn::Result { let mut generics = TypeList::empty(); for segment in &path.segments { diff --git a/crates/bevy_auto_plugin_shared/src/test_util/macros.rs b/crates/bevy_auto_plugin_shared/src/test_util/macros.rs deleted file mode 100644 index 1b9d9f0e..00000000 --- a/crates/bevy_auto_plugin_shared/src/test_util/macros.rs +++ /dev/null @@ -1,61 +0,0 @@ -macro_rules! parse_attribute_args_with_plugin { - // with meta args - ($plugin:expr, $args_ident:ident, $tokens:expr $(,)?) => {{ - use quote::quote; - use $crate::codegen::tokens::ArgsWithPlugin; - use $crate::macro_api::with_plugin::{ WithPlugin}; - let plugin = $plugin.clone(); - let macro_path = <$args_ident as AttributeIdent>::full_attribute_path(); - - let mut args = vec![ - quote!(plugin = #plugin) - ]; - - if !$tokens.is_empty() { - args.push($tokens); - } - - let input = quote! { #[#macro_path( #(#args),* )] }; - let attr: syn::Attribute = syn::parse_quote! { #input }; - let args_with_plugin = ArgsWithPlugin::from(WithPlugin::<$args_ident>::from_meta(&attr.meta)?); - (plugin, input, args_with_plugin) - }}; -} - -macro_rules! parse_vec_args { - ($plugin:expr, $args_ident:ident, $args:expr $(,)?) => {{ - let args = $args; - $crate::test_util::macros::parse_attribute_args_with_plugin!( - $plugin, - $args_ident, - quote! { #(#args),* } - ) - }}; - - ($plugin:expr, $args_ident:ident $(,)?) => {{ $crate::test_util::macros::parse_attribute_args_with_plugin!($plugin, $args_ident) }}; -} - -macro_rules! assert_vec_args_expand { - ($plugin:expr, $args_ident:ident, $args:expr $(,)?) => {{ - let (plugin, input, args) = - $crate::test_util::macros::parse_vec_args!($plugin, $args_ident, $args); - $crate::test_util::assert_tokens_match(plugin, input, args); - }}; - - ($plugin:expr, $args_ident:ident $(,)?) => {{ - let (plugin, input, args) = $crate::parse_vec_args!($plugin, $args_ident); - $crate::test_util::assert_tokens_match(plugin, input, args); - }}; -} - -macro_rules! plugin { - ($plugin:expr) => {{ $crate::syntax::validated::non_empty_path::NonEmptyPath::new_unchecked($plugin) }}; -} - -#[rustfmt::skip] -pub(crate) use { - parse_attribute_args_with_plugin, - parse_vec_args, - assert_vec_args_expand, - plugin, -}; diff --git a/crates/bevy_auto_plugin_shared/src/test_util/mod.rs b/crates/bevy_auto_plugin_shared/src/test_util/mod.rs index ce063de0..323ddc10 100644 --- a/crates/bevy_auto_plugin_shared/src/test_util/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/test_util/mod.rs @@ -1,21 +1 @@ pub(crate) mod combo; -pub(crate) mod macros; - -pub(crate) fn assert_tokens_match( - plugin: impl std::fmt::Debug, - input: impl ToString, - args: impl quote::ToTokens, -) { - let input = input.to_string(); - assert_eq!( - args.to_token_stream().to_string(), - input, - concat!( - "failed to expand into expected tokens - args: ", - stringify!($args_ident), - ", plugin: {:?}, args_inner: {}" - ), - plugin, - input, - ); -} diff --git a/crates/bevy_auto_plugin_shared/src/util/macros.rs b/crates/bevy_auto_plugin_shared/src/util/macros.rs index 098c0ac8..c3dad5ab 100644 --- a/crates/bevy_auto_plugin_shared/src/util/macros.rs +++ b/crates/bevy_auto_plugin_shared/src/util/macros.rs @@ -85,6 +85,8 @@ macro_rules! bevy_crate_path { use ::syn::parse2; use ::std::{concat, stringify}; use ::syn::Path; + // unused import for tests + #[cfg(not(test))] use $crate::util::macros::as_cargo_alias; #[allow(clippy::result_large_err)] let res: Result:: = match crate_name(concat!("bevy_", stringify!($target_crate))) { From 2286fb683cbf8a27165054e6347eecc726fe1c6c Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:36:18 -0400 Subject: [PATCH 065/162] fix: update `to_tokens` tests to use `assert_eq!` --- .../macro_api/mixins/generics/with_many.rs | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs index 96c4f3ca..dc206981 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs @@ -45,32 +45,38 @@ mod tests { #[xtest] fn test_to_tokens_zero() { - WithZeroOrManyGenerics { generics: vec![] } - .to_token_stream() - .to_string() - == r#""#; + assert_eq!( + WithZeroOrManyGenerics { generics: vec![] } + .to_token_stream() + .to_string(), + quote!().to_string() + ); } #[xtest] fn test_to_tokens_single() { - WithZeroOrManyGenerics { - generics: vec![TypeList(vec![parse_quote!(bool), parse_quote!(u32)])], - } - .to_token_stream() - .to_string() - == r#"generics(bool, u32)"#; + assert_eq!( + WithZeroOrManyGenerics { + generics: vec![TypeList(vec![parse_quote!(bool), parse_quote!(u32)])], + } + .to_token_stream() + .to_string(), + quote!(generics(bool, u32)).to_string() + ); } #[xtest] fn test_to_tokens_multiple() { - WithZeroOrManyGenerics { - generics: vec![ - TypeList(vec![parse_quote!(bool), parse_quote!(u32)]), - TypeList(vec![parse_quote!(usize)]), - ], - } - .to_token_stream() - .to_string() - == r#"generics(bool, u32), generics(usize)"#; + assert_eq!( + WithZeroOrManyGenerics { + generics: vec![ + TypeList(vec![parse_quote!(bool), parse_quote!(u32)]), + TypeList(vec![parse_quote!(usize)]), + ], + } + .to_token_stream() + .to_string(), + quote!(generics(bool, u32), generics(usize)).to_string() + ); } } From 9b34717891055e21115e630ad826fdd97fe02500 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:38:27 -0400 Subject: [PATCH 066/162] refactor: scope imports for cfg(test) --- .../src/syntax/ast/flag_or_list.rs | 10 ++++++---- .../src/syntax/ast/flag_or_lit.rs | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs index 708f44d6..e3347f0f 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs @@ -1,6 +1,5 @@ use darling::{Error, FromMeta, Result}; -use proc_macro2::{Ident, TokenStream}; -use quote::{ToTokens, quote}; +use quote::ToTokens; use smart_default::SmartDefault; use syn::parse::Parse; use syn::punctuated::Punctuated; @@ -22,9 +21,10 @@ where T: ToTokens + Parse, { #[cfg(test)] - pub fn to_outer_tokens(&self, flag_name: &str) -> TokenStream { + pub fn to_outer_tokens(&self, flag_name: &str) -> proc_macro2::TokenStream { + use quote::quote; use syn::spanned::Spanned; - let flag_ident = Ident::new(flag_name, self.present.span()); + let flag_ident = proc_macro2::Ident::new(flag_name, self.present.span()); if self.present { let items = &self.items; if !items.is_empty() { @@ -71,6 +71,8 @@ where mod tests { use super::*; use internal_test_proc_macro::xtest; + use proc_macro2::Ident; + use quote::quote; use syn::parse_quote; #[xtest] diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs index 3ab77519..8330ee40 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs @@ -1,6 +1,4 @@ use darling::{Error, FromMeta, Result}; -use proc_macro2::{Ident, TokenStream}; -use quote::quote; use smart_default::SmartDefault; use syn::spanned::Spanned; use syn::{Expr, Lit, Meta}; @@ -15,9 +13,10 @@ pub struct FlagOrLit { impl FlagOrLit { #[cfg(test)] - pub fn to_outer_tokens(&self, flag_name: &str) -> TokenStream { + pub fn to_outer_tokens(&self, flag_name: &str) -> proc_macro2::TokenStream { + use quote::quote; use syn::spanned::Spanned; - let flag_ident = Ident::new(flag_name, self.present.span()); + let flag_ident = proc_macro2::Ident::new(flag_name, self.present.span()); if self.present { let items = &self.lit; if let Some(lit) = items { @@ -59,6 +58,7 @@ impl FromMeta for FlagOrLit { mod tests { use super::*; use internal_test_proc_macro::xtest; + use quote::quote; use syn::parse_quote; #[xtest] From 620c292c56bb6237863edea6ef6dcd57249528c5 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:38:53 -0400 Subject: [PATCH 067/162] refactor: clean up imports in `concrete_path.rs` --- .../src/syntax/validated/concrete_path.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs index 158b41f6..736e9e7b 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs @@ -1,9 +1,6 @@ -use crate::macro_api::prelude::*; use crate::syntax::ast::type_list::TypeList; use crate::syntax::validated::generics::{Generics, GenericsCollection}; -use crate::syntax::validated::path_without_generics::{ - PathWithoutGenerics, TryFromPathWithoutGenericsError, -}; +use crate::syntax::validated::path_without_generics::PathWithoutGenerics; use proc_macro2::TokenStream as MacroStream; use quote::{ToTokens, quote}; use syn::{Path, PathArguments, parse2}; From 97e6c4d2685ea8b361a4bc89ec27f7783b644faa Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:42:07 -0400 Subject: [PATCH 068/162] refactor: remove dead code and migrate `generics_from_path` to `syntax/analysis` --- .../src/syntax/analysis/mod.rs | 1 + .../src/syntax/analysis/path.rs | 33 +++++ .../src/syntax/extensions/path.rs | 4 +- .../src/syntax/validated/concrete_path.rs | 135 ------------------ .../src/syntax/validated/generics.rs | 108 -------------- .../src/syntax/validated/mod.rs | 2 - 6 files changed, 36 insertions(+), 247 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/syntax/analysis/path.rs delete mode 100644 crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs delete mode 100644 crates/bevy_auto_plugin_shared/src/syntax/validated/generics.rs diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs index e91df11d..2294853b 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs @@ -1,3 +1,4 @@ pub mod fn_param; pub mod item; +pub mod path; pub mod ty_classify; diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/path.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/path.rs new file mode 100644 index 00000000..ec3e0855 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/path.rs @@ -0,0 +1,33 @@ +use crate::syntax::ast::type_list::TypeList; +use quote::ToTokens; +use syn::{Path, PathArguments, parse2}; + +pub fn generics_from_path(path: &Path) -> syn::Result { + let mut generics = TypeList::empty(); + for segment in &path.segments { + if let PathArguments::AngleBracketed(angle_bracketed) = &segment.arguments { + let type_list = parse2::(angle_bracketed.args.to_token_stream())?; + generics.0.extend(type_list.0); + } + } + Ok(generics) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::syntax::analysis::path::generics_from_path; + use internal_test_proc_macro::xtest; + use quote::quote; + + #[xtest] + fn test_generics_from_path() -> Result<(), syn::Error> { + let item = parse2::(quote! { + foo::bar:: + })?; + let generics = generics_from_path(&item).expect("no generics"); + let generics = quote! { #generics }; + assert_eq!("u32 , i32", generics.to_string()); + Ok(()) + } +} diff --git a/crates/bevy_auto_plugin_shared/src/syntax/extensions/path.rs b/crates/bevy_auto_plugin_shared/src/syntax/extensions/path.rs index f680335f..70a8ffe4 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/extensions/path.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/extensions/path.rs @@ -1,5 +1,5 @@ +use crate::syntax::analysis::path; use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::concrete_path; use syn::Path; pub trait PathExt { @@ -19,7 +19,7 @@ impl PathExt for Path { } fn generics(&self) -> syn::Result { - concrete_path::generics_from_path(self) + path::generics_from_path(self) } fn is_similar_path_or_ident(&self, other: &Self) -> bool { diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs deleted file mode 100644 index 736e9e7b..00000000 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/concrete_path.rs +++ /dev/null @@ -1,135 +0,0 @@ -use crate::syntax::ast::type_list::TypeList; -use crate::syntax::validated::generics::{Generics, GenericsCollection}; -use crate::syntax::validated::path_without_generics::PathWithoutGenerics; -use proc_macro2::TokenStream as MacroStream; -use quote::{ToTokens, quote}; -use syn::{Path, PathArguments, parse2}; - -#[derive(Debug, Clone, PartialEq, Hash)] -pub struct ConcreteTargetPath { - pub target: PathWithoutGenerics, - pub generics: Generics, - pub turbofish: bool, -} - -impl ToTokens for ConcreteTargetPath { - fn to_tokens(&self, tokens: &mut MacroStream) { - let path = &self.target; - let generics = &self.generics; - tokens.extend(if generics.is_empty() { - // TODO: generics already handles tokens properly when empty but we shoehorned the turbofish flag - // seemed more appropriate than forcing Generics to inherit the complexity and become an enum for both variants - // but there's likely a better way? - quote! { #path } - } else if self.turbofish { - quote! { #path :: #generics } - } else { - quote! { #path #generics } - }); - } -} - -#[derive(Debug, Clone, PartialEq, Hash)] -pub struct ConcreteTargetPathWithGenericsCollection { - pub target: PathWithoutGenerics, - pub generics: GenericsCollection, - pub turbofish: bool, -} - -impl IntoIterator for ConcreteTargetPathWithGenericsCollection { - type Item = ConcreteTargetPath; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - // TODO: better way? - self.generics - .iter_with_default_generics_when_empty() - .into_iter() - .map(|generics| ConcreteTargetPath { - target: self.target.clone(), - generics, - turbofish: self.turbofish, - }) - .collect::>() - .into_iter() - } -} - -pub fn generics_from_path(path: &Path) -> syn::Result { - let mut generics = TypeList::empty(); - for segment in &path.segments { - if let PathArguments::AngleBracketed(angle_bracketed) = &segment.arguments { - let type_list = parse2::(angle_bracketed.args.to_token_stream())?; - generics.0.extend(type_list.0); - } - } - Ok(generics) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::syntax::validated::generics::Generics; - use internal_test_proc_macro::xtest; - - #[xtest] - fn test_generics_from_path() -> Result<(), syn::Error> { - let item = parse2::(quote! { - foo::bar:: - })?; - let generics = generics_from_path(&item).expect("no generics"); - let generics = quote! { #generics }; - assert_eq!("u32 , i32", generics.to_string()); - Ok(()) - } - - #[xtest] - fn test_concrete_target_path_to_tokens() -> syn::Result<()> { - assert_eq!( - ConcreteTargetPath { - target: parse2::(quote! { Foo })?, - generics: Generics(parse2::(quote! {})?), - turbofish: false, - } - .to_token_stream() - .to_string(), - quote! { Foo }.to_string() - ); - assert_eq!( - ConcreteTargetPath { - target: parse2::(quote! { Foo })?, - generics: Generics(parse2::(quote! { u8 })?), - turbofish: false, - } - .to_token_stream() - .to_string(), - quote! { Foo }.to_string() - ); - Ok(()) - } - - #[xtest] - fn test_concrete_target_path_to_tokens_turbofish() -> syn::Result<()> { - assert_eq!( - ConcreteTargetPath { - target: parse2::(quote! { Foo })?, - generics: Generics(parse2::(quote! {})?), - turbofish: true, - } - .to_token_stream() - .to_string(), - quote! { Foo }.to_string() - ); - assert_eq!( - ConcreteTargetPath { - target: parse2::(quote! { Foo })?, - generics: Generics(parse2::(quote! { u8 })?), - turbofish: true, - } - .to_token_stream() - .to_string(), - quote! { Foo:: }.to_string() - ); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/generics.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/generics.rs deleted file mode 100644 index ba831a92..00000000 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/generics.rs +++ /dev/null @@ -1,108 +0,0 @@ -use crate::syntax::ast::type_list::TypeList; -use proc_macro2::TokenStream as MacroStream; -use quote::{ToTokens, quote}; - -#[derive(Debug, Clone, PartialEq, Hash)] -pub struct GenericsCollection(pub Vec); - -impl GenericsCollection { - pub fn iter_with_default_generics_when_empty(self) -> impl IntoIterator { - let mut vec = self.0.into_iter().map(Generics).collect::>(); - - if vec.is_empty() { - vec.push(Generics::default()); - } - - vec.into_iter() - } - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - pub fn to_attribute_arg_vec_tokens(&self) -> Vec { - self.0 - .iter() - .map(|type_list| quote!(generics(#type_list))) - .collect() - } - pub fn to_attribute_arg_tokens(&self) -> MacroStream { - let tokens = self.to_attribute_arg_vec_tokens(); - quote!(#(#tokens),*) - } -} - -impl IntoIterator for GenericsCollection { - type Item = Generics; - type IntoIter = std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0 - .into_iter() - .map(Generics) - .collect::>() - .into_iter() - } -} - -#[derive(Debug, Clone, Default, PartialEq, Hash)] -pub struct Generics(pub TypeList); - -impl Generics { - pub fn empty() -> Self { - Generics(TypeList::empty()) - } - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -impl ToTokens for Generics { - fn to_tokens(&self, tokens: &mut MacroStream) { - if self.is_empty() { - return; - } - let types = &self.0; - tokens.extend(quote!(< #types >)); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use darling::FromMeta; - use internal_test_proc_macro::xtest; - use quote::quote; - use syn::Type; - use syn::TypePath; - - fn types() -> syn::Result { - let ty_u32 = Type::Path(TypePath::from_string("u32")?); - let ty_bool = Type::Path(TypePath::from_string("bool")?); - Ok(TypeList(vec![ty_u32, ty_bool])) - } - - #[xtest] - fn test_generics() -> syn::Result<()> { - assert_eq!( - Generics(TypeList::empty()).to_token_stream().to_string(), - quote!().to_string() - ); - assert_eq!( - Generics(types()?).to_token_stream().to_string(), - quote!().to_string() - ); - assert_eq!( - Generics(types()?).to_token_stream().to_string(), - quote!().to_string() - ); - Ok(()) - } - - #[xtest] - fn test_generics_collection() -> syn::Result<()> { - let generics = GenericsCollection(vec![types()?]); - let mut iter = generics.into_iter(); - assert_eq!(iter.next(), Some(Generics(types()?))); - assert_eq!(iter.next(), None); - Ok(()) - } -} diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/mod.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/mod.rs index 3e2abd2c..f16fc98a 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/validated/mod.rs @@ -1,4 +1,2 @@ -pub mod concrete_path; -pub mod generics; pub mod non_empty_path; pub mod path_without_generics; From 40ad8431f5464eb5292d380eaa4d008c516a6e07 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 14:58:23 -0400 Subject: [PATCH 069/162] refactor: remove redundant `Hash` trait bounds and clean up implementations --- .../src/macro_api/attributes/mod.rs | 42 ++++++++----------- .../src/macro_api/composed.rs | 21 ++++++++-- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 5bb3b4b1..2e45a4ae 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -45,7 +45,7 @@ pub trait AttributeIdent { } } -pub trait ItemAttributeArgs: AttributeIdent + Hash + Clone { +pub trait ItemAttributeArgs: AttributeIdent + Clone { fn global_build_prefix() -> Ident { format_ident!("_auto_plugin_{}_", Self::IDENT) } @@ -53,16 +53,16 @@ pub trait ItemAttributeArgs: AttributeIdent + Hash + Clone { impl AttributeIdent for ItemAttribute where - T: AttributeIdent + Hash + Clone, + T: AttributeIdent + Clone, { const IDENT: &'static str = T::IDENT; } impl ItemAttributeArgs for ItemAttribute, R> where - T: AttributeIdent + Hash + Clone, - P: Clone + Hash, - G: Clone + Hash, - R: Clone + Hash, + T: AttributeIdent + Clone, + P: Clone, + G: Clone, + R: Clone, { } @@ -137,23 +137,12 @@ pub struct ItemAttribute { pub _resolver: PhantomData, } -// TODO: this impl doesnt make sense for this context but its required for ItemAttributeArgs -impl Hash for ItemAttribute -where - T: Hash, - R: Hash, -{ - fn hash(&self, _state: &mut H) { - panic!("ItemAttribute should not be hashed"); - } -} - // TODO: where should this live? -impl ItemAttribute -where - T: Hash, -{ - pub fn _concat_ident_hash(&self, ident: &Ident) -> String { +impl ItemAttribute { + pub fn _concat_ident_hash(&self, ident: &Ident) -> String + where + T: Hash, + { use std::hash::{Hash, Hasher}; let mut hasher = std::collections::hash_map::DefaultHasher::new(); ident.hash(&mut hasher); @@ -161,7 +150,10 @@ where format!("{:x}", hasher.finish()) } - pub fn _get_unique_ident(&self, prefix: Ident, ident: &Ident) -> Ident { + pub fn _get_unique_ident(&self, prefix: Ident, ident: &Ident) -> Ident + where + T: Hash, + { let hash = self._concat_ident_hash(ident); format_ident!("{prefix}_{hash}") } @@ -194,7 +186,7 @@ pub trait ItemAttributeTarget { impl ItemAttributeTarget for ItemAttribute where T: AttributeIdent + Hash + Clone, - Resolver: Hash + Clone, + Resolver: Clone, { fn target(&self) -> &syn::Path { &self.target @@ -209,7 +201,7 @@ impl ItemAttributeUniqueIdent for ItemAttribute where ItemAttribute: ItemAttributeArgs, T: AttributeIdent + Hash + Clone, - Resolver: Hash + Clone, + Resolver: Clone, { fn get_unique_ident(&self) -> Ident { self._get_unique_ident( diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 322e37bc..46986659 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -11,18 +11,31 @@ use darling::ast::NestedMeta; use proc_macro2::TokenStream; use quote::ToTokens; use std::collections::HashSet; -use std::hash::Hash; +use std::hash::{Hash, Hasher}; use syn::parse::{Parse, ParseStream}; use syn::parse_quote; use syn::punctuated::Punctuated; -#[derive(Debug, Clone, PartialEq, Hash)] +#[derive(Debug, Clone, PartialEq)] pub struct Composed { pub base: CBase, pub plugin: MPlugin, pub generics: MGenerics, } +impl Hash for Composed +where + C: Hash, + P: Hash, + G: Hash, +{ + fn hash(&self, state: &mut H) { + self.base.hash(state); + self.plugin.hash(state); + self.generics.hash(state); + } +} + impl FromMeta for Composed where CBase: FromMeta, @@ -108,8 +121,8 @@ where impl ItemAttributeArgs for Composed where T: ItemAttributeArgs, - P: Hash + Clone, - G: Hash + Clone, + P: Clone, + G: Clone, { } From 128b2dbd610baabe5ff58331922a8866f9a0d769 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 15:12:48 -0400 Subject: [PATCH 070/162] refactor: suppress warnings for dead code and add placeholder implementations for `EmitGuard` --- .../src/macro_api/composed.rs | 2 + .../src/test_util/combo.rs | 2 + .../src/util/after_drop.rs | 91 +++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 46986659..95f66ffb 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -139,6 +139,8 @@ where pub fn generics(&self) -> &[TypeList] { self.generics.generics() } + #[allow(dead_code)] + // TODO: which one to use? pub fn concrete_paths(&self, target: &syn::Path) -> Vec { if self.generics.generics().is_empty() { vec![target.clone()] diff --git a/crates/bevy_auto_plugin_shared/src/test_util/combo.rs b/crates/bevy_auto_plugin_shared/src/test_util/combo.rs index 5524b852..5ba3c3f6 100644 --- a/crates/bevy_auto_plugin_shared/src/test_util/combo.rs +++ b/crates/bevy_auto_plugin_shared/src/test_util/combo.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] +/// might still need when rewriting the old tests that were removed use internal_test_util::vec_spread; use std::borrow::Borrow; diff --git a/crates/bevy_auto_plugin_shared/src/util/after_drop.rs b/crates/bevy_auto_plugin_shared/src/util/after_drop.rs index d946da56..1a435cf8 100644 --- a/crates/bevy_auto_plugin_shared/src/util/after_drop.rs +++ b/crates/bevy_auto_plugin_shared/src/util/after_drop.rs @@ -1,3 +1,94 @@ +#![allow(dead_code)] +/** mock up usages + +use proc_macro2::TokenStream; +use quote::quote; +use syn::Item; + +pub struct EmitGuard<'a> { + out: &'a mut TokenStream, + original: TokenStream, + checkpoint: TokenStream, + done: bool, +} + +impl<'a> EmitGuard<'a> { + pub fn new(out: &'a mut TokenStream) -> Self { + let original = out.clone(); // cheap, Arc-backed + Self { + out, + checkpoint: original.clone(), + original, + done: false, + } + } + + /// Read-only view of the original tokens for parsing. + pub fn snapshot(&self) -> &TokenStream { + &self.original + } + + /// Save a checkpoint from an AST state. + pub fn checkpoint_item(&mut self, item: &Item) { + self.checkpoint = quote!(#item); + } + + /// Save a checkpoint from raw tokens. + pub fn checkpoint_tokens(&mut self, ts: TokenStream) { + self.checkpoint = ts; + } + + /// Finish successfully with a final AST. + pub fn succeed(mut self, item: Item) { + *self.out = quote!(#item); + self.done = true; + } + + /// Finish with an error, emitting compile_error! + last checkpoint. + pub fn fail(mut self, err: syn::Error) { + let ce = err.to_compile_error(); + let ckpt = std::mem::take(&mut self.checkpoint); + *self.out = quote!(#ce #ckpt); + self.done = true; + } +} + +impl<'a> Drop for EmitGuard<'a> { + fn drop(&mut self) { + if !self.done { + // Safety net: early-returned without succeed/fail, + // emit the last checkpoint. + *self.out = self.checkpoint.clone(); + } + } +} +*/ +/** usage + +pub fn my_attr(_attr: TokenStream, mut input: TokenStream) -> TokenStream { + let mut emit = EmitGuard::new(&mut input); + + // Parse from the original snapshot + let mut item: Item = match syn::parse2(emit.snapshot().clone()) { + Ok(it) => it, + Err(e) => return { emit.fail(e); input }, + }; + + // Stage 1: scrub helper attributes + scrub_helpers(&mut item)?; + emit.checkpoint_item(&item); // helpers removed → safe checkpoint + + // Stage 2: other transforms (can add more checkpoints between steps) + transform_x(&mut item)?; + // emit.checkpoint_item(&item); + + // Done + emit.succeed(item); + input +} + + +*/ use std::ops::{Deref, DerefMut}; pub struct AfterDrop<'a, T, F: FnOnce(&'a mut T)> { From 510ab349a6059228b65718222bf71292722da966 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 25 Oct 2025 22:25:38 -0400 Subject: [PATCH 071/162] refactor: dont scrub readonly --- .../src/__private/expand/attr/mod.rs | 8 +++----- .../attributes/actions/auto_configure_system_set.rs | 10 +++------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index e1546b36..1b5e4a7d 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -54,12 +54,10 @@ where input ); let body_fn = body(|body| quote! { #body }); - let q = Q::from_args(args); - // TODO: hack for auto_configure_system_set + let mut q = Q::from_args(args); let scrubbed_input = { - let mut scrubbed = q.clone(); - ok_or_emit_with!(scrubbed.scrub_item(), scrubbed.args.input_item()); - scrubbed.args.input_item().to_token_stream() + ok_or_emit_with!(q.scrub_item(), q.args.input_item()); + q.args.input_item().to_token_stream() }; let after_item_tokens = ok_or_emit_with!(body_fn(q), scrubbed_input); quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index b19d008f..5d50e555 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -162,14 +162,10 @@ impl ToTokensWithAppParam for QConfigureSystemSet { Ok(()) } fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - // TODO: HACK - probably shouldn't be scrubbing here - let mut this = self.clone(); - this.scrub_item().unwrap(); - - let generics = this.args.args.generics(); - for concrete_path in this.args.concrete_paths() { + let generics = self.args.args.generics(); + for concrete_path in self.args.concrete_paths() { tokens.extend(output( - &this.args.args.base, + &self.args.args.base, app_param, &concrete_path, !generics.is_empty(), From 7ba2d876d6e86a096d24c253c3568db61d170d3d Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 00:00:37 -0400 Subject: [PATCH 072/162] store --- .../src/util/after_drop.rs | 90 -------------- .../src/util/emit_guard.rs | 117 ++++++++++++++++++ .../bevy_auto_plugin_shared/src/util/mod.rs | 1 + 3 files changed, 118 insertions(+), 90 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/util/emit_guard.rs diff --git a/crates/bevy_auto_plugin_shared/src/util/after_drop.rs b/crates/bevy_auto_plugin_shared/src/util/after_drop.rs index 1a435cf8..5d8b69b8 100644 --- a/crates/bevy_auto_plugin_shared/src/util/after_drop.rs +++ b/crates/bevy_auto_plugin_shared/src/util/after_drop.rs @@ -1,94 +1,4 @@ #![allow(dead_code)] -/** mock up usages - -use proc_macro2::TokenStream; -use quote::quote; -use syn::Item; - -pub struct EmitGuard<'a> { - out: &'a mut TokenStream, - original: TokenStream, - checkpoint: TokenStream, - done: bool, -} - -impl<'a> EmitGuard<'a> { - pub fn new(out: &'a mut TokenStream) -> Self { - let original = out.clone(); // cheap, Arc-backed - Self { - out, - checkpoint: original.clone(), - original, - done: false, - } - } - - /// Read-only view of the original tokens for parsing. - pub fn snapshot(&self) -> &TokenStream { - &self.original - } - - /// Save a checkpoint from an AST state. - pub fn checkpoint_item(&mut self, item: &Item) { - self.checkpoint = quote!(#item); - } - - /// Save a checkpoint from raw tokens. - pub fn checkpoint_tokens(&mut self, ts: TokenStream) { - self.checkpoint = ts; - } - - /// Finish successfully with a final AST. - pub fn succeed(mut self, item: Item) { - *self.out = quote!(#item); - self.done = true; - } - - /// Finish with an error, emitting compile_error! + last checkpoint. - pub fn fail(mut self, err: syn::Error) { - let ce = err.to_compile_error(); - let ckpt = std::mem::take(&mut self.checkpoint); - *self.out = quote!(#ce #ckpt); - self.done = true; - } -} - -impl<'a> Drop for EmitGuard<'a> { - fn drop(&mut self) { - if !self.done { - // Safety net: early-returned without succeed/fail, - // emit the last checkpoint. - *self.out = self.checkpoint.clone(); - } - } -} -*/ -/** usage - -pub fn my_attr(_attr: TokenStream, mut input: TokenStream) -> TokenStream { - let mut emit = EmitGuard::new(&mut input); - - // Parse from the original snapshot - let mut item: Item = match syn::parse2(emit.snapshot().clone()) { - Ok(it) => it, - Err(e) => return { emit.fail(e); input }, - }; - - // Stage 1: scrub helper attributes - scrub_helpers(&mut item)?; - emit.checkpoint_item(&item); // helpers removed → safe checkpoint - - // Stage 2: other transforms (can add more checkpoints between steps) - transform_x(&mut item)?; - // emit.checkpoint_item(&item); - - // Done - emit.succeed(item); - input -} - - -*/ use std::ops::{Deref, DerefMut}; pub struct AfterDrop<'a, T, F: FnOnce(&'a mut T)> { diff --git a/crates/bevy_auto_plugin_shared/src/util/emit_guard.rs b/crates/bevy_auto_plugin_shared/src/util/emit_guard.rs new file mode 100644 index 00000000..06a61045 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/util/emit_guard.rs @@ -0,0 +1,117 @@ +use proc_macro2::TokenStream; +use quote::{ToTokens, quote}; +use std::ops::{Deref, DerefMut}; + +/** Example usage: +pub fn my_attr(_attr: TokenStream, mut input: TokenStream) -> TokenStream { + let mut emit = EmitGuard::new(&mut input); + + // Parse from the original snapshot + let mut item: Item = match syn::parse2(emit.snapshot().clone()) { + Ok(it) => it, + Err(e) => return { emit.fail(e); input }, + }; + + // Stage 1: scrub helper attributes + scrub_helpers(&mut item)?; + emit.checkpoint_item(&item); // helpers removed → safe checkpoint + + // Stage 2: other transforms (can add more checkpoints between steps) + transform_x(&mut item)?; + // emit.checkpoint_item(&item); + + // Done + emit.succeed(item); + input +} +*/ +#[derive(Debug)] +pub struct EmitGuard<'a> { + out: &'a mut TokenStream, + original: TokenStream, + checkpoint: TokenStream, + done: bool, +} + +impl<'a> EmitGuard<'a> { + pub fn new(out: &'a mut TokenStream) -> Self { + let original = out.clone(); + Self { + out, + checkpoint: original.clone(), + original, + done: false, + } + } + + /// Read-only view of the original tokens for parsing. + pub fn snapshot(&self) -> &TokenStream { + &self.original + } + + /// Save a checkpoint from an AST state. + pub fn checkpoint(&mut self, item: impl Into) { + let item = item.into(); + self.checkpoint = quote!(#item); + } + + /// Finish successfully with a final AST. + pub fn succeed(&mut self, item: impl Into) { + let item = item.into(); + *self.out = quote!(#item); + self.done = true; + } + + /// Finish with an error, emitting compile_error! + last checkpoint. + pub fn fail(&mut self, err: &syn::Error) { + let ce = err.to_compile_error(); + let checkpoint = std::mem::take(&mut self.checkpoint); + *self.out = quote!(#ce #checkpoint); + self.done = true; + } +} + +impl<'a> Drop for EmitGuard<'a> { + fn drop(&mut self) { + if !self.done { + // Safety net: early-returned without succeed/fail, + // emit the last checkpoint. + *self.out = self.checkpoint.clone(); + } + } +} + +impl Deref for EmitGuard<'_> { + type Target = TokenStream; + fn deref(&self) -> &Self::Target { + self.out + } +} +impl DerefMut for EmitGuard<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.out + } +} + +#[cfg(test)] +mod tests { + use super::*; + use internal_test_proc_macro::xtest; + #[xtest] + fn test_emit_guard_early() { + let mut input = quote!(0); + let mut emit = EmitGuard::new(&mut input); + emit.checkpoint::(quote!(1)); + *emit = quote!(2); + drop(emit); + assert_eq!(input.to_string(), quote!(1).to_string()); + } + #[xtest] + fn test_emit_guard_success() { + let mut input = quote!(0); + let mut emit = EmitGuard::new(&mut input); + emit.succeed::(quote!(1)); + drop(emit); + assert_eq!(input.to_string(), quote!(1).to_string()); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/util/mod.rs b/crates/bevy_auto_plugin_shared/src/util/mod.rs index 5e2d3de2..5bce4994 100644 --- a/crates/bevy_auto_plugin_shared/src/util/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/util/mod.rs @@ -1,2 +1,3 @@ mod after_drop; +pub mod emit_guard; pub mod macros; From bd9534d537c21e45086b855265866ec2f84c7d1d Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 00:01:45 -0400 Subject: [PATCH 073/162] refactor: remove dead code after drop and emit guard --- .../src/util/after_drop.rs | 50 -------- .../src/util/emit_guard.rs | 117 ------------------ .../bevy_auto_plugin_shared/src/util/mod.rs | 2 - 3 files changed, 169 deletions(-) delete mode 100644 crates/bevy_auto_plugin_shared/src/util/after_drop.rs delete mode 100644 crates/bevy_auto_plugin_shared/src/util/emit_guard.rs diff --git a/crates/bevy_auto_plugin_shared/src/util/after_drop.rs b/crates/bevy_auto_plugin_shared/src/util/after_drop.rs deleted file mode 100644 index 5d8b69b8..00000000 --- a/crates/bevy_auto_plugin_shared/src/util/after_drop.rs +++ /dev/null @@ -1,50 +0,0 @@ -#![allow(dead_code)] -use std::ops::{Deref, DerefMut}; - -pub struct AfterDrop<'a, T, F: FnOnce(&'a mut T)> { - target: Option<&'a mut T>, - on_drop: Option, -} - -impl<'a, T, F: FnOnce(&'a mut T)> AfterDrop<'a, T, F> { - pub fn new(target: &'a mut T, on_drop: F) -> Self { - Self { - target: Some(target), - on_drop: Some(on_drop), - } - } -} - -impl<'a, T, F: FnOnce(&'a mut T)> Deref for AfterDrop<'a, T, F> { - type Target = T; - fn deref(&self) -> &T { - self.target.as_deref().unwrap() - } -} -impl<'a, T, F: FnOnce(&'a mut T)> DerefMut for AfterDrop<'a, T, F> { - fn deref_mut(&mut self) -> &mut T { - self.target.as_deref_mut().unwrap() - } -} - -impl<'a, T, F: FnOnce(&'a mut T)> Drop for AfterDrop<'a, T, F> { - fn drop(&mut self) { - if let (Some(t), Some(f)) = (self.target.take(), self.on_drop.take()) { - f(t); - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use internal_test_proc_macro::xtest; - #[xtest] - fn test_after_drop() { - let mut x = 0; - let mut y = AfterDrop::new(&mut x, |x| *x = 1); - *y = 2; - drop(y); - assert_eq!(x, 1); - } -} diff --git a/crates/bevy_auto_plugin_shared/src/util/emit_guard.rs b/crates/bevy_auto_plugin_shared/src/util/emit_guard.rs deleted file mode 100644 index 06a61045..00000000 --- a/crates/bevy_auto_plugin_shared/src/util/emit_guard.rs +++ /dev/null @@ -1,117 +0,0 @@ -use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; -use std::ops::{Deref, DerefMut}; - -/** Example usage: -pub fn my_attr(_attr: TokenStream, mut input: TokenStream) -> TokenStream { - let mut emit = EmitGuard::new(&mut input); - - // Parse from the original snapshot - let mut item: Item = match syn::parse2(emit.snapshot().clone()) { - Ok(it) => it, - Err(e) => return { emit.fail(e); input }, - }; - - // Stage 1: scrub helper attributes - scrub_helpers(&mut item)?; - emit.checkpoint_item(&item); // helpers removed → safe checkpoint - - // Stage 2: other transforms (can add more checkpoints between steps) - transform_x(&mut item)?; - // emit.checkpoint_item(&item); - - // Done - emit.succeed(item); - input -} -*/ -#[derive(Debug)] -pub struct EmitGuard<'a> { - out: &'a mut TokenStream, - original: TokenStream, - checkpoint: TokenStream, - done: bool, -} - -impl<'a> EmitGuard<'a> { - pub fn new(out: &'a mut TokenStream) -> Self { - let original = out.clone(); - Self { - out, - checkpoint: original.clone(), - original, - done: false, - } - } - - /// Read-only view of the original tokens for parsing. - pub fn snapshot(&self) -> &TokenStream { - &self.original - } - - /// Save a checkpoint from an AST state. - pub fn checkpoint(&mut self, item: impl Into) { - let item = item.into(); - self.checkpoint = quote!(#item); - } - - /// Finish successfully with a final AST. - pub fn succeed(&mut self, item: impl Into) { - let item = item.into(); - *self.out = quote!(#item); - self.done = true; - } - - /// Finish with an error, emitting compile_error! + last checkpoint. - pub fn fail(&mut self, err: &syn::Error) { - let ce = err.to_compile_error(); - let checkpoint = std::mem::take(&mut self.checkpoint); - *self.out = quote!(#ce #checkpoint); - self.done = true; - } -} - -impl<'a> Drop for EmitGuard<'a> { - fn drop(&mut self) { - if !self.done { - // Safety net: early-returned without succeed/fail, - // emit the last checkpoint. - *self.out = self.checkpoint.clone(); - } - } -} - -impl Deref for EmitGuard<'_> { - type Target = TokenStream; - fn deref(&self) -> &Self::Target { - self.out - } -} -impl DerefMut for EmitGuard<'_> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.out - } -} - -#[cfg(test)] -mod tests { - use super::*; - use internal_test_proc_macro::xtest; - #[xtest] - fn test_emit_guard_early() { - let mut input = quote!(0); - let mut emit = EmitGuard::new(&mut input); - emit.checkpoint::(quote!(1)); - *emit = quote!(2); - drop(emit); - assert_eq!(input.to_string(), quote!(1).to_string()); - } - #[xtest] - fn test_emit_guard_success() { - let mut input = quote!(0); - let mut emit = EmitGuard::new(&mut input); - emit.succeed::(quote!(1)); - drop(emit); - assert_eq!(input.to_string(), quote!(1).to_string()); - } -} diff --git a/crates/bevy_auto_plugin_shared/src/util/mod.rs b/crates/bevy_auto_plugin_shared/src/util/mod.rs index 5bce4994..eda363d6 100644 --- a/crates/bevy_auto_plugin_shared/src/util/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/util/mod.rs @@ -1,3 +1 @@ -mod after_drop; -pub mod emit_guard; pub mod macros; From 8dce9d1c99d1f0f59c603c7d04808fadb3dccefb Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 00:06:35 -0400 Subject: [PATCH 074/162] chore(docs): remove na comment --- crates/bevy_auto_plugin_shared/src/macro_api/q.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs index 5b6f5bd1..0185ab61 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs @@ -32,7 +32,6 @@ where T: ItemAttributeInput, { fn to_tokens(&self, tokens: &mut TokenStream) { - // TODO: this mutates item which is already emitted ToTokensWithAppParam::to_tokens(self, tokens, &self.app_param); } } From 21d0e223562ae8163953944d9e8269591eee86cd Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 00:27:59 -0400 Subject: [PATCH 075/162] refactor: simplify argument inflation logic and improve token handling --- .../actions/auto_configure_system_set.rs | 68 +++++++++++++++---- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 5d50e555..7192f258 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -154,18 +154,41 @@ fn output( } impl ToTokensWithAppParam for QConfigureSystemSet { + // TODO: it would prob make more sense to return the token stream instead of inserting back into args + // but then that makes no-op default impl look weird. Would we return ItemInput regardless? + // or maybe we require a &mut TokenStream to be passed in and we mutate it fn scrub_item(&mut self) -> syn::Result<()> { - let mut input_ts = self.args.input_item.to_token_stream(); + let input_ts = self.args.input_item.to_token_stream(); check_strip_helpers(input_ts.clone(), &mut self.args.args.base)?; - args_with_plugin_from_args_input(&mut self.args.args.base, &mut input_ts)?; + let (args, input_ts) = + inflate_args_with_plugin_from_input(self.args.args.base.clone(), input_ts)? + .into_tuple(); + self.args.args.base = args; self.args.input_item = InputItem::Tokens(input_ts); Ok(()) } fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + let args = self.args.args.base.clone(); + // checks if we need to inflate args + let inflated_args = if args.inner.is_none() { + let (inflated_args, _) = match inflate_args_with_plugin_from_input( + args.clone(), + self.args.input_item.to_token_stream(), + ) { + Ok(res) => res.into_tuple(), + Err(err) => { + tokens.extend(err.to_compile_error()); + return; + } + }; + inflated_args + } else { + args + }; let generics = self.args.args.generics(); for concrete_path in self.args.concrete_paths() { tokens.extend(output( - &self.args.args.base, + &inflated_args, app_param, &concrete_path, !generics.is_empty(), @@ -209,15 +232,28 @@ pub fn args_from_attr_input( ) -> syn::Result { let mut args = syn::parse2::(attr)?; check_strip_helpers(input.clone(), &mut args)?; - args_with_plugin_from_args_input(&mut args, input)?; - Ok(args) + let output = inflate_args_with_plugin_from_input(args, input.clone())?; + *input = output.scrubbed_tokens; + Ok(output.inflated_args) +} + +#[derive(Debug)] +pub struct InflateArgsOutput { + scrubbed_tokens: TokenStream, + inflated_args: ConfigureSystemSetArgs, } -pub fn args_with_plugin_from_args_input( - args: &mut ConfigureSystemSetArgs, +impl InflateArgsOutput { + pub fn into_tuple(self) -> (ConfigureSystemSetArgs, TokenStream) { + (self.inflated_args, self.scrubbed_tokens) + } +} + +pub fn inflate_args_with_plugin_from_input( + mut args: ConfigureSystemSetArgs, // this is the only way we can strip out non-derive based attribute helpers - input: &mut TokenStream, -) -> syn::Result<()> { + mut input: TokenStream, +) -> syn::Result { fn resolve_ident(item: &Item) -> syn::Result<&Ident> { // TODO: remove and use ident from higher level resolve_ident_from_struct_or_enum(item) @@ -239,17 +275,20 @@ pub fn args_with_plugin_from_args_input( // 3) if args._strip_helpers { // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with - scrub.write_back(input)?; + scrub.write_back(&mut input)?; } else { // Check if we have errors to print and if so, strip helpers from the item // Otherwise, maintain helpers for the next attribute to process - scrub.write_if_errors_with_scrubbed_item(input)?; + scrub.write_if_errors_with_scrubbed_item(&mut input)?; } // 4) If it's a struct, there are no entries to compute let data_enum = match scrub.item { Item::Struct(_) => { - return Ok(()); + return Ok(InflateArgsOutput { + inflated_args: args, + scrubbed_tokens: input, + }); } Item::Enum(ref en) => en, _ => unreachable!("resolve_ident_from_struct_or_enum guarantees struct|enum"), @@ -389,7 +428,10 @@ pub fn args_with_plugin_from_args_input( // 8) Store into args and return args.inner = Some(ConfigureSystemSetArgsInner { entries }); - Ok(()) + Ok(InflateArgsOutput { + inflated_args: args, + scrubbed_tokens: input, + }) } #[cfg(test)] From bf0d7c34ad0b988718f4c4bdc8ad23b3d660dc15 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 14:57:39 -0400 Subject: [PATCH 076/162] refactor: rename `inflate_args_with_plugin_from_input` to `inflate_args_from_input` --- .../actions/auto_configure_system_set.rs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 7192f258..939c189d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -161,8 +161,7 @@ impl ToTokensWithAppParam for QConfigureSystemSet { let input_ts = self.args.input_item.to_token_stream(); check_strip_helpers(input_ts.clone(), &mut self.args.args.base)?; let (args, input_ts) = - inflate_args_with_plugin_from_input(self.args.args.base.clone(), input_ts)? - .into_tuple(); + inflate_args_from_input(self.args.args.base.clone(), input_ts)?.into_tuple(); self.args.args.base = args; self.args.input_item = InputItem::Tokens(input_ts); Ok(()) @@ -171,16 +170,15 @@ impl ToTokensWithAppParam for QConfigureSystemSet { let args = self.args.args.base.clone(); // checks if we need to inflate args let inflated_args = if args.inner.is_none() { - let (inflated_args, _) = match inflate_args_with_plugin_from_input( - args.clone(), - self.args.input_item.to_token_stream(), - ) { - Ok(res) => res.into_tuple(), - Err(err) => { - tokens.extend(err.to_compile_error()); - return; - } - }; + let (inflated_args, _) = + match inflate_args_from_input(args.clone(), self.args.input_item.to_token_stream()) + { + Ok(res) => res.into_tuple(), + Err(err) => { + tokens.extend(err.to_compile_error()); + return; + } + }; inflated_args } else { args @@ -232,7 +230,7 @@ pub fn args_from_attr_input( ) -> syn::Result { let mut args = syn::parse2::(attr)?; check_strip_helpers(input.clone(), &mut args)?; - let output = inflate_args_with_plugin_from_input(args, input.clone())?; + let output = inflate_args_from_input(args, input.clone())?; *input = output.scrubbed_tokens; Ok(output.inflated_args) } @@ -249,7 +247,7 @@ impl InflateArgsOutput { } } -pub fn inflate_args_with_plugin_from_input( +pub fn inflate_args_from_input( mut args: ConfigureSystemSetArgs, // this is the only way we can strip out non-derive based attribute helpers mut input: TokenStream, From 7ca101a07c2caccff85b7e95fb476856e63c427c Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 15:01:36 -0400 Subject: [PATCH 077/162] refactor: remove dead code --- .../src/syntax/parse/from_meta.rs | 94 ------------------- .../src/syntax/parse/mod.rs | 1 - 2 files changed, 95 deletions(-) delete mode 100644 crates/bevy_auto_plugin_shared/src/syntax/parse/from_meta.rs diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/from_meta.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/from_meta.rs deleted file mode 100644 index 71bdec7e..00000000 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/from_meta.rs +++ /dev/null @@ -1,94 +0,0 @@ -use darling::FromMeta; -use syn::Meta; - -#[allow(dead_code)] -pub trait FromMetaExt: FromMeta { - fn from_meta_ext(meta: &Meta) -> darling::Result; -} - -impl FromMetaExt for T { - /// allows us to call from_meta on items that are just a path (no args) - fn from_meta_ext(meta: &Meta) -> darling::Result { - match meta { - Meta::Path(_) => T::from_list(&[]), - _ => T::from_meta(meta), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use internal_test_proc_macro::xtest; - use syn::{Attribute, parse_quote}; - - #[derive(FromMeta, Debug, Default, PartialEq)] - #[darling(default)] - struct TestList { - a: Option, - b: Option, - } - - #[derive(FromMeta, Debug, Default, PartialEq)] - #[darling(default)] - struct TestSingle(Option); - - #[xtest] - #[should_panic(expected = "Unexpected meta-item format `word`")] - fn test_from_meta_word_panic() { - let attr: Attribute = parse_quote!(#[foo]); - match TestList::from_meta(&attr.meta) { - Ok(_) => {} - Err(e) => panic!("{e}"), - } - } - - #[xtest] - fn test_from_meta_ext_word() { - let attr: Attribute = parse_quote!(#[foo]); - assert_eq!( - TestList::from_meta_ext(&attr.meta).ok(), - Some(TestList::default()) - ); - } - - #[xtest] - fn test_from_meta_ext_list() { - let attr: Attribute = parse_quote!(#[foo(a = "bar")]); - assert_eq!( - TestList::from_meta_ext(&attr.meta).ok(), - Some(TestList { - a: Some("bar".to_string()), - ..Default::default() - }) - ); - let attr: Attribute = parse_quote!(#[foo(a = "bar", b = "baz")]); - assert_eq!( - TestList::from_meta_ext(&attr.meta).ok(), - Some(TestList { - a: Some("bar".to_string()), - b: Some("baz".to_string()), - }) - ); - } - - #[xtest] - // Meta::Path on tuple struct unsupported - #[should_panic(expected = "Unexpected meta-item format `word`")] - fn test_from_meta_ext_name_value_empty() { - let attr: Attribute = parse_quote!(#[foo]); - match TestList::from_meta(&attr.meta) { - Ok(_) => {} - Err(e) => panic!("{e}"), - } - } - - #[xtest] - fn test_from_meta_ext_name_value() { - let attr: Attribute = parse_quote!(#[foo = "bar"]); - assert_eq!( - TestSingle::from_meta_ext(&attr.meta).ok(), - Some(TestSingle(Some("bar".to_string()))) - ); - } -} diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/mod.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/mod.rs index 8134199e..0ac05958 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/mod.rs @@ -1,3 +1,2 @@ -pub mod from_meta; pub mod item; pub mod scrub_helpers; From 2e0f8b3c79d4d744da8726b2d196ead22d6afd7b Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 15:50:00 -0400 Subject: [PATCH 078/162] refactor: add `get_ident` and `ident` methods to `ItemAttrsExt` trait --- .../src/syntax/extensions/item.rs | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/syntax/extensions/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/extensions/item.rs index 1fe3b06e..f4e50f58 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/extensions/item.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/extensions/item.rs @@ -1,5 +1,6 @@ #![allow(dead_code)] +use quote::ToTokens; use syn::{Attribute, Item}; use thiserror::Error; @@ -10,6 +11,14 @@ pub enum TakeAndPutAttrsError { } pub trait ItemAttrsExt { + fn get_ident(&self) -> Option<&syn::Ident>; + fn ident(&self) -> syn::Result<&syn::Ident> + where + Self: ToTokens, + { + self.get_ident() + .ok_or_else(|| syn::Error::new_spanned(self, "Item does not have ident")) + } fn clone_attrs(&self) -> Option>; fn attrs(&self) -> Option<&[Attribute]>; fn attrs_mut(&mut self) -> Result<&mut Vec, TakeAndPutAttrsError>; @@ -18,6 +27,28 @@ pub trait ItemAttrsExt { } impl ItemAttrsExt for Item { + fn get_ident(&self) -> Option<&syn::Ident> { + match self { + Item::Const(item) => Some(&item.ident), + Item::Enum(item) => Some(&item.ident), + Item::ExternCrate(item) => Some(&item.ident), + Item::Fn(item) => Some(&item.sig.ident), + Item::ForeignMod(_) => None, + Item::Impl(_) => None, + Item::Macro(item) => item.ident.as_ref(), + Item::Mod(item) => Some(&item.ident), + Item::Static(item) => Some(&item.ident), + Item::Struct(item) => Some(&item.ident), + Item::Trait(item) => Some(&item.ident), + Item::TraitAlias(item) => Some(&item.ident), + Item::Type(item) => Some(&item.ident), + Item::Union(item) => Some(&item.ident), + // TODO: implement + Item::Use(_) => None, + Item::Verbatim(_) => None, + _ => None, + } + } fn clone_attrs(&self) -> Option> { Some(match self { Item::Const(i) => i.attrs.clone(), From 6fcdc8c999f7eea7f27f6f0edfc464378c3b01a9 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 15:50:27 -0400 Subject: [PATCH 079/162] refactor: utilize `get_ident` method and simplify `ident` handling in `InputItem` --- .../src/macro_api/input_item.rs | 31 ++++++------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs index c6c35b38..6e18fa67 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs @@ -1,6 +1,8 @@ +use crate::syntax::extensions::item::ItemAttrsExt; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; use syn::parse2; +use syn::spanned::Spanned; #[derive(Debug, Clone)] pub enum InputItem { @@ -37,30 +39,15 @@ impl InputItem { _ => unreachable!(), }) } - // TODO: use instead of analysis/item helpers? - #[allow(dead_code)] + // TODO: use instead of analysis/item helpers pub fn get_ident(&mut self) -> syn::Result> { - use syn::Item; let item = self.ensure_ast()?; - Ok(match item { - Item::Const(item) => Some(&item.ident), - Item::Enum(item) => Some(&item.ident), - Item::ExternCrate(item) => Some(&item.ident), - Item::Fn(item) => Some(&item.sig.ident), - Item::ForeignMod(_) => None, - Item::Impl(_) => None, - Item::Macro(item) => item.ident.as_ref(), - Item::Mod(item) => Some(&item.ident), - Item::Static(item) => Some(&item.ident), - Item::Struct(item) => Some(&item.ident), - Item::Trait(item) => Some(&item.ident), - Item::TraitAlias(item) => Some(&item.ident), - Item::Type(item) => Some(&item.ident), - Item::Union(item) => Some(&item.ident), - // TODO: implement - Item::Use(_) => None, - Item::Verbatim(_) => None, - _ => None, + Ok(item.get_ident()) + } + pub fn ident(&mut self) -> syn::Result<&syn::Ident> { + self.ensure_ast().and_then(|item| { + item.get_ident() + .ok_or_else(|| syn::Error::new(item.span(), "expected item to have an ident")) }) } pub fn map_ast(&mut self, f: F) -> syn::Result<()> From b6d7430fdea3fcd93163238cf8c21f2be9f06acb Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 15:50:38 -0400 Subject: [PATCH 080/162] refactor: simplify attribute handling and streamline `inflate_args_from_input` logic --- .../actions/auto_configure_system_set.rs | 132 ++++++++---------- .../src/syntax/parse/item.rs | 10 +- 2 files changed, 61 insertions(+), 81 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 939c189d..e10c8664 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,8 +1,8 @@ use crate::macro_api::prelude::*; use crate::macro_api::schedule_config::{ScheduleConfigArgs, ScheduleWithScheduleConfigArgs}; -use crate::syntax::analysis::item::resolve_ident_from_struct_or_enum; use crate::syntax::ast::flag::Flag; -use crate::syntax::parse::item::ts_item_has_attr; +use crate::syntax::extensions::item::ItemAttrsExt; +use crate::syntax::parse::item::item_has_attr; use crate::syntax::parse::scrub_helpers::{AttrSite, scrub_helpers_and_ident_with_filter}; use darling::FromMeta; use proc_macro2::{Ident, TokenStream}; @@ -158,12 +158,14 @@ impl ToTokensWithAppParam for QConfigureSystemSet { // but then that makes no-op default impl look weird. Would we return ItemInput regardless? // or maybe we require a &mut TokenStream to be passed in and we mutate it fn scrub_item(&mut self) -> syn::Result<()> { - let input_ts = self.args.input_item.to_token_stream(); - check_strip_helpers(input_ts.clone(), &mut self.args.args.base)?; - let (args, input_ts) = - inflate_args_from_input(self.args.args.base.clone(), input_ts)?.into_tuple(); - self.args.args.base = args; - self.args.input_item = InputItem::Tokens(input_ts); + let input_item = &mut self.args.input_item; + let args = &mut self.args.args.base; + let item = input_item.ensure_ast()?; + check_strip_helpers(item, args)?; + let input = input_item.to_token_stream(); + let res = inflate_args_from_input(args.clone(), input)?; + *args = res.inflated_args; + *input_item = InputItem::Tokens(res.scrubbed_tokens); Ok(()) } fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { @@ -198,7 +200,7 @@ impl ToTokensWithAppParam for QConfigureSystemSet { impl ToTokens for QQConfigureSystemSet { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); - // TODO: scrub input + todo!("not implemented"); // TODO: cleanup args.extend( self.args @@ -215,8 +217,8 @@ impl ToTokens for QQConfigureSystemSet { } /// HACK - if the item doesn't have anymore `auto_configure_system_set` - set a flag to strip out the helper attributes -fn check_strip_helpers(input: TokenStream, args: &mut ConfigureSystemSetArgs) -> syn::Result<()> { - if !ts_item_has_attr(input, &parse_quote!(auto_configure_system_set))? { +fn check_strip_helpers(item: &Item, args: &mut ConfigureSystemSetArgs) -> syn::Result<()> { + if !item_has_attr(item, &parse_quote!(auto_configure_system_set))? { args._strip_helpers = true; } Ok(()) @@ -225,14 +227,12 @@ fn check_strip_helpers(input: TokenStream, args: &mut ConfigureSystemSetArgs) -> #[cfg(test)] pub fn args_from_attr_input( attr: TokenStream, - // this is the only way we can strip out non-derive based attribute helpers - input: &mut TokenStream, -) -> syn::Result { + input: TokenStream, +) -> syn::Result { let mut args = syn::parse2::(attr)?; - check_strip_helpers(input.clone(), &mut args)?; - let output = inflate_args_from_input(args, input.clone())?; - *input = output.scrubbed_tokens; - Ok(output.inflated_args) + let mut input_item = InputItem::Tokens(input); + check_strip_helpers(input_item.ensure_ast()?, &mut args)?; + inflate_args_from_input(args, input_item.to_token_stream()) } #[derive(Debug)] @@ -249,22 +249,22 @@ impl InflateArgsOutput { pub fn inflate_args_from_input( mut args: ConfigureSystemSetArgs, - // this is the only way we can strip out non-derive based attribute helpers - mut input: TokenStream, + input: TokenStream, ) -> syn::Result { fn resolve_ident(item: &Item) -> syn::Result<&Ident> { - // TODO: remove and use ident from higher level - resolve_ident_from_struct_or_enum(item) - .map_err(|err| syn::Error::new(item.span(), format!("failed to resolve ident: {err}"))) + // TODO: remove and use ident from higher level? + item.ident() } fn is_allowed_helper(site: &AttrSite, attr: &Attribute) -> bool { is_config_helper(attr) && matches!(site, AttrSite::Variant { .. }) } + let mut scrubbed_tokens = input.clone(); + // 2) Scrub helpers from the item and resolve ident let scrub = scrub_helpers_and_ident_with_filter( - input.clone(), + input, is_allowed_helper, is_config_helper, resolve_ident, @@ -273,11 +273,11 @@ pub fn inflate_args_from_input( // 3) if args._strip_helpers { // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with - scrub.write_back(&mut input)?; + scrub.write_back(&mut scrubbed_tokens)?; } else { // Check if we have errors to print and if so, strip helpers from the item // Otherwise, maintain helpers for the next attribute to process - scrub.write_if_errors_with_scrubbed_item(&mut input)?; + scrub.write_if_errors_with_scrubbed_item(&mut scrubbed_tokens)?; } // 4) If it's a struct, there are no entries to compute @@ -285,7 +285,7 @@ pub fn inflate_args_from_input( Item::Struct(_) => { return Ok(InflateArgsOutput { inflated_args: args, - scrubbed_tokens: input, + scrubbed_tokens, }); } Item::Enum(ref en) => en, @@ -428,7 +428,7 @@ pub fn inflate_args_from_input( args.inner = Some(ConfigureSystemSetArgsInner { entries }); Ok(InflateArgsOutput { inflated_args: args, - scrubbed_tokens: input, + scrubbed_tokens, }) } @@ -440,24 +440,12 @@ mod tests { fn ident_and_args_from_attr_input( attr: TokenStream, - mut input: TokenStream, - ) -> Result<(Ident, ConfigureSystemSetArgs), syn::Error> { - let item = parse2::(input.clone())?; - let ident = resolve_ident_from_struct_or_enum(&item).map_err(|err| { - syn::Error::new(item.span(), format!("failed to resolve ident: {err}")) - })?; - args_from_attr_input(attr, &mut input).map(|args| (ident.clone(), args)) - } - - fn ident_and_args_from_attr_mut_input( - attr: TokenStream, - input: &mut TokenStream, + input: TokenStream, ) -> Result<(Ident, ConfigureSystemSetArgs), syn::Error> { - let item = parse2::(input.clone())?; - let ident = resolve_ident_from_struct_or_enum(&item).map_err(|err| { - syn::Error::new(item.span(), format!("failed to resolve ident: {err}")) - })?; - args_from_attr_input(attr, input).map(|args| (ident.clone(), args)) + let mut input_item = InputItem::Tokens(input); + let ident = input_item.ident()?.clone(); + let inflated_args = args_from_attr_input(attr, input_item.to_token_stream())?.inflated_args; + Ok((ident, inflated_args)) } mod test_struct { @@ -612,7 +600,7 @@ mod tests { #[xtest] fn test_helper() -> syn::Result<()> { - let (_ident, args) = ident_and_args_from_attr_input( + let inflated_args = args_from_attr_input( quote! { group = A, schedule = Update, @@ -625,9 +613,10 @@ mod tests { B, } }, - )?; + )? + .inflated_args; assert_eq!( - args, + inflated_args, ConfigureSystemSetArgs { schedule_config: ScheduleWithScheduleConfigArgs { schedule: parse_quote!(Update), @@ -663,8 +652,12 @@ mod tests { } #[xtest] - fn test_helper_removed_from_ts() { - let mut input = quote! { + fn test_helper_removed_from_ts() -> syn::Result<()> { + let attr = quote! { + group = A, + schedule = Update, + }; + let input = quote! { enum Foo { #[auto_configure_system_set_config(group = A)] A, @@ -672,15 +665,9 @@ mod tests { B, } }; - let _ = ident_and_args_from_attr_mut_input( - quote! { - group = A, - schedule = Update, - }, - &mut input, - ); + let scrubbed_input = args_from_attr_input(attr, input)?.scrubbed_tokens; assert_eq!( - input.to_string(), + scrubbed_input.to_string(), quote! { enum Foo { A, @@ -689,21 +676,21 @@ mod tests { } .to_string() ); + Ok(()) } #[xtest] fn test_conflict_outer() { - let mut input = quote! { - enum Foo { - A, - } - }; - let res = ident_and_args_from_attr_mut_input( + let res = ident_and_args_from_attr_input( quote! { schedule = Update, chain, chain_ignore_deferred }, - &mut input, + quote! { + enum Foo { + A, + } + }, ) .map_err(|e| e.to_string()); @@ -712,17 +699,16 @@ mod tests { #[xtest] fn test_conflict_entries() { - let mut input = quote! { - enum Foo { - #[auto_configure_system_set_config(chain, chain_ignore_deferred)] - A, - } - }; - let res = ident_and_args_from_attr_mut_input( + let res = ident_and_args_from_attr_input( quote! { schedule = Update, }, - &mut input, + quote! { + enum Foo { + #[auto_configure_system_set_config(chain, chain_ignore_deferred)] + A, + } + }, ) .map_err(|e| e.to_string()); diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs index 09e3554a..ad5fef83 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs @@ -1,14 +1,8 @@ use crate::syntax::extensions::item::ItemAttrsExt; use crate::syntax::extensions::path::PathExt; -use proc_macro2::TokenStream; -use syn::{Attribute, Item, parse2}; +use syn::{Attribute, Item}; -pub fn ts_item_has_attr(input: TokenStream, path: &syn::Path) -> syn::Result { - let item = parse2::(input)?; - item_has_attr(item, path) -} - -pub fn item_has_attr(item: Item, path: &syn::Path) -> syn::Result { +pub fn item_has_attr(item: &Item, path: &syn::Path) -> syn::Result { Ok(has_attr(item.attrs().unwrap_or_default(), path)) } From 570965dd8ec62a5a9e070c7b60596dcb55f281ab Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:13:09 -0400 Subject: [PATCH 081/162] refactor: rename `wrap` to `wrap_as_attr` --- .../src/macro_api/attributes/actions/auto_add_message.rs | 2 +- .../src/macro_api/attributes/actions/auto_add_observer.rs | 2 +- .../src/macro_api/attributes/actions/auto_add_plugin.rs | 2 +- .../src/macro_api/attributes/actions/auto_add_system.rs | 2 +- .../macro_api/attributes/actions/auto_configure_system_set.rs | 2 +- .../src/macro_api/attributes/actions/auto_init_resource.rs | 2 +- .../src/macro_api/attributes/actions/auto_init_state.rs | 2 +- .../src/macro_api/attributes/actions/auto_init_sub_state.rs | 2 +- .../src/macro_api/attributes/actions/auto_insert_resource.rs | 2 +- .../src/macro_api/attributes/actions/auto_name.rs | 2 +- .../macro_api/attributes/actions/auto_register_state_type.rs | 2 +- .../src/macro_api/attributes/actions/auto_register_type.rs | 2 +- crates/bevy_auto_plugin_shared/src/macro_api/qq.rs | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index fa740722..0b2ff857 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -32,6 +32,6 @@ impl ToTokens for QQAddMessage { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 8658ac56..408dccb8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -32,6 +32,6 @@ impl ToTokens for QQAddObserver { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index f67db23a..1449f37b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -46,6 +46,6 @@ impl ToTokens for QQAddPlugin { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index f78e66d4..f10bd2bc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -46,6 +46,6 @@ impl ToTokens for QQAddSystem { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index e10c8664..dbb9e10d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -212,7 +212,7 @@ impl ToTokens for QQConfigureSystemSet { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index bc516ac1..50d4e2c7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -35,6 +35,6 @@ impl ToTokens for QQInitResource { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index 0a2fdc7a..6407250a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -31,6 +31,6 @@ impl ToTokens for QQInitState { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index b6b880fd..032efe9a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -31,6 +31,6 @@ impl ToTokens for QQInitSubState { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 0e36d11d..8bbed835 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -40,6 +40,6 @@ impl ToTokens for QQInsertResource { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index e17475b4..f778b9ad 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -55,6 +55,6 @@ impl ToTokens for QQName { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index ea276718..17e294bb 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -36,6 +36,6 @@ impl ToTokens for QQRegisterStateType { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index cad434cc..cf641a7a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -33,6 +33,6 @@ impl ToTokens for QQRegisterType { tokens.extend(quote! { #(#args),* }); - *tokens = self.wrap(tokens); + *tokens = self.wrap_as_attr(tokens); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 419c8d87..387e2b0d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -22,7 +22,7 @@ impl QQ, R>> where T: MacroPathProvider, { - pub(crate) fn wrap(&self, args: &TokenStream) -> TokenStream { + pub(crate) fn wrap_as_attr(&self, args: &TokenStream) -> TokenStream { let macro_path = T::macro_path(self.args.context()); quote! { #[#macro_path( #args )] } } From cc9fa4a9bd63b4e53283af5c19f1b86113818224 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:13:23 -0400 Subject: [PATCH 082/162] refactor: handle empty `args` in `wrap_as_attr` method --- crates/bevy_auto_plugin_shared/src/macro_api/qq.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs index 387e2b0d..c8e431c1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs @@ -24,7 +24,11 @@ where { pub(crate) fn wrap_as_attr(&self, args: &TokenStream) -> TokenStream { let macro_path = T::macro_path(self.args.context()); - quote! { #[#macro_path( #args )] } + if args.is_empty() { + quote! { #[#macro_path] } + } else { + quote! { #[#macro_path( #args )] } + } } } From c6d72e60fa449364773f8aa8d717a1106fc6fb08 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:37:31 -0400 Subject: [PATCH 083/162] refactor: rename `Q` with `AppMutationEmitter` and update associated traits --- .../src/__private/expand/attr/mod.rs | 10 +++-- .../src/macro_api/app_mutation_emitter.rs | 42 +++++++++++++++++++ .../attributes/actions/auto_add_message.rs | 6 +-- .../attributes/actions/auto_add_observer.rs | 6 +-- .../attributes/actions/auto_add_plugin.rs | 6 +-- .../attributes/actions/auto_add_system.rs | 6 +-- .../actions/auto_configure_system_set.rs | 6 +-- .../attributes/actions/auto_init_resource.rs | 8 ++-- .../attributes/actions/auto_init_state.rs | 6 +-- .../attributes/actions/auto_init_sub_state.rs | 6 +-- .../actions/auto_insert_resource.rs | 6 +-- .../macro_api/attributes/actions/auto_name.rs | 6 +-- .../actions/auto_register_state_type.rs | 6 +-- .../attributes/actions/auto_register_type.rs | 6 +-- .../attributes/actions/auto_run_on_build.rs | 6 +-- .../src/macro_api/mod.rs | 4 +- .../src/macro_api/q.rs | 37 ---------------- 17 files changed, 90 insertions(+), 83 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/app_mutation_emitter.rs delete mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/q.rs diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 1b5e4a7d..3f89c0f1 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -7,7 +7,9 @@ use quote::{ToTokens, format_ident, quote}; pub mod auto_bind_plugin; pub mod auto_plugin; -fn body(body: impl Fn(MacroStream) -> MacroStream) -> impl Fn(Q) -> syn::Result +fn body( + body: impl Fn(MacroStream) -> MacroStream, +) -> impl Fn(AppMutationEmitter) -> syn::Result where T: ItemAttributeArgs + ItemAttributeParse @@ -16,7 +18,7 @@ where + ItemAttributeContext + ItemAttributeUniqueIdent + ItemAttributePlugin, - Q: ToTokens, + AppMutationEmitter: ToTokens, { move |params| -> syn::Result { let ident = params.args.target().to_token_stream(); @@ -47,14 +49,14 @@ where + ItemAttributeUniqueIdent + ItemAttributeContext + ItemAttributePlugin, - Q: ToTokens + ToTokensWithAppParam, + AppMutationEmitter: ToTokens + EmitAppMutationTokens, { let args = ok_or_emit_with!( T::from_attr_input_with_context(attr, input.clone(), Context::default()), input ); let body_fn = body(|body| quote! { #body }); - let mut q = Q::from_args(args); + let mut q = AppMutationEmitter::from_args(args); let scrubbed_input = { ok_or_emit_with!(q.scrub_item(), q.args.input_item()); q.args.input_item().to_token_stream() diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/app_mutation_emitter.rs b/crates/bevy_auto_plugin_shared/src/macro_api/app_mutation_emitter.rs new file mode 100644 index 00000000..bad49128 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/app_mutation_emitter.rs @@ -0,0 +1,42 @@ +use crate::macro_api::prelude::*; +use proc_macro2::TokenStream; +use quote::{ToTokens, format_ident}; + +/// for codegen attaching to bevy app +#[derive(Debug, Clone)] +pub(crate) struct AppMutationEmitter { + pub(crate) args: T, + // TODO: maybe app params should just be part of another wrapper struct? + pub(crate) app_param: syn::Ident, +} + +impl AppMutationEmitter { + pub fn from_args(args: T) -> AppMutationEmitter { + AppMutationEmitter:: { + args, + app_param: format_ident!("app"), + } + } +} + +pub trait EmitAppMutationTokens { + fn scrub_item(&mut self) -> syn::Result<()> { + Ok(()) + } + fn to_app_mutation_token_stream(&self, app_param: &syn::Ident) -> TokenStream { + let mut tokens = TokenStream::new(); + self.to_app_mutation_tokens(&mut tokens, app_param); + tokens + } + fn to_app_mutation_tokens(&self, out: &mut TokenStream, app_param: &syn::Ident); +} + +impl ToTokens for AppMutationEmitter +where + Self: EmitAppMutationTokens, + T: ItemAttributeInput, +{ + fn to_tokens(&self, tokens: &mut TokenStream) { + EmitAppMutationTokens::to_app_mutation_tokens(self, tokens, &self.app_param) + } +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index 0b2ff857..812cfccd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -13,11 +13,11 @@ impl AttributeIdent for AddMessageArgs { pub type IaAddMessage = ItemAttribute, AllowStructOrEnum>; -pub type QAddMessage = Q; +pub type QAddMessage = AppMutationEmitter; pub type QQAddMessage = QQ; -impl ToTokensWithAppParam for QAddMessage { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QAddMessage { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.add_message::<#concrete_path>(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 408dccb8..f8c7818e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -13,11 +13,11 @@ impl AttributeIdent for AddObserverArgs { pub type IaAddObserver = ItemAttribute, AllowFn>; -pub type QAddObserver = Q; +pub type QAddObserver = AppMutationEmitter; pub type QQAddObserver = QQ; -impl ToTokensWithAppParam for QAddObserver { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QAddObserver { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.add_observer( #concrete_path ); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index 1449f37b..2daa0a13 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -17,11 +17,11 @@ impl AttributeIdent for AddPluginArgs { pub type IaAddPlugin = ItemAttribute, AllowStructOrEnum>; -pub type QAddPlugin = Q; +pub type QAddPlugin = AppMutationEmitter; pub type QQAddPlugin = QQ; -impl ToTokensWithAppParam for QAddPlugin { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QAddPlugin { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { if let Some(expr) = &self.args.args.base.init.expr { tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index f10bd2bc..42a11ce1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -17,11 +17,11 @@ impl AttributeIdent for AddSystemArgs { pub type IaAddSystem = ItemAttribute, AllowFn>; -pub type QAddSystem = Q; +pub type QAddSystem = AppMutationEmitter; pub type QQAddSystem = QQ; -impl ToTokensWithAppParam for QAddSystem { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QAddSystem { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let schedule = &self.args.args.base.schedule_config.schedule; let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); for concrete_path in self.args.concrete_paths() { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index dbb9e10d..d563ec77 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -95,7 +95,7 @@ pub type IaConfigureSystemSet = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QConfigureSystemSet = Q; +pub type QConfigureSystemSet = AppMutationEmitter; pub type QQConfigureSystemSet = QQ; fn output( @@ -153,7 +153,7 @@ fn output( tokens } -impl ToTokensWithAppParam for QConfigureSystemSet { +impl EmitAppMutationTokens for QConfigureSystemSet { // TODO: it would prob make more sense to return the token stream instead of inserting back into args // but then that makes no-op default impl look weird. Would we return ItemInput regardless? // or maybe we require a &mut TokenStream to be passed in and we mutate it @@ -168,7 +168,7 @@ impl ToTokensWithAppParam for QConfigureSystemSet { *input_item = InputItem::Tokens(res.scrubbed_tokens); Ok(()) } - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = self.args.args.base.clone(); // checks if we need to inflate args let inflated_args = if args.inner.is_none() { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 50d4e2c7..49cc2265 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -1,5 +1,5 @@ +use crate::macro_api::app_mutation_emitter::{AppMutationEmitter, EmitAppMutationTokens}; use crate::macro_api::prelude::*; -use crate::macro_api::q::{Q, ToTokensWithAppParam}; use darling::FromMeta; use proc_macro2::TokenStream; use quote::{ToTokens, quote}; @@ -16,11 +16,11 @@ pub type IaInitResource = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QInitResource = Q; +pub type QInitResource = AppMutationEmitter; pub type QQInitResource = QQ; -impl ToTokensWithAppParam for QInitResource { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QInitResource { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.init_resource::<#concrete_path>(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index 6407250a..d726dae0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -13,11 +13,11 @@ impl AttributeIdent for InitStateArgs { pub type IaInitState = ItemAttribute, AllowStructOrEnum>; -pub type QInitState = Q; +pub type QInitState = AppMutationEmitter; pub type QQInitState = QQ; -impl ToTokensWithAppParam for QInitState { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QInitState { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { #app_param.init_state::<#target>(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 032efe9a..65d2c8c0 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -13,11 +13,11 @@ impl AttributeIdent for InitSubStateArgs { pub type IaInitSubState = ItemAttribute, AllowStructOrEnum>; -pub type QInitSubState = Q; +pub type QInitSubState = AppMutationEmitter; pub type QQInitSubState = QQ; -impl ToTokensWithAppParam for QInitSubState { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QInitSubState { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { #app_param.add_sub_state::<#target>(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 8bbed835..154a6054 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -18,11 +18,11 @@ pub type IaInsertResource = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QInsertResource = Q; +pub type QInsertResource = AppMutationEmitter; pub type QQInsertResource = QQ; -impl ToTokensWithAppParam for QInsertResource { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QInsertResource { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let resource = &self.args.args.base.resource; for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index f778b9ad..7549e1a1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -16,11 +16,11 @@ impl AttributeIdent for NameArgs { pub type IaName = ItemAttribute, AllowStructOrEnum>; -pub type QName = Q; +pub type QName = AppMutationEmitter; pub type QQName = QQ; -impl ToTokensWithAppParam for QName { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QName { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args.base; for concrete_path in self.args.concrete_paths() { let name = args diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 17e294bb..f4d8a5df 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -15,11 +15,11 @@ pub type IaRegisterStateType = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QRegisterStateType = Q; +pub type QRegisterStateType = AppMutationEmitter; pub type QQRegisterStateType = QQ; -impl ToTokensWithAppParam for QRegisterStateType { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QRegisterStateType { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { let bevy_state = crate::__private::paths::state::root_path(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index cf641a7a..66957156 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -15,11 +15,11 @@ pub type IaRegisterType = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QRegisterType = Q; +pub type QRegisterType = AppMutationEmitter; pub type QQRegisterType = QQ; -impl ToTokensWithAppParam for QRegisterType { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QRegisterType { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.register_type::<#concrete_path>(); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index 17122609..04952606 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -13,11 +13,11 @@ impl AttributeIdent for RunOnBuildArgs { pub type IaRunOnBuild = ItemAttribute, AllowFn>; -pub type QRunOnBuild = Q; +pub type QRunOnBuild = AppMutationEmitter; pub type QQRunOnBuild = QQ; -impl ToTokensWithAppParam for QRunOnBuild { - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { +impl EmitAppMutationTokens for QRunOnBuild { + fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #concrete_path(#app_param); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 5d9a9d3b..c0672949 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -1,3 +1,4 @@ +mod app_mutation_emitter; mod attributes; mod composed; mod context; @@ -5,13 +6,13 @@ mod derives; mod input_item; mod macro_paths; mod mixins; -mod q; mod qq; mod rewrite_q; mod schedule_config; pub(crate) mod prelude { use super::*; + pub use app_mutation_emitter::*; pub use attributes::prelude::*; pub use composed::*; pub use context::*; @@ -19,7 +20,6 @@ pub(crate) mod prelude { pub use input_item::*; pub use macro_paths::*; pub use mixins::prelude::*; - pub use q::*; pub use qq::*; pub use rewrite_q::*; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/q.rs deleted file mode 100644 index 0185ab61..00000000 --- a/crates/bevy_auto_plugin_shared/src/macro_api/q.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::macro_api::prelude::*; -use proc_macro2::TokenStream; -use quote::{ToTokens, format_ident}; - -/// for codegen attaching to bevy app -#[derive(Debug, Clone)] -pub(crate) struct Q { - pub(crate) args: T, - // TODO: maybe app params should just be part of another wrapper struct? - pub(crate) app_param: syn::Ident, -} - -impl Q { - pub fn from_args(args: T) -> Q { - Q:: { - args, - app_param: format_ident!("app"), - } - } -} - -pub trait ToTokensWithAppParam { - fn scrub_item(&mut self) -> syn::Result<()> { - Ok(()) - } - fn to_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident); -} - -impl ToTokens for Q -where - Self: ToTokensWithAppParam, - T: ItemAttributeInput, -{ - fn to_tokens(&self, tokens: &mut TokenStream) { - ToTokensWithAppParam::to_tokens(self, tokens, &self.app_param); - } -} From b9493c8f9ec54b1cd6cb0b2fcac99bbdadccd961 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:38:10 -0400 Subject: [PATCH 084/162] refactor: rename `QQ` to `AttrEmitter` and update references across the codebase --- .../src/macro_api/{qq.rs => attr_emitter.rs} | 20 +++++++++---------- .../attributes/actions/auto_add_message.rs | 2 +- .../attributes/actions/auto_add_observer.rs | 2 +- .../attributes/actions/auto_add_plugin.rs | 2 +- .../attributes/actions/auto_add_system.rs | 2 +- .../actions/auto_configure_system_set.rs | 2 +- .../attributes/actions/auto_init_resource.rs | 2 +- .../attributes/actions/auto_init_state.rs | 2 +- .../attributes/actions/auto_init_sub_state.rs | 2 +- .../actions/auto_insert_resource.rs | 2 +- .../macro_api/attributes/actions/auto_name.rs | 2 +- .../actions/auto_register_state_type.rs | 2 +- .../attributes/actions/auto_register_type.rs | 2 +- .../attributes/actions/auto_run_on_build.rs | 2 +- .../src/macro_api/mod.rs | 4 ++-- .../src/macro_api/rewrite_q.rs | 4 ++-- 16 files changed, 27 insertions(+), 27 deletions(-) rename crates/bevy_auto_plugin_shared/src/macro_api/{qq.rs => attr_emitter.rs} (79%) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attr_emitter.rs similarity index 79% rename from crates/bevy_auto_plugin_shared/src/macro_api/qq.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/attr_emitter.rs index c8e431c1..ce98e1bc 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/qq.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attr_emitter.rs @@ -8,17 +8,17 @@ use syn::spanned::Spanned; /// for codegen re-emitting macro args #[derive(Debug, Clone)] -pub(crate) struct QQ { +pub(crate) struct AttrEmitter { pub(crate) args: T, } -impl QQ { - pub(crate) fn from_args(args: T) -> QQ { - QQ:: { args } +impl AttrEmitter { + pub(crate) fn from_args(args: T) -> AttrEmitter { + AttrEmitter:: { args } } } -impl QQ, R>> +impl AttrEmitter, R>> where T: MacroPathProvider, { @@ -32,22 +32,22 @@ where } } -pub trait QQToExpandAttr { +pub trait AttrEmitterToExpandAttr { fn to_expand_attr(&self, expand_attrs: &mut ExpandAttrs); } -impl ToTokens for QQ +impl ToTokens for AttrEmitter where - Self: QQToExpandAttr, + Self: AttrEmitterToExpandAttr, { fn to_tokens(&self, tokens: &mut TokenStream) { let mut expand_attr = ExpandAttrs::default(); - QQToExpandAttr::to_expand_attr(self, &mut expand_attr); + AttrEmitterToExpandAttr::to_expand_attr(self, &mut expand_attr); expand_attr.to_tokens(tokens); } } -impl QQ +impl AttrEmitter where T: MacroPathProvider + ItemAttributeInput + ItemAttributeContext, Self: ToTokens, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index 812cfccd..e33ed88f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -14,7 +14,7 @@ impl AttributeIdent for AddMessageArgs { pub type IaAddMessage = ItemAttribute, AllowStructOrEnum>; pub type QAddMessage = AppMutationEmitter; -pub type QQAddMessage = QQ; +pub type QQAddMessage = AttrEmitter; impl EmitAppMutationTokens for QAddMessage { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index f8c7818e..1be9438a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -14,7 +14,7 @@ impl AttributeIdent for AddObserverArgs { pub type IaAddObserver = ItemAttribute, AllowFn>; pub type QAddObserver = AppMutationEmitter; -pub type QQAddObserver = QQ; +pub type QQAddObserver = AttrEmitter; impl EmitAppMutationTokens for QAddObserver { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index 2daa0a13..9e36bcd4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -18,7 +18,7 @@ impl AttributeIdent for AddPluginArgs { pub type IaAddPlugin = ItemAttribute, AllowStructOrEnum>; pub type QAddPlugin = AppMutationEmitter; -pub type QQAddPlugin = QQ; +pub type QQAddPlugin = AttrEmitter; impl EmitAppMutationTokens for QAddPlugin { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index 42a11ce1..cf409f3c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -18,7 +18,7 @@ impl AttributeIdent for AddSystemArgs { pub type IaAddSystem = ItemAttribute, AllowFn>; pub type QAddSystem = AppMutationEmitter; -pub type QQAddSystem = QQ; +pub type QQAddSystem = AttrEmitter; impl EmitAppMutationTokens for QAddSystem { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index d563ec77..1576b39f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -96,7 +96,7 @@ pub type IaConfigureSystemSet = ItemAttribute< AllowStructOrEnum, >; pub type QConfigureSystemSet = AppMutationEmitter; -pub type QQConfigureSystemSet = QQ; +pub type QQConfigureSystemSet = AttrEmitter; fn output( args: &ConfigureSystemSetArgs, diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 49cc2265..04c6a163 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -17,7 +17,7 @@ pub type IaInitResource = ItemAttribute< AllowStructOrEnum, >; pub type QInitResource = AppMutationEmitter; -pub type QQInitResource = QQ; +pub type QQInitResource = AttrEmitter; impl EmitAppMutationTokens for QInitResource { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index d726dae0..f38d150e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -14,7 +14,7 @@ impl AttributeIdent for InitStateArgs { pub type IaInitState = ItemAttribute, AllowStructOrEnum>; pub type QInitState = AppMutationEmitter; -pub type QQInitState = QQ; +pub type QQInitState = AttrEmitter; impl EmitAppMutationTokens for QInitState { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 65d2c8c0..afd4da3f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -14,7 +14,7 @@ impl AttributeIdent for InitSubStateArgs { pub type IaInitSubState = ItemAttribute, AllowStructOrEnum>; pub type QInitSubState = AppMutationEmitter; -pub type QQInitSubState = QQ; +pub type QQInitSubState = AttrEmitter; impl EmitAppMutationTokens for QInitSubState { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 154a6054..8d99bf35 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -19,7 +19,7 @@ pub type IaInsertResource = ItemAttribute< AllowStructOrEnum, >; pub type QInsertResource = AppMutationEmitter; -pub type QQInsertResource = QQ; +pub type QQInsertResource = AttrEmitter; impl EmitAppMutationTokens for QInsertResource { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index 7549e1a1..3fbe2a55 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -17,7 +17,7 @@ impl AttributeIdent for NameArgs { pub type IaName = ItemAttribute, AllowStructOrEnum>; pub type QName = AppMutationEmitter; -pub type QQName = QQ; +pub type QQName = AttrEmitter; impl EmitAppMutationTokens for QName { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index f4d8a5df..4d9f545d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -16,7 +16,7 @@ pub type IaRegisterStateType = ItemAttribute< AllowStructOrEnum, >; pub type QRegisterStateType = AppMutationEmitter; -pub type QQRegisterStateType = QQ; +pub type QQRegisterStateType = AttrEmitter; impl EmitAppMutationTokens for QRegisterStateType { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 66957156..16ea0216 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -16,7 +16,7 @@ pub type IaRegisterType = ItemAttribute< AllowStructOrEnum, >; pub type QRegisterType = AppMutationEmitter; -pub type QQRegisterType = QQ; +pub type QQRegisterType = AttrEmitter; impl EmitAppMutationTokens for QRegisterType { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index 04952606..f69262df 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -14,7 +14,7 @@ impl AttributeIdent for RunOnBuildArgs { pub type IaRunOnBuild = ItemAttribute, AllowFn>; pub type QRunOnBuild = AppMutationEmitter; -pub type QQRunOnBuild = QQ; +pub type QQRunOnBuild = AttrEmitter; impl EmitAppMutationTokens for QRunOnBuild { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index c0672949..e6627ed9 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -1,4 +1,5 @@ mod app_mutation_emitter; +mod attr_emitter; mod attributes; mod composed; mod context; @@ -6,13 +7,13 @@ mod derives; mod input_item; mod macro_paths; mod mixins; -mod qq; mod rewrite_q; mod schedule_config; pub(crate) mod prelude { use super::*; pub use app_mutation_emitter::*; + pub use attr_emitter::*; pub use attributes::prelude::*; pub use composed::*; pub use context::*; @@ -20,6 +21,5 @@ pub(crate) mod prelude { pub use input_item::*; pub use macro_paths::*; pub use mixins::prelude::*; - pub use qq::*; pub use rewrite_q::*; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs index 5fc8d6e7..c3e2e451 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs @@ -40,7 +40,7 @@ where impl From, RFrom>>> - for QQ, RTo>> + for AttrEmitter, RTo>> where TTo: From, GTo: From, @@ -75,7 +75,7 @@ where impl From<&RewriteQ, RFrom>>> - for QQ, RTo>> + for AttrEmitter, RTo>> where TTo: From, GTo: From, From bb716623ece1bf17ec8ca2051681348cbb1d6523 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:41:13 -0400 Subject: [PATCH 085/162] refactor: rename `RewriteQ` to `AttrExpansionEmitter` and update references across the codebase --- .../src/__private/expand/attr/mod.rs | 4 +-- ...rewrite_q.rs => attr_expansion_emitter.rs} | 28 +++++++++---------- .../attributes/rewrites/auto_component.rs | 4 +-- .../attributes/rewrites/auto_event.rs | 4 +-- .../attributes/rewrites/auto_message.rs | 4 +-- .../attributes/rewrites/auto_observer.rs | 4 +-- .../attributes/rewrites/auto_resource.rs | 4 +-- .../attributes/rewrites/auto_states.rs | 4 +-- .../attributes/rewrites/auto_system.rs | 4 +-- .../src/macro_api/mod.rs | 4 +-- 10 files changed, 32 insertions(+), 32 deletions(-) rename crates/bevy_auto_plugin_shared/src/macro_api/{rewrite_q.rs => attr_expansion_emitter.rs} (64%) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 3f89c0f1..b793f6c3 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -70,14 +70,14 @@ where fn proc_attribute_rewrite_outer(attr: MacroStream, input: MacroStream) -> MacroStream where - RewriteQ: ToTokens, + AttrExpansionEmitter: ToTokens, T: ItemAttributeArgs + ItemAttributeParse + ItemAttributeInput + ItemAttributeContext, { let args = ok_or_emit_with!( T::from_attr_input_with_context(attr, input.clone(), Context::default()), input ); - RewriteQ::from_item_attribute(args).to_token_stream() + AttrExpansionEmitter::from_item_attribute(args).to_token_stream() } pub fn inject_plugin_arg_for_attributes(attrs: &mut Vec, plugin: &syn::Path) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attr_expansion_emitter.rs similarity index 64% rename from crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/attr_expansion_emitter.rs index c3e2e451..d529ee8d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/rewrite_q.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attr_expansion_emitter.rs @@ -6,47 +6,47 @@ use std::marker::PhantomData; /// for codegen rewriting attrs #[derive(Debug, Clone)] -pub(crate) struct RewriteQ { +pub(crate) struct AttrExpansionEmitter { pub(crate) args: T, } -impl RewriteQ +impl AttrExpansionEmitter where T: ItemAttributeParse, { - pub fn from_item_attribute(item_attribute: T) -> RewriteQ { - RewriteQ:: { + pub fn from_item_attribute(item_attribute: T) -> AttrExpansionEmitter { + AttrExpansionEmitter:: { args: item_attribute, } } } -pub trait RewriteQToExpandAttr { +pub trait AttrExpansionEmitterToExpandAttr { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs); } -impl ToTokens for RewriteQ +impl ToTokens for AttrExpansionEmitter where - Self: RewriteQToExpandAttr, + Self: AttrExpansionEmitterToExpandAttr, T: ItemAttributeInput, { fn to_tokens(&self, tokens: &mut TokenStream) { let mut expand_attr = ExpandAttrs::default(); - RewriteQToExpandAttr::to_expand_attrs(self, &mut expand_attr); + AttrExpansionEmitterToExpandAttr::to_expand_attrs(self, &mut expand_attr); tokens.extend(expand_attr.to_token_stream()); tokens.extend(self.args.input_item().to_token_stream()); } } impl - From, RFrom>>> + From, RFrom>>> for AttrEmitter, RTo>> where TTo: From, GTo: From, RTo: From, { - fn from(value: RewriteQ, RFrom>>) -> Self { + fn from(value: AttrExpansionEmitter, RFrom>>) -> Self { let ItemAttribute { args, context, @@ -74,16 +74,16 @@ where } impl - From<&RewriteQ, RFrom>>> + From<&AttrExpansionEmitter, RFrom>>> for AttrEmitter, RTo>> where TTo: From, GTo: From, RTo: From, - RewriteQ, RFrom>>: Clone, + AttrExpansionEmitter, RFrom>>: Clone, { - fn from(value: &RewriteQ, RFrom>>) -> Self { - , RFrom>>>>::from( + fn from(value: &AttrExpansionEmitter, RFrom>>) -> Self { + , RFrom>>>>::from( value.clone(), ) } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index d77718c4..e83a99cd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -37,9 +37,9 @@ impl<'a> From<&'a ComponentArgs> for NameArgs { pub type IaComponent = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQComponent = RewriteQ; +pub type RewriteQComponent = AttrExpansionEmitter; -impl RewriteQToExpandAttr for RewriteQComponent { +impl AttrExpansionEmitterToExpandAttr for RewriteQComponent { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index 8b576a1c..d7d22f31 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -51,8 +51,8 @@ impl<'a> From<&'a EventArgs> for RegisterTypeArgs { pub type IaEvent = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQEvent = RewriteQ; -impl RewriteQToExpandAttr for RewriteQEvent { +pub type RewriteQEvent = AttrExpansionEmitter; +impl AttrExpansionEmitterToExpandAttr for RewriteQEvent { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { if matches!(self.args.args.base.target, EventTarget::Global) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index 9a9aec44..ab3eaee2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -32,9 +32,9 @@ impl<'a> From<&'a MessageArgs> for AddMessageArgs { pub type IaMessage = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQMessage = RewriteQ; +pub type RewriteQMessage = AttrExpansionEmitter; -impl RewriteQToExpandAttr for RewriteQMessage { +impl AttrExpansionEmitterToExpandAttr for RewriteQMessage { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index cf473dcc..240a7064 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -25,9 +25,9 @@ impl<'a> From<&'a ObserverArgs> for AddObserverArgs { pub type IaObserver = ItemAttribute, AllowFn>; -pub type RewriteQObserver = RewriteQ; +pub type RewriteQObserver = AttrExpansionEmitter; -impl RewriteQToExpandAttr for RewriteQObserver { +impl AttrExpansionEmitterToExpandAttr for RewriteQObserver { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { expand_attrs .attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 059958c6..2dece90d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -34,8 +34,8 @@ impl<'a> From<&'a ResourceArgs> for InitResourceArgs { pub type IaResource = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQResource = RewriteQ; -impl RewriteQToExpandAttr for RewriteQResource { +pub type RewriteQResource = AttrExpansionEmitter; +impl AttrExpansionEmitterToExpandAttr for RewriteQResource { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 2a32af50..cf5e4b7a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -32,8 +32,8 @@ impl<'a> From<&'a StatesArgs> for InitStateArgs { } pub type IaState = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQState = RewriteQ; -impl RewriteQToExpandAttr for RewriteQState { +pub type RewriteQState = AttrExpansionEmitter; +impl AttrExpansionEmitterToExpandAttr for RewriteQState { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs.append(tokens::derive_states(&self.args.args.base.derive.items)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index c2775d9a..285f8565 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -30,9 +30,9 @@ impl<'a> From<&'a SystemArgs> for AddSystemArgs { pub type IaSystem = ItemAttribute, AllowFn>; -pub type RewriteQSystem = RewriteQ; +pub type RewriteQSystem = AttrExpansionEmitter; -impl RewriteQToExpandAttr for RewriteQSystem { +impl AttrExpansionEmitterToExpandAttr for RewriteQSystem { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { expand_attrs .attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index e6627ed9..95a8599d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -1,5 +1,6 @@ mod app_mutation_emitter; mod attr_emitter; +mod attr_expansion_emitter; mod attributes; mod composed; mod context; @@ -7,13 +8,13 @@ mod derives; mod input_item; mod macro_paths; mod mixins; -mod rewrite_q; mod schedule_config; pub(crate) mod prelude { use super::*; pub use app_mutation_emitter::*; pub use attr_emitter::*; + pub use attr_expansion_emitter::*; pub use attributes::prelude::*; pub use composed::*; pub use context::*; @@ -21,5 +22,4 @@ pub(crate) mod prelude { pub use input_item::*; pub use macro_paths::*; pub use mixins::prelude::*; - pub use rewrite_q::*; } From 1023faac38b77905e16f278f53c81f20ed24740a Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:43:25 -0400 Subject: [PATCH 086/162] refactor: reorganize emitters into `macro_api/emitters` module and update references accordingly --- .../macro_api/attributes/actions/auto_init_resource.rs | 2 +- .../app_mutation.rs} | 0 .../macro_api/{attr_emitter.rs => emitters/attr.rs} | 0 .../attr_expansion.rs} | 0 .../src/macro_api/emitters/mod.rs | 3 +++ crates/bevy_auto_plugin_shared/src/macro_api/mod.rs | 10 ++++------ 6 files changed, 8 insertions(+), 7 deletions(-) rename crates/bevy_auto_plugin_shared/src/macro_api/{app_mutation_emitter.rs => emitters/app_mutation.rs} (100%) rename crates/bevy_auto_plugin_shared/src/macro_api/{attr_emitter.rs => emitters/attr.rs} (100%) rename crates/bevy_auto_plugin_shared/src/macro_api/{attr_expansion_emitter.rs => emitters/attr_expansion.rs} (100%) create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 04c6a163..5fabe472 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -1,4 +1,4 @@ -use crate::macro_api::app_mutation_emitter::{AppMutationEmitter, EmitAppMutationTokens}; +use crate::macro_api::emitters::app_mutation::{AppMutationEmitter, EmitAppMutationTokens}; use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/app_mutation_emitter.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs similarity index 100% rename from crates/bevy_auto_plugin_shared/src/macro_api/app_mutation_emitter.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attr_emitter.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr.rs similarity index 100% rename from crates/bevy_auto_plugin_shared/src/macro_api/attr_emitter.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr.rs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attr_expansion_emitter.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs similarity index 100% rename from crates/bevy_auto_plugin_shared/src/macro_api/attr_expansion_emitter.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs new file mode 100644 index 00000000..f19276e7 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs @@ -0,0 +1,3 @@ +pub mod app_mutation; +pub mod attr; +pub mod attr_expansion; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 95a8599d..3e9abf6c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -1,10 +1,8 @@ -mod app_mutation_emitter; -mod attr_emitter; -mod attr_expansion_emitter; mod attributes; mod composed; mod context; mod derives; +mod emitters; mod input_item; mod macro_paths; mod mixins; @@ -12,9 +10,9 @@ mod schedule_config; pub(crate) mod prelude { use super::*; - pub use app_mutation_emitter::*; - pub use attr_emitter::*; - pub use attr_expansion_emitter::*; + pub use crate::macro_api::emitters::app_mutation::*; + pub use crate::macro_api::emitters::attr::*; + pub use crate::macro_api::emitters::attr_expansion::*; pub use attributes::prelude::*; pub use composed::*; pub use context::*; From 4a855a6df8d7590c716973ceba665ddad5d20760 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:46:30 -0400 Subject: [PATCH 087/162] refactor: move `context.rs` into `context` module --- .../src/macro_api/{context.rs => context/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/bevy_auto_plugin_shared/src/macro_api/{context.rs => context/mod.rs} (100%) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs similarity index 100% rename from crates/bevy_auto_plugin_shared/src/macro_api/context.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs From e46a99c10c45b52f1dd867f36e053a0f8bfd9feb Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:47:06 -0400 Subject: [PATCH 088/162] refactor: move `macro_paths.rs` into `context` module and adjust references --- crates/bevy_auto_plugin_shared/src/macro_api/composed.rs | 2 +- .../src/macro_api/{ => context}/macro_paths.rs | 0 crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs | 4 +++- crates/bevy_auto_plugin_shared/src/macro_api/mod.rs | 3 +-- 4 files changed, 5 insertions(+), 4 deletions(-) rename crates/bevy_auto_plugin_shared/src/macro_api/{ => context}/macro_paths.rs (100%) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 95f66ffb..7d8e440f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -1,6 +1,6 @@ use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; use crate::macro_api::context::Context; -use crate::macro_api::macro_paths::MacroPathProvider; +use crate::macro_api::context::macro_paths::MacroPathProvider; use crate::macro_api::mixins::Mixin; use crate::macro_api::mixins::generics::HasGenerics; use crate::macro_api::mixins::nothing::Nothing; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context/macro_paths.rs similarity index 100% rename from crates/bevy_auto_plugin_shared/src/macro_api/macro_paths.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/context/macro_paths.rs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs index 0aade644..0a98eaca 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs @@ -1,4 +1,6 @@ -use crate::macro_api::macro_paths::MacroPaths; +use macro_paths::MacroPaths; + +pub mod macro_paths; #[derive(Debug, Clone, Default, PartialEq, Hash)] pub struct Context { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index 3e9abf6c..fffc7c72 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -4,12 +4,12 @@ mod context; mod derives; mod emitters; mod input_item; -mod macro_paths; mod mixins; mod schedule_config; pub(crate) mod prelude { use super::*; + pub use crate::macro_api::context::macro_paths::*; pub use crate::macro_api::emitters::app_mutation::*; pub use crate::macro_api::emitters::attr::*; pub use crate::macro_api::emitters::attr_expansion::*; @@ -18,6 +18,5 @@ pub(crate) mod prelude { pub use context::*; pub use derives::prelude::*; pub use input_item::*; - pub use macro_paths::*; pub use mixins::prelude::*; } From e40e64a188172e7dbdfb4cafee8eda26f1033a1c Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:48:04 -0400 Subject: [PATCH 089/162] refactor: consolidate macro_api imports using prelude module --- crates/bevy_auto_plugin_shared/src/macro_api/composed.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 7d8e440f..3dcddad4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -1,10 +1,4 @@ -use crate::macro_api::attributes::{AttributeIdent, ItemAttributeArgs}; -use crate::macro_api::context::Context; -use crate::macro_api::context::macro_paths::MacroPathProvider; -use crate::macro_api::mixins::Mixin; -use crate::macro_api::mixins::generics::HasGenerics; -use crate::macro_api::mixins::nothing::Nothing; -use crate::macro_api::mixins::with_plugin::WithPlugin; +use crate::macro_api::prelude::*; use crate::syntax::ast::type_list::TypeList; use darling::FromMeta; use darling::ast::NestedMeta; From 9c1eaa57fcad1c1ea735f0028fd23e75a520ed46 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 16:52:57 -0400 Subject: [PATCH 090/162] refactor: move `body` into AppMutationEmitter as `wrap_body` --- .../src/__private/expand/attr/mod.rs | 39 +------------------ .../src/macro_api/emitters/app_mutation.rs | 32 +++++++++++++++ 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index b793f6c3..1c7e2687 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,45 +1,11 @@ -use crate::__private::auto_plugin_registry::_plugin_entry_block; use crate::macro_api::prelude::*; use crate::util::macros::ok_or_emit_with; use proc_macro2::TokenStream as MacroStream; -use quote::{ToTokens, format_ident, quote}; +use quote::{ToTokens, quote}; pub mod auto_bind_plugin; pub mod auto_plugin; -fn body( - body: impl Fn(MacroStream) -> MacroStream, -) -> impl Fn(AppMutationEmitter) -> syn::Result -where - T: ItemAttributeArgs - + ItemAttributeParse - + ItemAttributeInput - + ItemAttributeTarget - + ItemAttributeContext - + ItemAttributeUniqueIdent - + ItemAttributePlugin, - AppMutationEmitter: ToTokens, -{ - move |params| -> syn::Result { - let ident = params.args.target().to_token_stream(); - let app_param = ¶ms.app_param; - let unique_ident = params.args.get_unique_ident(); - let plugin = params.args.plugin().clone(); - let body = body(params.to_token_stream()); - let expr: syn::ExprClosure = syn::parse_quote!(|#app_param| { - #body - }); - // required for generics - let unique_ident = format_ident!("{unique_ident}"); - let output = _plugin_entry_block(&unique_ident, &plugin, &expr); - assert!( - !output.is_empty(), - "No plugin entry points were generated for ident: {ident}" - ); - Ok(output) - } -} - fn proc_attribute_outer(attr: MacroStream, input: MacroStream) -> MacroStream where T: ItemAttributeArgs @@ -55,13 +21,12 @@ where T::from_attr_input_with_context(attr, input.clone(), Context::default()), input ); - let body_fn = body(|body| quote! { #body }); let mut q = AppMutationEmitter::from_args(args); let scrubbed_input = { ok_or_emit_with!(q.scrub_item(), q.args.input_item()); q.args.input_item().to_token_stream() }; - let after_item_tokens = ok_or_emit_with!(body_fn(q), scrubbed_input); + let after_item_tokens = ok_or_emit_with!(q.wrap_body(|body| quote! { #body }), scrubbed_input); quote! { #scrubbed_input #after_item_tokens diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs index bad49128..613ef898 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs @@ -1,3 +1,4 @@ +use crate::__private::auto_plugin_registry::_plugin_entry_block; use crate::macro_api::prelude::*; use proc_macro2::TokenStream; use quote::{ToTokens, format_ident}; @@ -17,6 +18,37 @@ impl AppMutationEmitter { app_param: format_ident!("app"), } } + pub fn wrap_body( + &mut self, + body: impl Fn(TokenStream) -> TokenStream, + ) -> syn::Result + where + T: ItemAttributeArgs + + ItemAttributeParse + + ItemAttributeInput + + ItemAttributeTarget + + ItemAttributeContext + + ItemAttributeUniqueIdent + + ItemAttributePlugin, + AppMutationEmitter: ToTokens, + { + let ident = self.args.target().to_token_stream(); + let app_param = &self.app_param; + let unique_ident = self.args.get_unique_ident(); + let plugin = self.args.plugin().clone(); + let body = body(self.to_token_stream()); + let expr: syn::ExprClosure = syn::parse_quote!(|#app_param| { + #body + }); + // required for generics + let unique_ident = format_ident!("{unique_ident}"); + let output = _plugin_entry_block(&unique_ident, &plugin, &expr); + assert!( + !output.is_empty(), + "No plugin entry points were generated for ident: {ident}" + ); + Ok(output) + } } pub trait EmitAppMutationTokens { From 56ece7585a12d7da62cc07447a206cbd9b47acb1 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 18:49:52 -0400 Subject: [PATCH 091/162] refactor: extract `proc_attribute_outer` and `proc_attribute_rewrite_outer` into separate modules and update references --- .../src/__private/expand/attr/action.rs | 31 ++++++++++++ .../src/__private/expand/attr/mod.rs | 48 ++----------------- .../src/__private/expand/attr/rewrite.rs | 16 +++++++ 3 files changed, 52 insertions(+), 43 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs create mode 100644 crates/bevy_auto_plugin_shared/src/__private/expand/attr/rewrite.rs diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs new file mode 100644 index 00000000..cc5eaa85 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs @@ -0,0 +1,31 @@ +use crate::macro_api::prelude::*; +use crate::util::macros::ok_or_emit_with; +use proc_macro2::TokenStream as MacroStream; +use quote::{ToTokens, quote}; + +pub fn proc_attribute_outer(attr: MacroStream, input: MacroStream) -> MacroStream +where + T: ItemAttributeArgs + + ItemAttributeParse + + ItemAttributeInput + + ItemAttributeTarget + + ItemAttributeUniqueIdent + + ItemAttributeContext + + ItemAttributePlugin, + AppMutationEmitter: ToTokens + EmitAppMutationTokens, +{ + let args = ok_or_emit_with!( + T::from_attr_input_with_context(attr, input.clone(), Context::default()), + input + ); + let mut q = AppMutationEmitter::from_args(args); + let scrubbed_input = { + ok_or_emit_with!(q.scrub_item(), q.args.input_item()); + q.args.input_item().to_token_stream() + }; + let after_item_tokens = ok_or_emit_with!(q.wrap_body(|body| quote! { #body }), scrubbed_input); + quote! { + #scrubbed_input + #after_item_tokens + } +} diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 1c7e2687..750331c4 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,49 +1,11 @@ use crate::macro_api::prelude::*; -use crate::util::macros::ok_or_emit_with; use proc_macro2::TokenStream as MacroStream; -use quote::{ToTokens, quote}; +use quote::ToTokens; +pub mod action; pub mod auto_bind_plugin; pub mod auto_plugin; - -fn proc_attribute_outer(attr: MacroStream, input: MacroStream) -> MacroStream -where - T: ItemAttributeArgs - + ItemAttributeParse - + ItemAttributeInput - + ItemAttributeTarget - + ItemAttributeUniqueIdent - + ItemAttributeContext - + ItemAttributePlugin, - AppMutationEmitter: ToTokens + EmitAppMutationTokens, -{ - let args = ok_or_emit_with!( - T::from_attr_input_with_context(attr, input.clone(), Context::default()), - input - ); - let mut q = AppMutationEmitter::from_args(args); - let scrubbed_input = { - ok_or_emit_with!(q.scrub_item(), q.args.input_item()); - q.args.input_item().to_token_stream() - }; - let after_item_tokens = ok_or_emit_with!(q.wrap_body(|body| quote! { #body }), scrubbed_input); - quote! { - #scrubbed_input - #after_item_tokens - } -} - -fn proc_attribute_rewrite_outer(attr: MacroStream, input: MacroStream) -> MacroStream -where - AttrExpansionEmitter: ToTokens, - T: ItemAttributeArgs + ItemAttributeParse + ItemAttributeInput + ItemAttributeContext, -{ - let args = ok_or_emit_with!( - T::from_attr_input_with_context(attr, input.clone(), Context::default()), - input - ); - AttrExpansionEmitter::from_item_attribute(args).to_token_stream() -} +pub mod rewrite; pub fn inject_plugin_arg_for_attributes(attrs: &mut Vec, plugin: &syn::Path) { use syn::Meta; @@ -120,7 +82,7 @@ macro_rules! gen_auto_attribute_outers { (@one $fn:ident, $args:ty) => { #[inline] pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { - proc_attribute_outer::<$args>(attr, input) + action::proc_attribute_outer::<$args>(attr, input) } }; @@ -138,7 +100,7 @@ macro_rules! gen_auto_outers { $( #[inline] pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { - proc_attribute_rewrite_outer::<$args>(attr, input) + rewrite::proc_attribute_rewrite_outer::<$args>(attr, input) } )+ }; diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/rewrite.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/rewrite.rs new file mode 100644 index 00000000..499883a4 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/rewrite.rs @@ -0,0 +1,16 @@ +use crate::macro_api::prelude::*; +use crate::util::macros::ok_or_emit_with; +use proc_macro2::TokenStream as MacroStream; +use quote::ToTokens; + +pub fn proc_attribute_rewrite_outer(attr: MacroStream, input: MacroStream) -> MacroStream +where + AttrExpansionEmitter: ToTokens, + T: ItemAttributeArgs + ItemAttributeParse + ItemAttributeInput + ItemAttributeContext, +{ + let args = ok_or_emit_with!( + T::from_attr_input_with_context(attr, input.clone(), Context::default()), + input + ); + AttrExpansionEmitter::from_item_attribute(args).to_token_stream() +} From cc5b021f5b72daede9e75aa657cdadd27ffe9e7f Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 18:51:34 -0400 Subject: [PATCH 092/162] refactor: simplify `gen_auto_attribute_outers` macro by removing parser handling logic --- .../src/__private/expand/attr/mod.rs | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 750331c4..1f37d442 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -71,28 +71,21 @@ fn list_has_key(ml: &syn::MetaList, key: &str) -> bool { } macro_rules! gen_auto_attribute_outers { - // Each item: fn_name => ArgsTy [using ] - ( $( $fn:ident => $args:ty $(: parser = $parser:expr)? ),+ $(,)? ) => { - $( - gen_auto_attribute_outers!(@one $fn, $args $(, $parser)?); - )+ + ( $( $fn:ident => $args:ty ),+ $(,)? ) => { + $( + #[inline] + pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { + action::proc_attribute_outer::<$args>(attr, input) + } + )+ }; - // No parser (@one $fn:ident, $args:ty) => { #[inline] pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { action::proc_attribute_outer::<$args>(attr, input) } }; - - // With parser - (@one $fn:ident, $args:ty, $parser:expr) => { - #[inline] - pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { - proc_attribute_with_parser_outer::<$args>(attr, input, $parser) - } - }; } macro_rules! gen_auto_outers { From dc0c75fd1bd460439809a6ef9598ee7a5cc325e3 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 18:52:35 -0400 Subject: [PATCH 093/162] refactor: rename macros `gen_auto_attribute_outers` and `gen_auto_outers` to `gen_action_outers` and `gen_rewrite_outers` respectively --- .../src/__private/expand/attr/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 1f37d442..efc1d68a 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -70,7 +70,7 @@ fn list_has_key(ml: &syn::MetaList, key: &str) -> bool { } } -macro_rules! gen_auto_attribute_outers { +macro_rules! gen_action_outers { ( $( $fn:ident => $args:ty ),+ $(,)? ) => { $( #[inline] @@ -88,7 +88,7 @@ macro_rules! gen_auto_attribute_outers { }; } -macro_rules! gen_auto_outers { +macro_rules! gen_rewrite_outers { ( $( $fn:ident => $args:ty ),+ $(,)? ) => { $( #[inline] @@ -99,7 +99,7 @@ macro_rules! gen_auto_outers { }; } -gen_auto_attribute_outers! { +gen_action_outers! { auto_run_on_build => IaRunOnBuild, auto_register_type => IaRegisterType, auto_add_message => IaAddMessage, @@ -115,7 +115,7 @@ gen_auto_attribute_outers! { auto_configure_system_set => IaConfigureSystemSet, } -gen_auto_outers! { +gen_rewrite_outers! { auto_component => IaComponent, auto_resource => IaResource, auto_system => IaSystem, From 450121339d7dab0bc8b794af2d695e6df35dde96 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 18:53:20 -0400 Subject: [PATCH 094/162] refactor: remove unused `@one` macro helper from `expand/attr/mod.rs` --- .../src/__private/expand/attr/mod.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index efc1d68a..f407d916 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -79,13 +79,6 @@ macro_rules! gen_action_outers { } )+ }; - - (@one $fn:ident, $args:ty) => { - #[inline] - pub fn $fn(attr: MacroStream, input: MacroStream) -> MacroStream { - action::proc_attribute_outer::<$args>(attr, input) - } - }; } macro_rules! gen_rewrite_outers { From 4d7aeb246c84612b06066d1f0d4a45690adebe67 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 19:52:37 -0400 Subject: [PATCH 095/162] refactor: rename plugin injection functions --- .../src/__private/expand/attr/auto_bind_plugin.rs | 2 +- .../src/__private/expand/attr/mod.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index 112a4c99..a4313b21 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -25,7 +25,7 @@ pub fn auto_bind_plugin_inner( .take_attrs() .map_err(|err| syn::Error::new(item.span(), err))?; - attr::inject_plugin_arg_for_attributes(&mut attrs, plugin_path); + attr::attrs_inject_plugin_param(&mut attrs, plugin_path); let Ok(_) = item.put_attrs(attrs) else { unreachable!() diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index f407d916..d2f80390 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -7,7 +7,7 @@ pub mod auto_bind_plugin; pub mod auto_plugin; pub mod rewrite; -pub fn inject_plugin_arg_for_attributes(attrs: &mut Vec, plugin: &syn::Path) { +pub fn attrs_inject_plugin_param(attrs: &mut Vec, plugin: &syn::Path) { use syn::Meta; for attr in attrs { @@ -32,11 +32,11 @@ pub fn inject_plugin_arg_for_attributes(attrs: &mut Vec, plugin: continue; } - inject_plugin_arg(attr, plugin); + attr_inject_plugin_param(attr, plugin); } } -fn inject_plugin_arg(attr: &mut syn::Attribute, plugin: &syn::Path) { +fn attr_inject_plugin_param(attr: &mut syn::Attribute, plugin: &syn::Path) { use syn::Meta; use syn::parse_quote; match &attr.meta { From 91234f73030fd161f0762ad458caef7a46c6d3c8 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 19:52:52 -0400 Subject: [PATCH 096/162] refactor: remove unused `ToTokens` import from `expand/attr/mod.rs` --- crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index d2f80390..ed5383ca 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -1,6 +1,5 @@ use crate::macro_api::prelude::*; use proc_macro2::TokenStream as MacroStream; -use quote::ToTokens; pub mod action; pub mod auto_bind_plugin; From 23ab0eb18efbb6245f9bffecf1469434c31f87d9 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 20:03:53 -0400 Subject: [PATCH 097/162] refactor: add `item_emitter` module and consolidate `emitters` imports using prelude module --- .../bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs | 8 ++++++++ crates/bevy_auto_plugin_shared/src/macro_api/mod.rs | 1 + 2 files changed, 9 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs index f19276e7..3ea67dd4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs @@ -1,3 +1,11 @@ pub mod app_mutation; pub mod attr; pub mod attr_expansion; +pub mod item_emitter; + +pub mod prelude { + pub use super::app_mutation::*; + pub use super::attr::*; + pub use super::attr_expansion::*; + pub use super::item_emitter::*; +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index fffc7c72..f52ffd2e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -17,6 +17,7 @@ pub(crate) mod prelude { pub use composed::*; pub use context::*; pub use derives::prelude::*; + pub use emitters::prelude::*; pub use input_item::*; pub use mixins::prelude::*; } From 84d1e0effbfcb3e15b9ea2ccc00713ab2b8a9540 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 21:07:47 -0400 Subject: [PATCH 098/162] refactor: rename `scrub_item` to `item_post_process` and update related references --- .../src/__private/expand/attr/action.rs | 18 ++++++---- .../actions/auto_configure_system_set.rs | 35 +++++++++---------- .../src/macro_api/emitters/app_mutation.rs | 3 +- .../src/macro_api/emitters/mod.rs | 2 -- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs index cc5eaa85..40c579d8 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs @@ -18,14 +18,20 @@ where T::from_attr_input_with_context(attr, input.clone(), Context::default()), input ); - let mut q = AppMutationEmitter::from_args(args); - let scrubbed_input = { - ok_or_emit_with!(q.scrub_item(), q.args.input_item()); - q.args.input_item().to_token_stream() + let mut app_mut_emitter = AppMutationEmitter::from_args(args); + let processed_item = { + ok_or_emit_with!( + app_mut_emitter.item_post_process(), + app_mut_emitter.args.input_item() + ); + app_mut_emitter.args.input_item().to_token_stream() }; - let after_item_tokens = ok_or_emit_with!(q.wrap_body(|body| quote! { #body }), scrubbed_input); + let after_item_tokens = ok_or_emit_with!( + app_mut_emitter.wrap_body(|body| quote! { #body }), + processed_item + ); quote! { - #scrubbed_input + #processed_item #after_item_tokens } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 1576b39f..cb2c042f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -9,7 +9,6 @@ use proc_macro2::{Ident, TokenStream}; use quote::{ToTokens, quote}; use syn::spanned::Spanned; use syn::{Attribute, Item, Path, parse_quote}; - const CONFIG_ATTR_NAME: &str = "auto_configure_system_set_config"; const CHAIN_CONFLICT_ERR: &str = "`chain` and `chain_ignore_deferred` are mutually exclusive"; @@ -154,34 +153,32 @@ fn output( } impl EmitAppMutationTokens for QConfigureSystemSet { - // TODO: it would prob make more sense to return the token stream instead of inserting back into args - // but then that makes no-op default impl look weird. Would we return ItemInput regardless? - // or maybe we require a &mut TokenStream to be passed in and we mutate it - fn scrub_item(&mut self) -> syn::Result<()> { + fn item_post_process(&mut self) -> syn::Result<()> { let input_item = &mut self.args.input_item; let args = &mut self.args.args.base; let item = input_item.ensure_ast()?; check_strip_helpers(item, args)?; - let input = input_item.to_token_stream(); - let res = inflate_args_from_input(args.clone(), input)?; - *args = res.inflated_args; - *input_item = InputItem::Tokens(res.scrubbed_tokens); + if args.inner.is_none() { + let input = input_item.to_token_stream(); + let res = inflate_args_from_input(args.clone(), input)?; + *args = res.inflated_args; + *input_item = InputItem::Tokens(res.scrubbed_tokens); + } Ok(()) } fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = self.args.args.base.clone(); // checks if we need to inflate args let inflated_args = if args.inner.is_none() { - let (inflated_args, _) = - match inflate_args_from_input(args.clone(), self.args.input_item.to_token_stream()) - { - Ok(res) => res.into_tuple(), - Err(err) => { - tokens.extend(err.to_compile_error()); - return; - } - }; - inflated_args + let args = args.clone(); + let input = self.args.input_item.to_token_stream(); + match inflate_args_from_input(args, input) { + Ok(res) => res.inflated_args, + Err(err) => { + tokens.extend(err.to_compile_error()); + return; + } + } } else { args }; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs index 613ef898..ac37f6c5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs @@ -52,7 +52,8 @@ impl AppMutationEmitter { } pub trait EmitAppMutationTokens { - fn scrub_item(&mut self) -> syn::Result<()> { + // TODO: this should be its own thing but it might overcomplicate things + fn item_post_process(&mut self) -> syn::Result<()> { Ok(()) } fn to_app_mutation_token_stream(&self, app_param: &syn::Ident) -> TokenStream { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs index 3ea67dd4..be7c2396 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs @@ -1,11 +1,9 @@ pub mod app_mutation; pub mod attr; pub mod attr_expansion; -pub mod item_emitter; pub mod prelude { pub use super::app_mutation::*; pub use super::attr::*; pub use super::attr_expansion::*; - pub use super::item_emitter::*; } From fd46720f8da25cea0ac41698dcfe74156fc2a0d4 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sun, 26 Oct 2025 21:15:10 -0400 Subject: [PATCH 099/162] refactor: rename emitter types and related references --- .../bevy_auto_plugin_shared/src/codegen/tokens.rs | 14 +++++++------- .../attributes/actions/auto_add_message.rs | 8 ++++---- .../attributes/actions/auto_add_observer.rs | 8 ++++---- .../attributes/actions/auto_add_plugin.rs | 8 ++++---- .../attributes/actions/auto_add_system.rs | 8 ++++---- .../actions/auto_configure_system_set.rs | 8 ++++---- .../attributes/actions/auto_init_resource.rs | 8 ++++---- .../attributes/actions/auto_init_state.rs | 8 ++++---- .../attributes/actions/auto_init_sub_state.rs | 8 ++++---- .../attributes/actions/auto_insert_resource.rs | 8 ++++---- .../src/macro_api/attributes/actions/auto_name.rs | 8 ++++---- .../attributes/actions/auto_register_state_type.rs | 8 ++++---- .../attributes/actions/auto_register_type.rs | 8 ++++---- .../attributes/actions/auto_run_on_build.rs | 8 ++++---- .../attributes/rewrites/auto_component.rs | 4 ++-- .../macro_api/attributes/rewrites/auto_event.rs | 4 ++-- .../macro_api/attributes/rewrites/auto_message.rs | 4 ++-- .../macro_api/attributes/rewrites/auto_observer.rs | 4 ++-- .../macro_api/attributes/rewrites/auto_resource.rs | 4 ++-- .../macro_api/attributes/rewrites/auto_states.rs | 4 ++-- .../macro_api/attributes/rewrites/auto_system.rs | 4 ++-- 21 files changed, 73 insertions(+), 73 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs index cb445698..db954fc8 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs @@ -158,24 +158,24 @@ pub fn use_bevy_state_app_ext_states() -> syn::ItemUse { parse_quote! { use #root::app::AppExtStates as _; } } -pub fn auto_register_type(args: QQRegisterType) -> TokenStream { +pub fn auto_register_type(args: RegisterTypeAttrEmitter) -> TokenStream { args.to_token_stream() } -pub fn auto_name(args: QQName) -> TokenStream { +pub fn auto_name(args: NameAttrEmitter) -> TokenStream { args.to_token_stream() } -pub fn auto_init_resource(args: QQInitResource) -> TokenStream { +pub fn auto_init_resource(args: InitResourceAttrEmitter) -> TokenStream { args.to_token_stream() } -pub fn auto_init_states(args: QQInitState) -> TokenStream { +pub fn auto_init_states(args: InitStateAttrEmitter) -> TokenStream { args.to_token_stream() } -pub fn auto_add_systems(args: QQAddSystem) -> TokenStream { +pub fn auto_add_systems(args: AddSystemAttrEmitter) -> TokenStream { args.to_token_stream() } -pub fn auto_add_observer(args: QQAddObserver) -> TokenStream { +pub fn auto_add_observer(args: AddObserverAttrEmitter) -> TokenStream { args.to_token_stream() } -pub fn auto_add_message(args: QQAddMessage) -> TokenStream { +pub fn auto_add_message(args: AddMessageAttrEmitter) -> TokenStream { args.to_token_stream() } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index e33ed88f..d1845d0f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -13,10 +13,10 @@ impl AttributeIdent for AddMessageArgs { pub type IaAddMessage = ItemAttribute, AllowStructOrEnum>; -pub type QAddMessage = AppMutationEmitter; -pub type QQAddMessage = AttrEmitter; +pub type AddMessageAppMutEmitter = AppMutationEmitter; +pub type AddMessageAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QAddMessage { +impl EmitAppMutationTokens for AddMessageAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl EmitAppMutationTokens for QAddMessage { } } -impl ToTokens for QQAddMessage { +impl ToTokens for AddMessageAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 1be9438a..4dfba80f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -13,10 +13,10 @@ impl AttributeIdent for AddObserverArgs { pub type IaAddObserver = ItemAttribute, AllowFn>; -pub type QAddObserver = AppMutationEmitter; -pub type QQAddObserver = AttrEmitter; +pub type AddObserverAppMutEmitter = AppMutationEmitter; +pub type AddObserverAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QAddObserver { +impl EmitAppMutationTokens for AddObserverAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl EmitAppMutationTokens for QAddObserver { } } -impl ToTokens for QQAddObserver { +impl ToTokens for AddObserverAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index 9e36bcd4..3baac2db 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -17,10 +17,10 @@ impl AttributeIdent for AddPluginArgs { pub type IaAddPlugin = ItemAttribute, AllowStructOrEnum>; -pub type QAddPlugin = AppMutationEmitter; -pub type QQAddPlugin = AttrEmitter; +pub type AddPluginAppMutEmitter = AppMutationEmitter; +pub type AddPluginAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QAddPlugin { +impl EmitAppMutationTokens for AddPluginAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { if let Some(expr) = &self.args.args.base.init.expr { @@ -40,7 +40,7 @@ impl EmitAppMutationTokens for QAddPlugin { } } -impl ToTokens for QQAddPlugin { +impl ToTokens for AddPluginAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index cf409f3c..21fbcbcf 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -17,10 +17,10 @@ impl AttributeIdent for AddSystemArgs { pub type IaAddSystem = ItemAttribute, AllowFn>; -pub type QAddSystem = AppMutationEmitter; -pub type QQAddSystem = AttrEmitter; +pub type AddSystemAppMutEmitter = AppMutationEmitter; +pub type AddSystemAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QAddSystem { +impl EmitAppMutationTokens for AddSystemAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let schedule = &self.args.args.base.schedule_config.schedule; let config_tokens = self.args.args.base.schedule_config.config.to_token_stream(); @@ -32,7 +32,7 @@ impl EmitAppMutationTokens for QAddSystem { } } -impl ToTokens for QQAddSystem { +impl ToTokens for AddSystemAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); // TODO: cleanup diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index cb2c042f..0c69461c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -94,8 +94,8 @@ pub type IaConfigureSystemSet = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QConfigureSystemSet = AppMutationEmitter; -pub type QQConfigureSystemSet = AttrEmitter; +pub type ConfigureSystemSetAppMutEmitter = AppMutationEmitter; +pub type ConfigureSystemSetAttrEmitter = AttrEmitter; fn output( args: &ConfigureSystemSetArgs, @@ -152,7 +152,7 @@ fn output( tokens } -impl EmitAppMutationTokens for QConfigureSystemSet { +impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { fn item_post_process(&mut self) -> syn::Result<()> { let input_item = &mut self.args.input_item; let args = &mut self.args.args.base; @@ -194,7 +194,7 @@ impl EmitAppMutationTokens for QConfigureSystemSet { } } -impl ToTokens for QQConfigureSystemSet { +impl ToTokens for ConfigureSystemSetAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); todo!("not implemented"); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 5fabe472..416273d9 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -16,10 +16,10 @@ pub type IaInitResource = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QInitResource = AppMutationEmitter; -pub type QQInitResource = AttrEmitter; +pub type InitResourceAppMutEmitter = AppMutationEmitter; +pub type InitResourceAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QInitResource { +impl EmitAppMutationTokens for InitResourceAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -29,7 +29,7 @@ impl EmitAppMutationTokens for QInitResource { } } -impl ToTokens for QQInitResource { +impl ToTokens for InitResourceAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index f38d150e..04ba582e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -13,10 +13,10 @@ impl AttributeIdent for InitStateArgs { pub type IaInitState = ItemAttribute, AllowStructOrEnum>; -pub type QInitState = AppMutationEmitter; -pub type QQInitState = AttrEmitter; +pub type InitStateAppMutEmitter = AppMutationEmitter; +pub type InitStateAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QInitState { +impl EmitAppMutationTokens for InitStateAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { @@ -25,7 +25,7 @@ impl EmitAppMutationTokens for QInitState { } } -impl ToTokens for QQInitState { +impl ToTokens for InitStateAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index afd4da3f..786f9464 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -13,10 +13,10 @@ impl AttributeIdent for InitSubStateArgs { pub type IaInitSubState = ItemAttribute, AllowStructOrEnum>; -pub type QInitSubState = AppMutationEmitter; -pub type QQInitSubState = AttrEmitter; +pub type InitSubStateAppMutEmitter = AppMutationEmitter; +pub type InitSubStateAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QInitSubState { +impl EmitAppMutationTokens for InitSubStateAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let target = &self.args.target; tokens.extend(quote! { @@ -25,7 +25,7 @@ impl EmitAppMutationTokens for QInitSubState { } } -impl ToTokens for QQInitSubState { +impl ToTokens for InitSubStateAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 8d99bf35..21a33f89 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -18,10 +18,10 @@ pub type IaInsertResource = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QInsertResource = AppMutationEmitter; -pub type QQInsertResource = AttrEmitter; +pub type InsertResourceAppMutEmitter = AppMutationEmitter; +pub type InsertResourceAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QInsertResource { +impl EmitAppMutationTokens for InsertResourceAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let resource = &self.args.args.base.resource; for concrete_path in self.args.concrete_paths() { @@ -32,7 +32,7 @@ impl EmitAppMutationTokens for QInsertResource { } } -impl ToTokens for QQInsertResource { +impl ToTokens for InsertResourceAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); let resource = &self.args.args.base.resource; diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index 3fbe2a55..608650a4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -16,10 +16,10 @@ impl AttributeIdent for NameArgs { pub type IaName = ItemAttribute, AllowStructOrEnum>; -pub type QName = AppMutationEmitter; -pub type QQName = AttrEmitter; +pub type NameAppMutEmitter = AppMutationEmitter; +pub type NameAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QName { +impl EmitAppMutationTokens for NameAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args.base; for concrete_path in self.args.concrete_paths() { @@ -46,7 +46,7 @@ impl EmitAppMutationTokens for QName { } } -impl ToTokens for QQName { +impl ToTokens for NameAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); if let Some(name) = &self.args.args.base.name { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index 4d9f545d..bd12ff8c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -15,10 +15,10 @@ pub type IaRegisterStateType = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QRegisterStateType = AppMutationEmitter; -pub type QQRegisterStateType = AttrEmitter; +pub type RegisterStateTypeAppMutEmitter = AppMutationEmitter; +pub type RegisterStateTypeAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QRegisterStateType { +impl EmitAppMutationTokens for RegisterStateTypeAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { let bevy_state = crate::__private::paths::state::root_path(); @@ -30,7 +30,7 @@ impl EmitAppMutationTokens for QRegisterStateType { } } -impl ToTokens for QQRegisterStateType { +impl ToTokens for RegisterStateTypeAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 16ea0216..1f5a2773 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -15,10 +15,10 @@ pub type IaRegisterType = ItemAttribute< Composed, AllowStructOrEnum, >; -pub type QRegisterType = AppMutationEmitter; -pub type QQRegisterType = AttrEmitter; +pub type RegisterTypeAppMutEmitter = AppMutationEmitter; +pub type RegisterTypeAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QRegisterType { +impl EmitAppMutationTokens for RegisterTypeAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -27,7 +27,7 @@ impl EmitAppMutationTokens for QRegisterType { } } } -impl ToTokens for QQRegisterType { +impl ToTokens for RegisterTypeAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index f69262df..4dcf29bb 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -13,10 +13,10 @@ impl AttributeIdent for RunOnBuildArgs { pub type IaRunOnBuild = ItemAttribute, AllowFn>; -pub type QRunOnBuild = AppMutationEmitter; -pub type QQRunOnBuild = AttrEmitter; +pub type RunOnBuildAppMutEmitter = AppMutationEmitter; +pub type RunOnBuildAttrEmitter = AttrEmitter; -impl EmitAppMutationTokens for QRunOnBuild { +impl EmitAppMutationTokens for RunOnBuildAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { @@ -26,7 +26,7 @@ impl EmitAppMutationTokens for QRunOnBuild { } } -impl ToTokens for QQRunOnBuild { +impl ToTokens for RunOnBuildAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let args = self.args.args.extra_args(); tokens.extend(quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index e83a99cd..7941b83c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -37,9 +37,9 @@ impl<'a> From<&'a ComponentArgs> for NameArgs { pub type IaComponent = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQComponent = AttrExpansionEmitter; +pub type ComponentAttrExpandEmitter = AttrExpansionEmitter; -impl AttrExpansionEmitterToExpandAttr for RewriteQComponent { +impl AttrExpansionEmitterToExpandAttr for ComponentAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index d7d22f31..ab5b40a5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -51,8 +51,8 @@ impl<'a> From<&'a EventArgs> for RegisterTypeArgs { pub type IaEvent = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQEvent = AttrExpansionEmitter; -impl AttrExpansionEmitterToExpandAttr for RewriteQEvent { +pub type EventAttrExpandEmitter = AttrExpansionEmitter; +impl AttrExpansionEmitterToExpandAttr for EventAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { if matches!(self.args.args.base.target, EventTarget::Global) { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index ab3eaee2..c529ef15 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -32,9 +32,9 @@ impl<'a> From<&'a MessageArgs> for AddMessageArgs { pub type IaMessage = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQMessage = AttrExpansionEmitter; +pub type MessageAttrExpandEmitter = AttrExpansionEmitter; -impl AttrExpansionEmitterToExpandAttr for RewriteQMessage { +impl AttrExpansionEmitterToExpandAttr for MessageAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index 240a7064..47371b45 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -25,9 +25,9 @@ impl<'a> From<&'a ObserverArgs> for AddObserverArgs { pub type IaObserver = ItemAttribute, AllowFn>; -pub type RewriteQObserver = AttrExpansionEmitter; +pub type ObserverAttrExpandEmitter = AttrExpansionEmitter; -impl AttrExpansionEmitterToExpandAttr for RewriteQObserver { +impl AttrExpansionEmitterToExpandAttr for ObserverAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { expand_attrs .attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index 2dece90d..b5dc735e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -34,8 +34,8 @@ impl<'a> From<&'a ResourceArgs> for InitResourceArgs { pub type IaResource = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQResource = AttrExpansionEmitter; -impl AttrExpansionEmitterToExpandAttr for RewriteQResource { +pub type ResourceAttrExpandEmitter = AttrExpansionEmitter; +impl AttrExpansionEmitterToExpandAttr for ResourceAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index cf5e4b7a..eff69999 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -32,8 +32,8 @@ impl<'a> From<&'a StatesArgs> for InitStateArgs { } pub type IaState = ItemAttribute, AllowStructOrEnum>; -pub type RewriteQState = AttrExpansionEmitter; -impl AttrExpansionEmitterToExpandAttr for RewriteQState { +pub type StateAttrExpandEmitter = AttrExpansionEmitter; +impl AttrExpansionEmitterToExpandAttr for StateAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { expand_attrs.append(tokens::derive_states(&self.args.args.base.derive.items)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 285f8565..40c80cc1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -30,9 +30,9 @@ impl<'a> From<&'a SystemArgs> for AddSystemArgs { pub type IaSystem = ItemAttribute, AllowFn>; -pub type RewriteQSystem = AttrExpansionEmitter; +pub type SystemAttrExpandEmitter = AttrExpansionEmitter; -impl AttrExpansionEmitterToExpandAttr for RewriteQSystem { +impl AttrExpansionEmitterToExpandAttr for SystemAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { expand_attrs .attrs From dba99719aeb62653529b0656d8bfbd77bb2a7d74 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 13:24:17 -0400 Subject: [PATCH 100/162] refactor: consolidate `context` and `macro_paths` imports using prelude modules --- .../bevy_auto_plugin_shared/src/macro_api/context/mod.rs | 7 ++++++- crates/bevy_auto_plugin_shared/src/macro_api/mod.rs | 6 +----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs index 0a98eaca..8aa9806c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs @@ -1,8 +1,13 @@ use macro_paths::MacroPaths; -pub mod macro_paths; +mod macro_paths; #[derive(Debug, Clone, Default, PartialEq, Hash)] pub struct Context { pub macros: MacroPaths, } + +pub mod prelude { + pub use super::Context; + pub use super::macro_paths::*; +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs index f52ffd2e..374e115b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mod.rs @@ -9,13 +9,9 @@ mod schedule_config; pub(crate) mod prelude { use super::*; - pub use crate::macro_api::context::macro_paths::*; - pub use crate::macro_api::emitters::app_mutation::*; - pub use crate::macro_api::emitters::attr::*; - pub use crate::macro_api::emitters::attr_expansion::*; pub use attributes::prelude::*; pub use composed::*; - pub use context::*; + pub use context::prelude::*; pub use derives::prelude::*; pub use emitters::prelude::*; pub use input_item::*; From 2bda5cde4a630e3bfb9588793d4a427182f69d66 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 13:26:27 -0400 Subject: [PATCH 101/162] refactor: prevent unreachable statement warnings in ToTokens for ConfigureSystemSetAttrEmitter --- .../macro_api/attributes/actions/auto_configure_system_set.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 0c69461c..5ae94628 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -197,8 +197,6 @@ impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { impl ToTokens for ConfigureSystemSetAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); - todo!("not implemented"); - // TODO: cleanup args.extend( self.args .args @@ -210,6 +208,8 @@ impl ToTokens for ConfigureSystemSetAttrEmitter { #(#args),* }); *tokens = self.wrap_as_attr(tokens); + todo!("not implemented"); + // TODO: would need to modify item to inject helper attributes } } From f9f7c5cfef8ab7b3be05ed3ed241e582fba5eb02 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 13:27:16 -0400 Subject: [PATCH 102/162] refactor: make `AppMutationEmitter` struct public to match `proc_attribute_outer` vis --- .../src/macro_api/emitters/app_mutation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs index ac37f6c5..9581554f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs @@ -5,7 +5,7 @@ use quote::{ToTokens, format_ident}; /// for codegen attaching to bevy app #[derive(Debug, Clone)] -pub(crate) struct AppMutationEmitter { +pub struct AppMutationEmitter { pub(crate) args: T, // TODO: maybe app params should just be part of another wrapper struct? pub(crate) app_param: syn::Ident, From e6b738f006a337e8f41b3359916b83e3200e7a0a Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 13:27:52 -0400 Subject: [PATCH 103/162] refactor: make `AttrExpansionEmitter` struct public to match `proc_attribute_rewrite_outer` vis --- .../src/macro_api/emitters/attr_expansion.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs index d529ee8d..eb24e21e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs @@ -6,7 +6,7 @@ use std::marker::PhantomData; /// for codegen rewriting attrs #[derive(Debug, Clone)] -pub(crate) struct AttrExpansionEmitter { +pub struct AttrExpansionEmitter { pub(crate) args: T, } From 825717b9140b2dc706701b2998b4b97fd910b6cb Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 13:28:12 -0400 Subject: [PATCH 104/162] refactor: remove unused `into_tuple` method from `InflateArgsOutput` struct --- .../attributes/actions/auto_configure_system_set.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 5ae94628..26118e45 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -238,12 +238,6 @@ pub struct InflateArgsOutput { inflated_args: ConfigureSystemSetArgs, } -impl InflateArgsOutput { - pub fn into_tuple(self) -> (ConfigureSystemSetArgs, TokenStream) { - (self.inflated_args, self.scrubbed_tokens) - } -} - pub fn inflate_args_from_input( mut args: ConfigureSystemSetArgs, input: TokenStream, From 5dad0ced7215a6d49769b5632e1b766224e68a96 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 13:29:25 -0400 Subject: [PATCH 105/162] refactor: remove `item` module and related `resolve_ident_from_struct_or_enum` usage --- .../src/syntax/analysis/item.rs | 37 ------------------- .../src/syntax/analysis/mod.rs | 1 - .../src/syntax/parse/scrub_helpers.rs | 5 +-- 3 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs deleted file mode 100644 index 4453844b..00000000 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs +++ /dev/null @@ -1,37 +0,0 @@ -use proc_macro2::Ident; -use syn::Item; -use syn::spanned::Spanned; -use thiserror::Error; - -#[derive(Error, Debug, PartialEq, Copy, Clone)] -pub enum ResolveIdentFromItemError<'a> { - #[error("Expected function")] - NotFn(&'a Item), - #[error("Expected Struct or Enum")] - NotStructOrEnum(&'a Item), -} - -impl ResolveIdentFromItemError<'_> { - pub fn span(&self) -> proc_macro2::Span { - match self { - Self::NotFn(item) => item.span(), - Self::NotStructOrEnum(item) => item.span(), - } - } -} - -impl From> for syn::Error { - fn from(value: ResolveIdentFromItemError) -> Self { - Self::new(value.span(), value.to_string()) - } -} - -pub type IdentFromItemResult<'a> = Result<&'a Ident, ResolveIdentFromItemError<'a>>; - -pub fn resolve_ident_from_struct_or_enum(item: &Item) -> IdentFromItemResult<'_> { - match item { - Item::Struct(s) => Ok(&s.ident), - Item::Enum(e) => Ok(&e.ident), - _ => Err(ResolveIdentFromItemError::NotStructOrEnum(item)), - } -} diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs index 2294853b..be9d8276 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs @@ -1,4 +1,3 @@ pub mod fn_param; -pub mod item; pub mod path; pub mod ty_classify; diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index b4aea89f..72049f2f 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -448,7 +448,6 @@ pub fn parse_removed_as( #[cfg(test)] mod tests { use super::*; - use crate::syntax::analysis::item::resolve_ident_from_struct_or_enum; use crate::syntax::extensions::path::PathExt; use internal_test_proc_macro::xtest; use quote::{ToTokens, quote}; @@ -541,9 +540,7 @@ mod tests { } fn resolve_ident(item: &Item) -> syn::Result<&Ident> { - resolve_ident_from_struct_or_enum(item).map_err(|err| { - syn::Error::new(item.span(), format!("failed to resolve ident: {err}")) - }) + item.ident() } #[xtest] From d6323bc80873b199e8eff4f39ba510900c223406 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 14:07:42 -0400 Subject: [PATCH 106/162] chore(config): add `rustfmt.toml` for consistent formatting rules --- rustfmt.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..4eb77fda --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,10 @@ +use_small_heuristics = "Max" # prefer breaking earlier +normalize_comments = true +use_field_init_shorthand = true +newline_style = "Unix" +style_edition = "2024" + +unstable_features = true +imports_granularity = "Crate" # consolidate use by crate +reorder_imports = true # required to merge imports +imports_layout = "Vertical" # one per line in braces (if any) \ No newline at end of file From 9b303d42af6026fba0dc102f653f7d262204dfe9 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 14:08:02 -0400 Subject: [PATCH 107/162] refactor: apply rustfmt --- build.rs | 5 +- .../bevy_auto_plugin_proc_macros/src/lib.rs | 6 +- .../src/__private/auto_plugin_registry.rs | 60 +++--- .../src/__private/expand/attr/action.rs | 22 +- .../__private/expand/attr/auto_bind_plugin.rs | 18 +- .../src/__private/expand/attr/auto_plugin.rs | 25 ++- .../src/__private/expand/attr/mod.rs | 23 +- .../src/__private/expand/attr/rewrite.rs | 6 +- .../__private/expand/derive/auto_plugin.rs | 12 +- .../src/codegen/mod.rs | 5 +- .../src/codegen/tokens.rs | 50 ++--- .../attributes/actions/auto_add_message.rs | 5 +- .../attributes/actions/auto_add_observer.rs | 5 +- .../attributes/actions/auto_add_plugin.rs | 11 +- .../attributes/actions/auto_add_system.rs | 19 +- .../actions/auto_configure_system_set.rs | 113 +++++----- .../attributes/actions/auto_init_resource.rs | 14 +- .../attributes/actions/auto_init_state.rs | 5 +- .../attributes/actions/auto_init_sub_state.rs | 5 +- .../actions/auto_insert_resource.rs | 11 +- .../macro_api/attributes/actions/auto_name.rs | 37 ++-- .../actions/auto_register_state_type.rs | 5 +- .../attributes/actions/auto_register_type.rs | 5 +- .../attributes/actions/auto_run_on_build.rs | 5 +- .../src/macro_api/attributes/auto_plugin.rs | 45 ++-- .../src/macro_api/attributes/mod.rs | 95 ++++---- .../attributes/rewrites/auto_component.rs | 33 +-- .../attributes/rewrites/auto_event.rs | 41 ++-- .../attributes/rewrites/auto_message.rs | 29 +-- .../attributes/rewrites/auto_observer.rs | 15 +- .../attributes/rewrites/auto_resource.rs | 29 +-- .../attributes/rewrites/auto_states.rs | 25 ++- .../attributes/rewrites/auto_system.rs | 25 +-- .../src/macro_api/composed.rs | 44 ++-- .../src/macro_api/context/macro_paths.rs | 6 +- .../src/macro_api/context/mod.rs | 6 +- .../src/macro_api/derives/auto_plugin.rs | 15 +- .../src/macro_api/derives/mod.rs | 8 +- .../src/macro_api/emitters/app_mutation.rs | 21 +- .../src/macro_api/emitters/attr.rs | 23 +- .../src/macro_api/emitters/attr_expansion.rs | 18 +- .../src/macro_api/emitters/mod.rs | 8 +- .../src/macro_api/input_item.rs | 11 +- .../src/macro_api/mixins/generics/none.rs | 28 ++- .../macro_api/mixins/generics/with_many.rs | 21 +- .../macro_api/mixins/generics/with_single.rs | 29 +-- .../src/macro_api/mixins/nothing.rs | 10 +- .../src/macro_api/mixins/with_plugin.rs | 5 +- .../src/macro_api/schedule_config.rs | 10 +- .../src/syntax/analysis/fn_param.rs | 13 +- .../src/syntax/analysis/path.rs | 6 +- .../src/syntax/analysis/ty_classify.rs | 13 +- .../src/syntax/ast/any_expr.rs | 5 +- .../src/syntax/ast/expr_path_or_call.rs | 35 +-- .../src/syntax/ast/expr_value.rs | 26 ++- .../src/syntax/ast/flag.rs | 46 ++-- .../src/syntax/ast/flag_or_expr.rs | 41 ++-- .../src/syntax/ast/flag_or_list.rs | 56 ++--- .../src/syntax/ast/flag_or_lit.rs | 54 ++--- .../src/syntax/ast/flag_or_meta.rs | 84 +++----- .../src/syntax/ast/type_list.rs | 43 ++-- .../src/syntax/diagnostic/kind.rs | 6 +- .../src/syntax/extensions/generics.rs | 14 +- .../src/syntax/extensions/item.rs | 8 +- .../src/syntax/extensions/path.rs | 6 +- .../src/syntax/parse/item.rs | 15 +- .../src/syntax/parse/scrub_helpers.rs | 204 ++++++------------ .../src/syntax/validated/non_empty_path.rs | 49 +++-- .../syntax/validated/path_without_generics.rs | 27 +-- .../src/test_util/combo.rs | 6 +- .../src/util/macros.rs | 15 +- crates/internal_test_proc_macro/src/lib.rs | 6 +- crates/internal_test_util/src/lib.rs | 23 +- crates/internal_test_util/src/ui_util.rs | 35 ++- tests/e2e/auto_add_message_generic.rs | 6 +- tests/e2e/auto_add_observer.rs | 17 +- tests/e2e/auto_add_plugin.rs | 5 +- .../e2e/auto_add_plugin_with_default_init.rs | 6 +- tests/e2e/auto_add_plugin_with_init.rs | 6 +- .../auto_add_systems_complex_with_generics.rs | 9 +- tests/e2e/auto_add_systems_with_generics.rs | 9 +- tests/e2e/auto_add_systems_with_set.rs | 5 +- tests/e2e/auto_bind_plugin.rs | 48 ++--- tests/e2e/auto_component.rs | 16 +- ...tem_set_schedule_config_multiple_groups.rs | 6 +- tests/e2e/auto_init_resource.rs | 5 +- tests/e2e/auto_init_resource_generic.rs | 5 +- tests/e2e/auto_init_state.rs | 16 +- tests/e2e/auto_init_sub_state.rs | 45 +--- tests/e2e/auto_insert_resource.rs | 6 +- tests/e2e/auto_name.rs | 16 +- tests/e2e/auto_name_with_generics.rs | 11 +- tests/e2e/auto_plugin.rs | 61 ++---- tests/e2e/auto_plugin_param.rs | 5 +- tests/e2e/auto_plugin_with_generics.rs | 90 +++----- tests/e2e/auto_register_state_type.rs | 6 +- tests/e2e/auto_register_type.rs | 5 +- tests/e2e/auto_register_type_generic.rs | 5 +- tests/e2e/auto_run_on_build_with_generics.rs | 10 +- tests/e2e/auto_system_schedule_multiple.rs | 10 +- tests/e2e/auto_system_schedule_non_path.rs | 10 +- tests/e2e/auto_system_schedule_on_state.rs | 4 +- tests/e2e/bare_fn.rs | 5 +- tests/e2e/bare_fn_default_app_param.rs | 5 +- tests/e2e/self_impl_plugin.rs | 5 +- .../e2e/self_impl_plugin_default_app_param.rs | 5 +- tests/e2e/self_impl_plugin_with_generics.rs | 5 +- tests/e2e/ui_tests.rs | 6 +- 108 files changed, 1134 insertions(+), 1248 deletions(-) diff --git a/build.rs b/build.rs index e59de1e8..28a5cf2c 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,7 @@ -use rustc_version::{Channel, version_meta}; +use rustc_version::{ + Channel, + version_meta, +}; fn main() { println!("cargo:rustc-check-cfg=cfg(nightly)"); diff --git a/crates/bevy_auto_plugin_proc_macros/src/lib.rs b/crates/bevy_auto_plugin_proc_macros/src/lib.rs index c508a707..f7e65967 100644 --- a/crates/bevy_auto_plugin_proc_macros/src/lib.rs +++ b/crates/bevy_auto_plugin_proc_macros/src/lib.rs @@ -171,9 +171,5 @@ pub fn auto_run_on_build(attr: CompilerStream, input: CompilerStream) -> Compile #[doc = include_str!("../docs/proc_attributes/auto_bind_plugin.md")] #[proc_macro_attribute] pub fn auto_bind_plugin(attr: CompilerStream, input: CompilerStream) -> CompilerStream { - handle_attribute( - expand::attr::auto_bind_plugin::auto_bind_plugin_outer, - attr, - input, - ) + handle_attribute(expand::attr::auto_bind_plugin::auto_bind_plugin_outer, attr, input) } diff --git a/crates/bevy_auto_plugin_shared/src/__private/auto_plugin_registry.rs b/crates/bevy_auto_plugin_shared/src/__private/auto_plugin_registry.rs index 067304e6..6e976da0 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/auto_plugin_registry.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/auto_plugin_registry.rs @@ -1,11 +1,22 @@ // derived from Bevy Butler - MIT/Apache 2.0 https://github.com/TGRCdev/bevy-butler/blob/4eca26421d275134e0adc907e8c851bdcf10823a/bevy-butler/src/__private/plugin.rs -use proc_macro2::{Ident, TokenStream as MacroStream}; +use proc_macro2::{ + Ident, + TokenStream as MacroStream, +}; use quote::quote; -use std::any::{TypeId, type_name}; -use std::collections::HashMap; -use std::sync::LazyLock; -use syn::{ExprClosure, Path}; +use std::{ + any::{ + TypeId, + type_name, + }, + collections::HashMap, + sync::LazyLock, +}; +use syn::{ + ExprClosure, + Path, +}; pub use bevy_app; #[cfg(any(target_arch = "wasm32", feature = "inventory"))] @@ -34,10 +45,7 @@ pub static AUTO_PLUGIN_REGISTRY: LazyLock = LazyLock::new(|| let mut registry: HashMap> = HashMap::new(); for (ix, AutoPluginRegistryEntryFactory(type_factory, sys_factory)) in iter.enumerate() { - registry - .entry(type_factory()) - .or_default() - .push(*sys_factory); + registry.entry(type_factory()).or_default().push(*sys_factory); #[allow(unused_assignments)] { count = ix + 1; @@ -80,12 +88,9 @@ pub trait AutoPlugin: AutoPluginTypeId { } fn static_build(app: &mut bevy_app::App) { let type_id = ::type_id(); - AUTO_PLUGIN_REGISTRY - .get_entries(type_id) - .iter() - .for_each(|build_fn| { - build_fn(app); - }); + AUTO_PLUGIN_REGISTRY.get_entries(type_id).iter().for_each(|build_fn| { + build_fn(app); + }); } } @@ -102,10 +107,7 @@ pub struct AutoPluginRegistry(HashMap>); impl AutoPluginRegistry { pub(crate) fn get_entries(&'static self, marker: TypeId) -> &'static [BevyAppBuildFn] { - self.0 - .get(&marker) - .map(|v| v.as_slice()) - .unwrap_or_default() + self.0.get(&marker).map(|v| v.as_slice()).unwrap_or_default() } } @@ -125,15 +127,17 @@ pub fn _plugin_entry_block(static_ident: &Ident, plugin: &Path, expr: &ExprClosu #[macro_export] #[doc(hidden)] macro_rules! _plugin_entry { - ($static_ident:ident, $entry:expr) => { - #[::bevy_auto_plugin::__private::shared::__private::auto_plugin_registry::linkme::distributed_slice(::bevy_auto_plugin::__private::shared::__private::auto_plugin_registry::AUTO_PLUGINS)] - #[linkme(crate = ::bevy_auto_plugin::__private::shared::__private::auto_plugin_registry::linkme)] - #[allow(non_upper_case_globals)] - static $static_ident: - ::bevy_auto_plugin::__private::shared::__private::auto_plugin_registry::AutoPluginRegistryEntryFactory = - $entry; - }; - } + ($static_ident:ident, $entry:expr) => { + #[::bevy_auto_plugin::__private::shared::__private::auto_plugin_registry::linkme::distributed_slice( + ::bevy_auto_plugin::__private::shared::__private::auto_plugin_registry::AUTO_PLUGINS + )] + #[linkme(crate = ::bevy_auto_plugin::__private::shared::__private::auto_plugin_registry::linkme)] + #[allow(non_upper_case_globals)] + static $static_ident: + ::bevy_auto_plugin::__private::shared::__private::auto_plugin_registry::AutoPluginRegistryEntryFactory = + $entry; + }; +} #[cfg(any(target_arch = "wasm32", feature = "inventory"))] #[macro_export] diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs index 40c579d8..3eefcb37 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs @@ -1,7 +1,12 @@ -use crate::macro_api::prelude::*; -use crate::util::macros::ok_or_emit_with; +use crate::{ + macro_api::prelude::*, + util::macros::ok_or_emit_with, +}; use proc_macro2::TokenStream as MacroStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; pub fn proc_attribute_outer(attr: MacroStream, input: MacroStream) -> MacroStream where @@ -20,16 +25,11 @@ where ); let mut app_mut_emitter = AppMutationEmitter::from_args(args); let processed_item = { - ok_or_emit_with!( - app_mut_emitter.item_post_process(), - app_mut_emitter.args.input_item() - ); + ok_or_emit_with!(app_mut_emitter.item_post_process(), app_mut_emitter.args.input_item()); app_mut_emitter.args.input_item().to_token_stream() }; - let after_item_tokens = ok_or_emit_with!( - app_mut_emitter.wrap_body(|body| quote! { #body }), - processed_item - ); + let after_item_tokens = + ok_or_emit_with!(app_mut_emitter.wrap_body(|body| quote! { #body }), processed_item); quote! { #processed_item #after_item_tokens diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index a4313b21..6d974eb4 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -1,7 +1,9 @@ -use crate::__private::expand::attr; -use crate::macro_api::prelude::*; -use crate::syntax::extensions::item::ItemAttrsExt; -use crate::util::macros::compile_error_with; +use crate::{ + __private::expand::attr, + macro_api::prelude::*, + syntax::extensions::item::ItemAttrsExt, + util::macros::compile_error_with, +}; use proc_macro2::TokenStream as MacroStream; use quote::ToTokens; use syn::spanned::Spanned; @@ -21,15 +23,11 @@ pub fn auto_bind_plugin_inner( let plugin_path = item_attribute.args.plugin(); let item = item_attribute.input_item.ensure_ast_mut()?; - let mut attrs = item - .take_attrs() - .map_err(|err| syn::Error::new(item.span(), err))?; + let mut attrs = item.take_attrs().map_err(|err| syn::Error::new(item.span(), err))?; attr::attrs_inject_plugin_param(&mut attrs, plugin_path); - let Ok(_) = item.put_attrs(attrs) else { - unreachable!() - }; + let Ok(_) = item.put_attrs(attrs) else { unreachable!() }; Ok(item.to_token_stream()) } diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs index de7c104d..c6c1f66c 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs @@ -1,14 +1,23 @@ -use crate::util::macros::{compile_error_with, ok_or_emit_with, parse_macro_input2_or_emit_with}; +use crate::util::macros::{ + compile_error_with, + ok_or_emit_with, + parse_macro_input2_or_emit_with, +}; use proc_macro2::TokenStream as MacroStream; use syn::ItemFn; pub fn expand_auto_plugin(attr: MacroStream, input: MacroStream) -> MacroStream { - use crate::macro_api::prelude::*; - use crate::syntax::analysis::fn_param::require_fn_param_mutable_reference; + use crate::{ + macro_api::prelude::*, + syntax::analysis::fn_param::require_fn_param_mutable_reference, + }; use proc_macro2::Ident; use quote::quote; - use syn::spanned::Spanned; - use syn::{FnArg, parse2}; + use syn::{ + FnArg, + parse2, + spanned::Spanned, + }; let og_input = input.clone(); let item = parse_macro_input2_or_emit_with!(input as ItemFn, og_input); let params = ok_or_emit_with!(parse2::(attr), og_input); @@ -29,10 +38,8 @@ pub fn expand_auto_plugin(attr: MacroStream, input: MacroStream) -> MacroStream let self_arg = self_args.first(); // TODO: use helper - let app_param_ident = ok_or_emit_with!( - resolve_app_param_name(&item, params.app_param.as_ref()), - og_input - ); + let app_param_ident = + ok_or_emit_with!(resolve_app_param_name(&item, params.app_param.as_ref()), og_input); if let Err(err) = require_fn_param_mutable_reference(&item, app_param_ident, "bevy app") { return compile_error_with!(err, og_input); diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index ed5383ca..ce3f099a 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -10,12 +10,7 @@ pub fn attrs_inject_plugin_param(attrs: &mut Vec, plugin: &syn:: use syn::Meta; for attr in attrs { - let last = attr - .path() - .segments - .last() - .map(|s| s.ident.to_string()) - .unwrap_or_default(); + let last = attr.path().segments.last().map(|s| s.ident.to_string()).unwrap_or_default(); if !last.starts_with("auto_") { continue; @@ -36,8 +31,10 @@ pub fn attrs_inject_plugin_param(attrs: &mut Vec, plugin: &syn:: } fn attr_inject_plugin_param(attr: &mut syn::Attribute, plugin: &syn::Path) { - use syn::Meta; - use syn::parse_quote; + use syn::{ + Meta, + parse_quote, + }; match &attr.meta { Meta::Path(path) => *attr = parse_quote!( #[#path(plugin = #plugin)] ), Meta::List(ml) => { @@ -54,10 +51,12 @@ fn attr_inject_plugin_param(attr: &mut syn::Attribute, plugin: &syn::Path) { } fn list_has_key(ml: &syn::MetaList, key: &str) -> bool { - use syn::Meta; - use syn::Token; - use syn::parse::Parser; - use syn::punctuated::Punctuated; + use syn::{ + Meta, + Token, + parse::Parser, + punctuated::Punctuated, + }; let parser = Punctuated::::parse_terminated; match parser.parse2(ml.tokens.clone()) { Ok(list) => list.iter().any(|m| match m { diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/rewrite.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/rewrite.rs index 499883a4..32e61183 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/rewrite.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/rewrite.rs @@ -1,5 +1,7 @@ -use crate::macro_api::prelude::*; -use crate::util::macros::ok_or_emit_with; +use crate::{ + macro_api::prelude::*, + util::macros::ok_or_emit_with, +}; use proc_macro2::TokenStream as MacroStream; use quote::ToTokens; diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs index ada8e8c6..427c3b8c 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs @@ -3,8 +3,10 @@ use proc_macro2::TokenStream as MacroStream; use syn::spanned::Spanned; pub fn expand_derive_auto_plugin(input: MacroStream) -> MacroStream { - use crate::macro_api::prelude::*; - use crate::syntax::extensions::generics; + use crate::{ + macro_api::prelude::*, + syntax::extensions::generics, + }; use darling::FromDeriveInput; use quote::quote; use syn::DeriveInput; @@ -22,11 +24,7 @@ pub fn expand_derive_auto_plugin(input: MacroStream) -> MacroStream { let mut compile_warnings = quote! {}; #[allow(deprecated)] - if params - .auto_plugin - .impl_generic_auto_plugin_trait - .is_present() - { + if params.auto_plugin.impl_generic_auto_plugin_trait.is_present() { compile_warnings.extend( syn::Error::new( params.auto_plugin.impl_generic_auto_plugin_trait.span(), diff --git a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs index a490b105..8661f225 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs @@ -1,7 +1,10 @@ pub mod tokens; use proc_macro2::TokenStream as MacroStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(Debug, Default, Clone)] pub struct ExpandAttrs { diff --git a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs index db954fc8..16fa2a97 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs @@ -1,8 +1,16 @@ -use crate::codegen::ExpandAttrs; -use crate::macro_api::prelude::*; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use proc_macro2::{Ident, TokenStream}; -use quote::{ToTokens, quote}; +use crate::{ + codegen::ExpandAttrs, + macro_api::prelude::*, + syntax::validated::non_empty_path::NonEmptyPath, +}; +use proc_macro2::{ + Ident, + TokenStream, +}; +use quote::{ + ToTokens, + quote, +}; use syn::parse_quote; pub fn reflect<'a>(idents: impl IntoIterator) -> ExpandAttrs { @@ -81,49 +89,27 @@ pub fn derive_component<'a>( extra_items: impl IntoIterator, ) -> TokenStream { derive_from( - [ - vec![&derive_component_path()], - extra_items.into_iter().collect::>(), - ] - .concat(), + [vec![&derive_component_path()], extra_items.into_iter().collect::>()].concat(), ) } pub fn derive_resource<'a>(extra_items: impl IntoIterator) -> TokenStream { derive_from( - [ - vec![&derive_resource_path()], - extra_items.into_iter().collect::>(), - ] - .concat(), + [vec![&derive_resource_path()], extra_items.into_iter().collect::>()].concat(), ) } pub fn derive_event<'a>(extra_items: impl IntoIterator) -> TokenStream { - derive_from( - [ - vec![&derive_event_path()], - extra_items.into_iter().collect::>(), - ] - .concat(), - ) + derive_from([vec![&derive_event_path()], extra_items.into_iter().collect::>()].concat()) } pub fn derive_entity_event<'a>( extra_items: impl IntoIterator, ) -> TokenStream { derive_from( - [ - vec![&derive_entity_event_path()], - extra_items.into_iter().collect::>(), - ] - .concat(), + [vec![&derive_entity_event_path()], extra_items.into_iter().collect::>()].concat(), ) } pub fn derive_message<'a>(extra_items: impl IntoIterator) -> TokenStream { derive_from( - [ - vec![&derive_message_path()], - extra_items.into_iter().collect::>(), - ] - .concat(), + [vec![&derive_message_path()], extra_items.into_iter().collect::>()].concat(), ) } pub fn derive_states<'a>(extra_items: impl IntoIterator) -> ExpandAttrs { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs index d1845d0f..2bccfc79 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_message.rs @@ -1,7 +1,10 @@ use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs index 4dfba80f..5cda7dd4 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_observer.rs @@ -1,7 +1,10 @@ use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs index 3baac2db..de881017 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_plugin.rs @@ -1,8 +1,13 @@ -use crate::macro_api::prelude::*; -use crate::syntax::ast::flag_or_expr::FlagOrExpr; +use crate::{ + macro_api::prelude::*, + syntax::ast::flag_or_expr::FlagOrExpr, +}; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs index 21fbcbcf..f1d2c053 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_add_system.rs @@ -1,8 +1,13 @@ -use crate::macro_api::prelude::*; -use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; +use crate::macro_api::{ + prelude::*, + schedule_config::ScheduleWithScheduleConfigArgs, +}; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -36,13 +41,7 @@ impl ToTokens for AddSystemAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); // TODO: cleanup - args.extend( - self.args - .args - .base - .schedule_config - .to_inner_arg_tokens_vec(), - ); + args.extend(self.args.args.base.schedule_config.to_inner_arg_tokens_vec()); tokens.extend(quote! { #(#args),* }); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 26118e45..f8fc6f2b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,14 +1,39 @@ -use crate::macro_api::prelude::*; -use crate::macro_api::schedule_config::{ScheduleConfigArgs, ScheduleWithScheduleConfigArgs}; -use crate::syntax::ast::flag::Flag; -use crate::syntax::extensions::item::ItemAttrsExt; -use crate::syntax::parse::item::item_has_attr; -use crate::syntax::parse::scrub_helpers::{AttrSite, scrub_helpers_and_ident_with_filter}; +use crate::{ + macro_api::{ + prelude::*, + schedule_config::{ + ScheduleConfigArgs, + ScheduleWithScheduleConfigArgs, + }, + }, + syntax::{ + ast::flag::Flag, + extensions::item::ItemAttrsExt, + parse::{ + item::item_has_attr, + scrub_helpers::{ + AttrSite, + scrub_helpers_and_ident_with_filter, + }, + }, + }, +}; use darling::FromMeta; -use proc_macro2::{Ident, TokenStream}; -use quote::{ToTokens, quote}; -use syn::spanned::Spanned; -use syn::{Attribute, Item, Path, parse_quote}; +use proc_macro2::{ + Ident, + TokenStream, +}; +use quote::{ + ToTokens, + quote, +}; +use syn::{ + Attribute, + Item, + Path, + parse_quote, + spanned::Spanned, +}; const CONFIG_ATTR_NAME: &str = "auto_configure_system_set_config"; const CHAIN_CONFLICT_ERR: &str = "`chain` and `chain_ignore_deferred` are mutually exclusive"; @@ -184,12 +209,7 @@ impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { }; let generics = self.args.args.generics(); for concrete_path in self.args.concrete_paths() { - tokens.extend(output( - &inflated_args, - app_param, - &concrete_path, - !generics.is_empty(), - )); + tokens.extend(output(&inflated_args, app_param, &concrete_path, !generics.is_empty())); } } } @@ -197,13 +217,7 @@ impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { impl ToTokens for ConfigureSystemSetAttrEmitter { fn to_tokens(&self, tokens: &mut TokenStream) { let mut args = self.args.args.extra_args(); - args.extend( - self.args - .args - .base - .schedule_config - .to_inner_arg_tokens_vec(), - ); + args.extend(self.args.args.base.schedule_config.to_inner_arg_tokens_vec()); tokens.extend(quote! { #(#args),* }); @@ -274,10 +288,7 @@ pub fn inflate_args_from_input( // 4) If it's a struct, there are no entries to compute let data_enum = match scrub.item { Item::Struct(_) => { - return Ok(InflateArgsOutput { - inflated_args: args, - scrubbed_tokens, - }); + return Ok(InflateArgsOutput { inflated_args: args, scrubbed_tokens }); } Item::Enum(ref en) => en, _ => unreachable!("resolve_ident_from_struct_or_enum guarantees struct|enum"), @@ -306,9 +317,7 @@ pub fn inflate_args_from_input( // Treat a second helper on the same (variant, group or None) as a hard error. for (observed_index, site) in scrub.all_with_removed_attrs().into_iter().enumerate() { if let AttrSite::Variant { variant } = &site.site { - observed_order_by_variant - .entry(variant.clone()) - .or_insert(observed_index); + observed_order_by_variant.entry(variant.clone()).or_insert(observed_index); for attr in &site.attrs { // Only care about our helper @@ -320,11 +329,8 @@ pub fn inflate_args_from_input( // If order wasn't provided on the helper, set it to the first observed index for this variant if entry.order.is_none() { - entry.order = Some( - *observed_order_by_variant - .get(variant) - .unwrap_or(&observed_index), - ); + entry.order = + Some(*observed_order_by_variant.get(variant).unwrap_or(&observed_index)); } let bucket = variants_cfg.entry(variant.clone()).or_default(); @@ -367,9 +373,8 @@ pub fn inflate_args_from_input( let prev_observed_len = observed_order_by_variant.len(); // Find observed order for this variant (if we never saw the site, use sequential fallback) - let observed = *observed_order_by_variant - .entry(v_ident.clone()) - .or_insert_with(|| prev_observed_len); + let observed = + *observed_order_by_variant.entry(v_ident.clone()).or_insert_with(|| prev_observed_len); let chosen_entry = (|| { let bucket = variants_cfg.get(&v_ident); @@ -417,17 +422,18 @@ pub fn inflate_args_from_input( // 8) Store into args and return args.inner = Some(ConfigureSystemSetArgsInner { entries }); - Ok(InflateArgsOutput { - inflated_args: args, - scrubbed_tokens, - }) + Ok(InflateArgsOutput { inflated_args: args, scrubbed_tokens }) } #[cfg(test)] mod tests { use super::*; use internal_test_proc_macro::xtest; - use syn::{Path, parse_quote, parse2}; + use syn::{ + Path, + parse_quote, + parse2, + }; fn ident_and_args_from_attr_input( attr: TokenStream, @@ -462,12 +468,7 @@ mod tests { fn test_to_tokens_single() -> syn::Result<()> { let args = parse2::(quote!(schedule = Update))?; let app_param = parse_quote!(app); - let tokens = output( - &args, - &app_param, - &parse_quote!(FooTarget::), - true, - ); + let tokens = output(&args, &app_param, &parse_quote!(FooTarget::), true); assert_eq!( tokens.to_string(), quote! { @@ -482,12 +483,7 @@ mod tests { fn test_to_tokens_multiple() -> syn::Result<()> { let args = parse2::(quote!(schedule = Update))?; let app_param = parse_quote!(app); - let tokens = output( - &args, - &app_param, - &parse_quote!(FooTarget::), - true, - ); + let tokens = output(&args, &app_param, &parse_quote!(FooTarget::), true); assert_eq!( tokens.to_string(), quote! { @@ -495,12 +491,7 @@ mod tests { } .to_string() ); - let tokens = output( - &args, - &app_param, - &parse_quote!(FooTarget::), - true, - ); + let tokens = output(&args, &app_param, &parse_quote!(FooTarget::), true); assert_eq!( tokens.to_string(), quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs index 416273d9..1b7fde56 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_resource.rs @@ -1,8 +1,16 @@ -use crate::macro_api::emitters::app_mutation::{AppMutationEmitter, EmitAppMutationTokens}; -use crate::macro_api::prelude::*; +use crate::macro_api::{ + emitters::app_mutation::{ + AppMutationEmitter, + EmitAppMutationTokens, + }, + prelude::*, +}; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs index 04ba582e..f9a4aa3b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_state.rs @@ -1,7 +1,10 @@ use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs index 786f9464..6446ec04 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_init_sub_state.rs @@ -1,7 +1,10 @@ use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 21a33f89..801bbb20 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -1,8 +1,13 @@ -use crate::macro_api::prelude::*; -use crate::syntax::ast::any_expr::AnyExprCallClosureMacroPath; +use crate::{ + macro_api::prelude::*, + syntax::ast::any_expr::AnyExprCallClosureMacroPath, +}; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs index 608650a4..0922b4c3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_name.rs @@ -1,8 +1,13 @@ -use crate::macro_api::prelude::*; -use crate::syntax::extensions::lit::LitExt; +use crate::{ + macro_api::prelude::*, + syntax::extensions::lit::LitExt, +}; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -23,21 +28,17 @@ impl EmitAppMutationTokens for NameAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { let args = &self.args.args.base; for concrete_path in self.args.concrete_paths() { - let name = args - .name - .as_ref() - .map(|name| name.unquoted_string()) - .unwrap_or_else(|| { - // TODO: move to util fn - quote!(#concrete_path) - .to_string() - .replace(" :: < ", "<") - .replace(" < ", "<") - .replace(" >", ">") - .replace(" ,", ",") - // TODO: offer option to only remove all spaces? - // .replace(" ", "") - }); + let name = args.name.as_ref().map(|name| name.unquoted_string()).unwrap_or_else(|| { + // TODO: move to util fn + quote!(#concrete_path) + .to_string() + .replace(" :: < ", "<") + .replace(" < ", "<") + .replace(" >", ">") + .replace(" ,", ",") + // TODO: offer option to only remove all spaces? + // .replace(" ", "") + }); let bevy_ecs = crate::__private::paths::ecs::ecs_root_path(); tokens.extend(quote! { #app_param.register_required_components_with::<#concrete_path, #bevy_ecs::prelude::Name>(|| #bevy_ecs::prelude::Name::new(#name)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs index bd12ff8c..2fcfb582 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_state_type.rs @@ -1,7 +1,10 @@ use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs index 1f5a2773..3ce3a864 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_register_type.rs @@ -1,7 +1,10 @@ use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs index 4dcf29bb..caf0dd37 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_run_on_build.rs @@ -1,7 +1,10 @@ use crate::macro_api::prelude::*; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] #[darling(derive_syn_parse)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs index bbe87789..c53be868 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs @@ -1,10 +1,19 @@ -use crate::syntax::analysis::fn_param::require_fn_param_mutable_reference; -use crate::syntax::ast::type_list::TypeList; -use darling::FromMeta; -use darling::util::Flag; +use crate::syntax::{ + analysis::fn_param::require_fn_param_mutable_reference, + ast::type_list::TypeList, +}; +use darling::{ + FromMeta, + util::Flag, +}; use proc_macro2::Ident; -use syn::spanned::Spanned; -use syn::{FnArg, ItemFn, Pat, Path}; +use syn::{ + FnArg, + ItemFn, + Pat, + Path, + spanned::Spanned, +}; #[derive(FromMeta, Debug, Default, Clone)] #[darling(derive_syn_parse, default)] @@ -39,11 +48,7 @@ pub fn resolve_app_param_name<'a>( app_param_name: Option<&'a Ident>, ) -> syn::Result<&'a Ident> { // Helper: pick a useful Span for errors - let err_span = || { - app_param_name - .map(Ident::span) - .unwrap_or_else(|| input.sig.span()) - }; + let err_span = || app_param_name.map(Ident::span).unwrap_or_else(|| input.sig.span()); // Helper: try to get &Ident from a typed arg fn ident_from_typed_arg(arg: &FnArg) -> Option<&Ident> { @@ -56,19 +61,10 @@ pub fn resolve_app_param_name<'a>( } } - let has_self = input - .sig - .inputs - .iter() - .any(|a| matches!(a, FnArg::Receiver(_))); + let has_self = input.sig.inputs.iter().any(|a| matches!(a, FnArg::Receiver(_))); // collect all named params - let named = input - .sig - .inputs - .iter() - .filter_map(ident_from_typed_arg) - .collect::>(); + let named = input.sig.inputs.iter().filter_map(ident_from_typed_arg).collect::>(); // If user explicitly provided a name, validate it exists and return it if let Some(given) = app_param_name.as_ref() { @@ -117,7 +113,10 @@ pub fn resolve_app_param_name<'a>( mod tests { use crate::macro_api::attributes::auto_plugin::resolve_app_param_name; use internal_test_proc_macro::xtest; - use proc_macro2::{Ident, Span}; + use proc_macro2::{ + Ident, + Span, + }; #[xtest] #[should_panic = "auto_plugin provided app_param: `bar` but it was not found in the function signature"] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 2e45a4ae..c485ffe2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -1,37 +1,55 @@ -use crate::macro_api::prelude::*; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use crate::util::macros::impl_from_default; -use proc_macro2::{Ident, TokenStream}; +use crate::{ + macro_api::prelude::*, + syntax::validated::non_empty_path::NonEmptyPath, + util::macros::impl_from_default, +}; +use proc_macro2::{ + Ident, + TokenStream, +}; use quote::format_ident; -use std::hash::Hash; -use std::marker::PhantomData; -use syn::parse::Parse; -use syn::spanned::Spanned; -use syn::{Item, Path, parse_quote, parse2}; +use std::{ + hash::Hash, + marker::PhantomData, +}; +use syn::{ + Item, + Path, + parse::Parse, + parse_quote, + parse2, + spanned::Spanned, +}; mod actions; mod auto_plugin; mod rewrites; pub mod prelude { - pub use super::AllowAny; - pub use super::AllowFn; - pub use super::AllowStructOrEnum; - pub use super::AttributeIdent; - pub use super::GenericsCap; - pub use super::ItemAttribute; - pub use super::ItemAttributeArgs; - pub use super::ItemAttributeContext; - pub use super::ItemAttributeInput; - pub use super::ItemAttributeParse; - pub use super::ItemAttributePlugin; - pub use super::ItemAttributeTarget; - pub use super::ItemAttributeUniqueIdent; - pub use super::auto_plugin::{ - AutoPluginFnArgs, AutoPluginStructOrEnumArgs, resolve_app_param_name, + pub use super::{ + AllowAny, + AllowFn, + AllowStructOrEnum, + AttributeIdent, + GenericsCap, + ItemAttribute, + ItemAttributeArgs, + ItemAttributeContext, + ItemAttributeInput, + ItemAttributeParse, + ItemAttributePlugin, + ItemAttributeTarget, + ItemAttributeUniqueIdent, + auto_plugin::{ + AutoPluginFnArgs, + AutoPluginStructOrEnumArgs, + resolve_app_param_name, + }, + }; + pub use crate::macro_api::attributes::{ + actions::prelude::*, + rewrites::prelude::*, }; - pub use crate::macro_api::attributes::actions::prelude::*; - pub use crate::macro_api::attributes::rewrites::prelude::*; } pub trait AttributeIdent { @@ -143,7 +161,10 @@ impl ItemAttribute { where T: Hash, { - use std::hash::{Hash, Hasher}; + use std::hash::{ + Hash, + Hasher, + }; let mut hasher = std::collections::hash_map::DefaultHasher::new(); ident.hash(&mut hasher); self.args.hash(&mut hasher); @@ -262,18 +283,9 @@ where let mut input_item = InputItem::Tokens(input); let item = input_item.ensure_ast()?; let Some(target) = Resolver::resolve_ident_path(item) else { - return Err(syn::Error::new( - input_item.span(), - Resolver::NOT_ALLOWED_MESSAGE, - )); + return Err(syn::Error::new(input_item.span(), Resolver::NOT_ALLOWED_MESSAGE)); }; - Ok(Self { - args: parse2::(attr)?, - context, - input_item, - target, - _resolver: PhantomData, - }) + Ok(Self { args: parse2::(attr)?, context, input_item, target, _resolver: PhantomData }) } } @@ -286,12 +298,7 @@ where if self.args.generics.generics().is_empty() { vec![target.clone()] } else { - self.args - .generics - .generics() - .iter() - .map(|g| syn::parse_quote!(#target::<#g>)) - .collect() + self.args.generics.generics().iter().map(|g| syn::parse_quote!(#target::<#g>)).collect() } } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs index 7941b83c..c41d02ac 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_component.rs @@ -1,9 +1,18 @@ -use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::prelude::*; -use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::ast::flag_or_lit::FlagOrLit; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use crate::util::macros::impl_from_default; +use crate::{ + codegen::{ + ExpandAttrs, + tokens, + }, + macro_api::prelude::*, + syntax::{ + ast::{ + flag_or_list::FlagOrList, + flag_or_lit::FlagOrLit, + }, + validated::non_empty_path::NonEmptyPath, + }, + util::macros::impl_from_default, +}; use darling::FromMeta; use proc_macro2::Ident; use syn::parse_quote; @@ -29,9 +38,7 @@ impl From<&ComponentArgs> for RegisterTypeArgs { impl<'a> From<&'a ComponentArgs> for NameArgs { fn from(value: &'a ComponentArgs) -> Self { - Self { - name: value.auto_name.lit.clone(), - } + Self { name: value.auto_name.lit.clone() } } } @@ -42,9 +49,7 @@ pub type ComponentAttrExpandEmitter = AttrExpansionEmitter; impl AttrExpansionEmitterToExpandAttr for ComponentAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { - expand_attrs - .attrs - .push(tokens::derive_component(&self.args.args.base.derive.items)); + expand_attrs.attrs.push(tokens::derive_component(&self.args.args.base.derive.items)); } if self.args.args.base.reflect.present { if self.args.args.base.derive.present { @@ -56,9 +61,7 @@ impl AttrExpansionEmitterToExpandAttr for ComponentAttrExpandEmitter { expand_attrs.append(tokens::reflect(items)) } if self.args.args.base.register { - expand_attrs - .attrs - .push(tokens::auto_register_type(self.into())); + expand_attrs.attrs.push(tokens::auto_register_type(self.into())); } if self.args.args.base.auto_name.present { expand_attrs.attrs.push(tokens::auto_name(self.into())); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs index ab5b40a5..c601e7fa 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_event.rs @@ -1,11 +1,24 @@ -use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::prelude::*; -use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use crate::util::macros::impl_from_default; +use crate::{ + codegen::{ + ExpandAttrs, + tokens, + }, + macro_api::prelude::*, + syntax::{ + ast::flag_or_list::FlagOrList, + validated::non_empty_path::NonEmptyPath, + }, + util::macros::impl_from_default, +}; use darling::FromMeta; -use proc_macro2::{Ident, TokenStream}; -use quote::{ToTokens, quote}; +use proc_macro2::{ + Ident, + TokenStream, +}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Default, Debug, Copy, Clone, PartialEq, Hash)] #[darling(derive_syn_parse, default)] @@ -56,14 +69,12 @@ impl AttrExpansionEmitterToExpandAttr for EventAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { if matches!(self.args.args.base.target, EventTarget::Global) { - expand_attrs - .attrs - .push(tokens::derive_event(&self.args.args.base.derive.items)); + expand_attrs.attrs.push(tokens::derive_event(&self.args.args.base.derive.items)); } if matches!(self.args.args.base.target, EventTarget::Entity) { - expand_attrs.attrs.push(tokens::derive_entity_event( - &self.args.args.base.derive.items, - )); + expand_attrs + .attrs + .push(tokens::derive_entity_event(&self.args.args.base.derive.items)); } } if self.args.args.base.reflect.present { @@ -73,9 +84,7 @@ impl AttrExpansionEmitterToExpandAttr for EventAttrExpandEmitter { expand_attrs.append(tokens::reflect(&self.args.args.base.reflect.items)) } if self.args.args.base.register { - expand_attrs - .attrs - .push(tokens::auto_register_type(self.into())); + expand_attrs.attrs.push(tokens::auto_register_type(self.into())); } } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs index c529ef15..c5a01444 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_message.rs @@ -1,8 +1,15 @@ -use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::prelude::*; -use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use crate::util::macros::impl_from_default; +use crate::{ + codegen::{ + ExpandAttrs, + tokens, + }, + macro_api::prelude::*, + syntax::{ + ast::flag_or_list::FlagOrList, + validated::non_empty_path::NonEmptyPath, + }, + util::macros::impl_from_default, +}; use darling::FromMeta; use proc_macro2::Ident; @@ -37,9 +44,7 @@ pub type MessageAttrExpandEmitter = AttrExpansionEmitter; impl AttrExpansionEmitterToExpandAttr for MessageAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { - expand_attrs - .attrs - .push(tokens::derive_message(&self.args.args.base.derive.items)); + expand_attrs.attrs.push(tokens::derive_message(&self.args.args.base.derive.items)); } if self.args.args.base.reflect.present { if self.args.args.base.derive.present { @@ -48,15 +53,11 @@ impl AttrExpansionEmitterToExpandAttr for MessageAttrExpandEmitter { expand_attrs.append(tokens::reflect(&self.args.args.base.reflect.items)) } if self.args.args.base.register { - expand_attrs - .attrs - .push(tokens::auto_register_type(self.into())); + expand_attrs.attrs.push(tokens::auto_register_type(self.into())); } // TODO: should this be gated behind a flag? - expand_attrs - .attrs - .push(tokens::auto_add_message(self.into())); + expand_attrs.attrs.push(tokens::auto_add_message(self.into())); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs index 47371b45..27e273e3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_observer.rs @@ -1,6 +1,11 @@ -use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::prelude::*; -use crate::util::macros::impl_from_default; +use crate::{ + codegen::{ + ExpandAttrs, + tokens, + }, + macro_api::prelude::*, + util::macros::impl_from_default, +}; use darling::FromMeta; #[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] @@ -29,9 +34,7 @@ pub type ObserverAttrExpandEmitter = AttrExpansionEmitter; impl AttrExpansionEmitterToExpandAttr for ObserverAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { - expand_attrs - .attrs - .push(tokens::auto_add_observer(self.into())); + expand_attrs.attrs.push(tokens::auto_add_observer(self.into())); } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs index b5dc735e..f993e17e 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_resource.rs @@ -1,8 +1,15 @@ -use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::prelude::*; -use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use crate::util::macros::impl_from_default; +use crate::{ + codegen::{ + ExpandAttrs, + tokens, + }, + macro_api::prelude::*, + syntax::{ + ast::flag_or_list::FlagOrList, + validated::non_empty_path::NonEmptyPath, + }, + util::macros::impl_from_default, +}; use darling::FromMeta; use proc_macro2::Ident; use syn::parse_quote; @@ -38,9 +45,7 @@ pub type ResourceAttrExpandEmitter = AttrExpansionEmitter; impl AttrExpansionEmitterToExpandAttr for ResourceAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { if self.args.args.base.derive.present { - expand_attrs - .attrs - .push(tokens::derive_resource(&self.args.args.base.derive.items)); + expand_attrs.attrs.push(tokens::derive_resource(&self.args.args.base.derive.items)); } if self.args.args.base.reflect.present { if self.args.args.base.derive.present { @@ -52,14 +57,10 @@ impl AttrExpansionEmitterToExpandAttr for ResourceAttrExpandEmitter { expand_attrs.append(tokens::reflect(items)) } if self.args.args.base.register { - expand_attrs - .attrs - .push(tokens::auto_register_type(self.into())); + expand_attrs.attrs.push(tokens::auto_register_type(self.into())); } if self.args.args.base.init { - expand_attrs - .attrs - .push(tokens::auto_init_resource(self.into())); + expand_attrs.attrs.push(tokens::auto_init_resource(self.into())); } } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index eff69999..231fffee 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -1,8 +1,15 @@ -use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::prelude::*; -use crate::syntax::ast::flag_or_list::FlagOrList; -use crate::syntax::validated::non_empty_path::NonEmptyPath; -use crate::util::macros::impl_from_default; +use crate::{ + codegen::{ + ExpandAttrs, + tokens, + }, + macro_api::prelude::*, + syntax::{ + ast::flag_or_list::FlagOrList, + validated::non_empty_path::NonEmptyPath, + }, + util::macros::impl_from_default, +}; use darling::FromMeta; use proc_macro2::Ident; @@ -45,14 +52,10 @@ impl AttrExpansionEmitterToExpandAttr for StateAttrExpandEmitter { expand_attrs.append(tokens::reflect(&self.args.args.base.reflect.items)) } if self.args.args.base.register { - expand_attrs - .attrs - .push(tokens::auto_register_type(self.into())); + expand_attrs.attrs.push(tokens::auto_register_type(self.into())); } if self.args.args.base.init { - expand_attrs - .attrs - .push(tokens::auto_init_states(self.into())); + expand_attrs.attrs.push(tokens::auto_init_states(self.into())); } } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs index 40c80cc1..2fd6ae4f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_system.rs @@ -1,6 +1,13 @@ -use crate::codegen::{ExpandAttrs, tokens}; -use crate::macro_api::prelude::*; -use crate::macro_api::schedule_config::ScheduleWithScheduleConfigArgs; +use crate::{ + codegen::{ + ExpandAttrs, + tokens, + }, + macro_api::{ + prelude::*, + schedule_config::ScheduleWithScheduleConfigArgs, + }, +}; use darling::FromMeta; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] @@ -22,9 +29,7 @@ impl<'a> From<&'a SystemArgs> for RegisterTypeArgs { impl<'a> From<&'a SystemArgs> for AddSystemArgs { fn from(value: &'a SystemArgs) -> Self { - AddSystemArgs { - schedule_config: value.schedule_config.clone(), - } + AddSystemArgs { schedule_config: value.schedule_config.clone() } } } @@ -34,16 +39,12 @@ pub type SystemAttrExpandEmitter = AttrExpansionEmitter; impl AttrExpansionEmitterToExpandAttr for SystemAttrExpandEmitter { fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { - expand_attrs - .attrs - .push(tokens::auto_add_systems(self.into())); + expand_attrs.attrs.push(tokens::auto_add_systems(self.into())); } } impl From for AddSystemArgs { fn from(value: SystemArgs) -> Self { - Self { - schedule_config: value.schedule_config, - } + Self { schedule_config: value.schedule_config } } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs index 3dcddad4..1339ba19 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/composed.rs @@ -1,14 +1,28 @@ -use crate::macro_api::prelude::*; -use crate::syntax::ast::type_list::TypeList; -use darling::FromMeta; -use darling::ast::NestedMeta; +use crate::{ + macro_api::prelude::*, + syntax::ast::type_list::TypeList, +}; +use darling::{ + FromMeta, + ast::NestedMeta, +}; use proc_macro2::TokenStream; use quote::ToTokens; -use std::collections::HashSet; -use std::hash::{Hash, Hasher}; -use syn::parse::{Parse, ParseStream}; -use syn::parse_quote; -use syn::punctuated::Punctuated; +use std::{ + collections::HashSet, + hash::{ + Hash, + Hasher, + }, +}; +use syn::{ + parse::{ + Parse, + ParseStream, + }, + parse_quote, + punctuated::Punctuated, +}; #[derive(Debug, Clone, PartialEq)] pub struct Composed { @@ -82,11 +96,7 @@ where let plugin = MPlugin::from_list(&plugin_bucket)?; let generics = MGenerics::from_list(&generics_bucket)?; - Ok(Self { - base, - plugin, - generics, - }) + Ok(Self { base, plugin, generics }) } } @@ -139,11 +149,7 @@ where if self.generics.generics().is_empty() { vec![target.clone()] } else { - self.generics - .generics() - .iter() - .map(|g| parse_quote!(#target :: < #g >)) - .collect() + self.generics.generics().iter().map(|g| parse_quote!(#target :: < #g >)).collect() } } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context/macro_paths.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context/macro_paths.rs index c76ece0c..a2e7150a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/context/macro_paths.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/context/macro_paths.rs @@ -1,5 +1,7 @@ -use crate::macro_api::attributes::prelude::*; -use crate::macro_api::context::Context; +use crate::macro_api::{ + attributes::prelude::*, + context::Context, +}; use syn::parse_quote; #[derive(Debug, Clone, PartialEq, Hash)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs index 8aa9806c..431d62e6 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs @@ -8,6 +8,8 @@ pub struct Context { } pub mod prelude { - pub use super::Context; - pub use super::macro_paths::*; + pub use super::{ + Context, + macro_paths::*, + }; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/derives/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/derives/auto_plugin.rs index 6bbc14e5..3915a71b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/derives/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/derives/auto_plugin.rs @@ -1,8 +1,17 @@ -use crate::macro_api::attributes::prelude::*; -use crate::macro_api::derives::{FieldData, VariantData}; +use crate::macro_api::{ + attributes::prelude::*, + derives::{ + FieldData, + VariantData, + }, +}; use darling::FromDeriveInput; use proc_macro2::Ident; -use syn::{Attribute, Generics, Visibility}; +use syn::{ + Attribute, + Generics, + Visibility, +}; #[derive(FromDeriveInput, Debug)] #[darling(attributes(auto_plugin), forward_attrs, supports(struct_any, enum_any))] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs index 0501984f..9213e066 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/derives/mod.rs @@ -1,4 +1,7 @@ -use darling::{FromField, FromVariant}; +use darling::{ + FromField, + FromVariant, +}; use proc_macro2::Ident; use syn::Type; @@ -19,7 +22,6 @@ pub struct VariantData { } pub mod prelude { - - + pub use super::auto_plugin::*; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs index 9581554f..29741b73 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs @@ -1,7 +1,12 @@ -use crate::__private::auto_plugin_registry::_plugin_entry_block; -use crate::macro_api::prelude::*; +use crate::{ + __private::auto_plugin_registry::_plugin_entry_block, + macro_api::prelude::*, +}; use proc_macro2::TokenStream; -use quote::{ToTokens, format_ident}; +use quote::{ + ToTokens, + format_ident, +}; /// for codegen attaching to bevy app #[derive(Debug, Clone)] @@ -13,10 +18,7 @@ pub struct AppMutationEmitter { impl AppMutationEmitter { pub fn from_args(args: T) -> AppMutationEmitter { - AppMutationEmitter:: { - args, - app_param: format_ident!("app"), - } + AppMutationEmitter:: { args, app_param: format_ident!("app") } } pub fn wrap_body( &mut self, @@ -43,10 +45,7 @@ impl AppMutationEmitter { // required for generics let unique_ident = format_ident!("{unique_ident}"); let output = _plugin_entry_block(&unique_ident, &plugin, &expr); - assert!( - !output.is_empty(), - "No plugin entry points were generated for ident: {ident}" - ); + assert!(!output.is_empty(), "No plugin entry points were generated for ident: {ident}"); Ok(output) } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr.rs index ce98e1bc..98580ac2 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr.rs @@ -1,10 +1,17 @@ -use crate::codegen::ExpandAttrs; -use crate::macro_api::prelude::*; -use crate::syntax::extensions::item::ItemAttrsExt; +use crate::{ + codegen::ExpandAttrs, + macro_api::prelude::*, + syntax::extensions::item::ItemAttrsExt, +}; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; -use syn::parse_quote; -use syn::spanned::Spanned; +use quote::{ + ToTokens, + quote, +}; +use syn::{ + parse_quote, + spanned::Spanned, +}; /// for codegen re-emitting macro args #[derive(Debug, Clone)] @@ -59,9 +66,7 @@ where let macro_path = T::macro_path(self.args.context()).clone(); self.args.input_item_mut().map_ast(|item| { // insert attribute tokens - let mut attrs = item - .take_attrs() - .map_err(|err| syn::Error::new(item.span(), err))?; + let mut attrs = item.take_attrs().map_err(|err| syn::Error::new(item.span(), err))?; attrs.insert(0, parse_quote!(#[#macro_path(#args)])); item.put_attrs(attrs).unwrap(); // infallible Ok(()) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs index eb24e21e..28ab8584 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs @@ -1,5 +1,7 @@ -use crate::codegen::ExpandAttrs; -use crate::macro_api::prelude::*; +use crate::{ + codegen::ExpandAttrs, + macro_api::prelude::*, +}; use proc_macro2::TokenStream; use quote::ToTokens; use std::marker::PhantomData; @@ -15,9 +17,7 @@ where T: ItemAttributeParse, { pub fn from_item_attribute(item_attribute: T) -> AttrExpansionEmitter { - AttrExpansionEmitter:: { - args: item_attribute, - } + AttrExpansionEmitter:: { args: item_attribute } } } @@ -47,13 +47,7 @@ where RTo: From, { fn from(value: AttrExpansionEmitter, RFrom>>) -> Self { - let ItemAttribute { - args, - context, - input_item, - target, - _resolver, - } = value.args; + let ItemAttribute { args, context, input_item, target, _resolver } = value.args; let mapped = Composed { base: args.base.into(), // TTo: From diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs index be7c2396..c0ea9956 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/mod.rs @@ -3,7 +3,9 @@ pub mod attr; pub mod attr_expansion; pub mod prelude { - pub use super::app_mutation::*; - pub use super::attr::*; - pub use super::attr_expansion::*; + pub use super::{ + app_mutation::*, + attr::*, + attr_expansion::*, + }; } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs index 6e18fa67..780ac2cb 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs @@ -1,8 +1,13 @@ use crate::syntax::extensions::item::ItemAttrsExt; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; -use syn::parse2; -use syn::spanned::Spanned; +use quote::{ + ToTokens, + quote, +}; +use syn::{ + parse2, + spanned::Spanned, +}; #[derive(Debug, Clone)] pub enum InputItem { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs index 1338748d..e1ec928b 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/none.rs @@ -1,12 +1,26 @@ -use crate::macro_api::mixins::HasKeys; -use crate::macro_api::prelude::{WithZeroOrManyGenerics, WithZeroOrOneGenerics}; -use crate::util::macros::impl_from_default; -use darling::FromMeta; -use darling::ast::NestedMeta; +use crate::{ + macro_api::{ + mixins::HasKeys, + prelude::{ + WithZeroOrManyGenerics, + WithZeroOrOneGenerics, + }, + }, + util::macros::impl_from_default, +}; +use darling::{ + FromMeta, + ast::NestedMeta, +}; use proc_macro2::TokenStream; use quote::ToTokens; -use syn::parse::{Parse, ParseStream}; -use syn::spanned::Spanned; +use syn::{ + parse::{ + Parse, + ParseStream, + }, + spanned::Spanned, +}; #[derive(Debug, Clone, Default, PartialEq, Hash)] pub struct WithNoGenerics {} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs index dc206981..0c904185 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_many.rs @@ -1,9 +1,16 @@ -use crate::macro_api::mixins::HasKeys; -use crate::macro_api::mixins::generics::HasGenerics; -use crate::syntax::ast::type_list::TypeList; +use crate::{ + macro_api::mixins::{ + HasKeys, + generics::HasGenerics, + }, + syntax::ast::type_list::TypeList, +}; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(Debug, Clone, Default, FromMeta, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -46,9 +53,7 @@ mod tests { #[xtest] fn test_to_tokens_zero() { assert_eq!( - WithZeroOrManyGenerics { generics: vec![] } - .to_token_stream() - .to_string(), + WithZeroOrManyGenerics { generics: vec![] }.to_token_stream().to_string(), quote!().to_string() ); } @@ -57,7 +62,7 @@ mod tests { fn test_to_tokens_single() { assert_eq!( WithZeroOrManyGenerics { - generics: vec![TypeList(vec![parse_quote!(bool), parse_quote!(u32)])], + generics: vec![TypeList(vec![parse_quote!(bool), parse_quote!(u32)])] } .to_token_stream() .to_string(), diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs index 5261f5c0..7c331bc7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/generics/with_single.rs @@ -1,10 +1,19 @@ -use crate::macro_api::mixins::HasKeys; -use crate::macro_api::mixins::generics::HasGenerics; -use crate::macro_api::prelude::WithZeroOrManyGenerics; -use crate::syntax::ast::type_list::TypeList; +use crate::{ + macro_api::{ + mixins::{ + HasKeys, + generics::HasGenerics, + }, + prelude::WithZeroOrManyGenerics, + }, + syntax::ast::type_list::TypeList, +}; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(Debug, Clone, Default, FromMeta, PartialEq, Hash)] #[darling(derive_syn_parse)] @@ -40,9 +49,7 @@ impl ToTokens for WithZeroOrOneGenerics { impl From for WithZeroOrManyGenerics { fn from(value: WithZeroOrOneGenerics) -> Self { - Self { - generics: value.generics.as_slice().to_vec(), - } + Self { generics: value.generics.as_slice().to_vec() } } } @@ -55,9 +62,7 @@ mod tests { #[xtest] fn test_to_tokens_zero() { assert_eq!( - WithZeroOrOneGenerics { generics: None } - .to_token_stream() - .to_string(), + WithZeroOrOneGenerics { generics: None }.to_token_stream().to_string(), quote!().to_string(), ); } @@ -66,7 +71,7 @@ mod tests { fn test_to_tokens_single() { assert_eq!( WithZeroOrOneGenerics { - generics: Some(TypeList(vec![parse_quote!(bool), parse_quote!(u32)])), + generics: Some(TypeList(vec![parse_quote!(bool), parse_quote!(u32)])) } .to_token_stream() .to_string(), diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/nothing.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/nothing.rs index a173e1a8..b7da6c9a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/nothing.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/nothing.rs @@ -1,6 +1,10 @@ -use crate::macro_api::mixins::HasKeys; -use crate::macro_api::mixins::generics::HasGenerics; -use crate::syntax::ast::type_list::TypeList; +use crate::{ + macro_api::mixins::{ + HasKeys, + generics::HasGenerics, + }, + syntax::ast::type_list::TypeList, +}; use darling::FromMeta; #[derive(Debug, Clone, FromMeta)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs index 10d44464..0a4c96f9 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/mixins/with_plugin.rs @@ -1,7 +1,10 @@ use crate::macro_api::mixins::HasKeys; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(Debug, Clone, FromMeta, PartialEq, Hash)] #[darling(derive_syn_parse)] diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/schedule_config.rs b/crates/bevy_auto_plugin_shared/src/macro_api/schedule_config.rs index bf2c4f57..e638ce9d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/schedule_config.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/schedule_config.rs @@ -1,7 +1,13 @@ -use crate::syntax::ast::any_expr::{AnyExprCallClosureMacroPath, AnyExprCallMacroPath}; +use crate::syntax::ast::any_expr::{ + AnyExprCallClosureMacroPath, + AnyExprCallMacroPath, +}; use darling::FromMeta; use proc_macro2::TokenStream as MacroStream; -use quote::{ToTokens, quote}; +use quote::{ + ToTokens, + quote, +}; #[derive(FromMeta, Clone, Debug, PartialEq, Hash)] #[darling(derive_syn_parse)] diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/fn_param.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/fn_param.rs index e66c37ff..1d466536 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/fn_param.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/fn_param.rs @@ -12,8 +12,12 @@ pub fn is_fn_param_mutable_reference( messages: FnParamMutabilityCheckErrMessages, ) -> syn::Result<()> { use crate::syntax::analysis::ty_classify; - use syn::spanned::Spanned; - use syn::{Error, FnArg, Pat}; + use syn::{ + Error, + FnArg, + Pat, + spanned::Spanned, + }; for arg in &item.sig.inputs { if let FnArg::Typed(pat_type) = arg { let Pat::Ident(pat_ident) = &*pat_type.pat else { @@ -28,10 +32,7 @@ pub fn is_fn_param_mutable_reference( return Ok(()); } } - Err(Error::new( - item.sig.inputs.span(), - messages.not_found_message, - )) + Err(Error::new(item.sig.inputs.span(), messages.not_found_message)) } pub fn require_fn_param_mutable_reference( diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/path.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/path.rs index ec3e0855..05479240 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/path.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/path.rs @@ -1,6 +1,10 @@ use crate::syntax::ast::type_list::TypeList; use quote::ToTokens; -use syn::{Path, PathArguments, parse2}; +use syn::{ + Path, + PathArguments, + parse2, +}; pub fn generics_from_path(path: &Path) -> syn::Result { let mut generics = TypeList::empty(); diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/ty_classify.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/ty_classify.rs index 66b06c99..fc02570b 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/ty_classify.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/ty_classify.rs @@ -1,12 +1,9 @@ -use syn::{Type, TypeReference}; +use syn::{ + Type, + TypeReference, +}; /// Check if the type is `&mut _` pub fn is_mutable_reference(ty: &Type) -> bool { - matches!( - ty, - Type::Reference(TypeReference { - mutability: Some(_), - .. - }) - ) + matches!(ty, Type::Reference(TypeReference { mutability: Some(_), .. })) } diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/any_expr.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/any_expr.rs index f2f57c3d..1dd05352 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/any_expr.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/any_expr.rs @@ -193,7 +193,10 @@ mod tests { use internal_test_proc_macro::xtest; use proc_macro2::TokenStream; use quote::quote; - use syn::{parse_quote, parse2}; + use syn::{ + parse_quote, + parse2, + }; fn map_err_to_string(r: Result) -> Result { r.map_err(|e| &*format!("{e}").leak()) diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/expr_path_or_call.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/expr_path_or_call.rs index e7b2e004..3101f534 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/expr_path_or_call.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/expr_path_or_call.rs @@ -1,9 +1,13 @@ use darling::FromMeta; use proc_macro2::TokenStream; use quote::ToTokens; -use syn::parse::Parser; -use syn::spanned::Spanned; -use syn::{Expr, Token, punctuated::Punctuated}; +use syn::{ + Expr, + Token, + parse::Parser, + punctuated::Punctuated, + spanned::Spanned, +}; #[derive(Debug, Clone, PartialEq, Hash)] pub enum ExprPathOrCall { @@ -56,9 +60,7 @@ impl FromMeta for ExprPathOrCall { syn::Meta::List(list) => { // Parse exactly one Expr from the list's tokens. let parser = Punctuated::::parse_terminated; - let elems = parser - .parse2(list.tokens.clone()) - .map_err(darling::Error::from)?; + let elems = parser.parse2(list.tokens.clone()).map_err(darling::Error::from)?; let mut it = elems.into_iter(); let expr = it.next().ok_or_else(|| { darling::Error::too_few_items(1).with_span(&list.tokens.span()) @@ -76,10 +78,10 @@ impl FromMeta for ExprPathOrCall { } // Bare flag like `item` is not accepted. - syn::Meta::Path(_) => Err(darling::Error::custom( - "expected `item = ` or `item()`", - ) - .with_span(&meta.span())), + syn::Meta::Path(_) => { + Err(darling::Error::custom("expected `item = ` or `item()`") + .with_span(&meta.span())) + } } } } @@ -89,14 +91,10 @@ impl syn::parse::Parse for ExprPathOrCall { let elems = Punctuated::::parse_terminated(input)?; let mut elems = elems.into_iter(); let Some(elem) = elems.next() else { - return Err(darling::Error::too_few_items(1) - .with_span(&input.span()) - .into()); + return Err(darling::Error::too_few_items(1).with_span(&input.span()).into()); }; if let Some(elem) = elems.next() { - return Err(darling::Error::too_many_items(1) - .with_span(&elem.span()) - .into()); + return Err(darling::Error::too_many_items(1).with_span(&elem.span()).into()); } Ok(match elem { Expr::Call(call) => ExprPathOrCall::Call(call), @@ -112,7 +110,10 @@ impl syn::parse::Parse for ExprPathOrCall { mod tests { use super::*; use internal_test_proc_macro::xtest; - use syn::{Meta, parse_quote}; + use syn::{ + Meta, + parse_quote, + }; #[derive(Debug)] #[allow(dead_code)] diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/expr_value.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/expr_value.rs index 39dfe77f..9cf97d53 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/expr_value.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/expr_value.rs @@ -1,9 +1,17 @@ -use darling::{Error, FromMeta}; +use darling::{ + Error, + FromMeta, +}; use proc_macro2::TokenStream; use quote::ToTokens; -use syn::parse::Parser; -use syn::spanned::Spanned; -use syn::{Expr, Meta, Token, punctuated::Punctuated}; +use syn::{ + Expr, + Meta, + Token, + parse::Parser, + punctuated::Punctuated, + spanned::Spanned, +}; #[derive(Debug, Clone, PartialEq, Hash)] pub struct ExprValue(pub Expr); @@ -43,9 +51,8 @@ impl FromMeta for ExprValue { let list = meta.require_list()?; // Parse its tokens as `T, T, ...` where each `T` is a syn::Type let parser = Punctuated::::parse_terminated; - let elems = parser - .parse2(list.tokens.clone()) - .map_err(|e| failed_err(e, &list.tokens.span()))?; + let elems = + parser.parse2(list.tokens.clone()).map_err(|e| failed_err(e, &list.tokens.span()))?; let mut elems = elems.into_iter(); let Some(elem) = elems.next() else { return Err(Error::too_few_items(1).with_span(&meta.span())); @@ -76,7 +83,10 @@ mod tests { use super::*; use internal_test_proc_macro::xtest; use quote::quote; - use syn::{Meta, parse_quote}; + use syn::{ + Meta, + parse_quote, + }; #[derive(Debug)] #[allow(dead_code)] diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag.rs index da6000fb..b538d029 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag.rs @@ -1,9 +1,17 @@ -use darling::{FromMeta, Result}; +use darling::{ + FromMeta, + Result, +}; use proc_macro2::Span; use smart_default::SmartDefault; -use std::hash::{Hash, Hasher}; -use syn::Meta; -use syn::spanned::Spanned; +use std::hash::{ + Hash, + Hasher, +}; +use syn::{ + Meta, + spanned::Spanned, +}; /// Wrapper type for darling::util::Flag that implements PartialEq and Hash /// @@ -41,11 +49,7 @@ impl FromMeta for Flag { fn from_meta(meta: &Meta) -> Result { Ok(match meta { Meta::NameValue(nv) => { - if let syn::Expr::Lit(syn::ExprLit { - lit: syn::Lit::Bool(b), - .. - }) = &nv.value - { + if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Bool(b), .. }) = &nv.value { Self::from_bool(b.value)? } else { return Err(darling::Error::unknown_value("expected boolean literal") @@ -71,11 +75,7 @@ impl From for bool { impl From for Flag { fn from(v: bool) -> Self { - if v { - Self::present() - } else { - Self(darling::util::Flag::from(false)) - } + if v { Self::present() } else { Self(darling::util::Flag::from(false)) } } } @@ -93,27 +93,17 @@ mod tests { #[xtest] #[should_panic = "Unexpected type `lit`"] fn test_from_meta_flag_list_single() { - Flag::from_meta(&parse_quote!(this_flag("foo"))) - .map_err(|e| e.to_string()) - .unwrap(); + Flag::from_meta(&parse_quote!(this_flag("foo"))).map_err(|e| e.to_string()).unwrap(); } #[xtest] #[should_panic = "Multiple errors: (Unexpected type `lit`, Unexpected type `lit`)"] fn test_from_meta_flag_list_multiple() { - Flag::from_meta(&parse_quote!(this_flag("foo", "bar"))) - .map_err(|e| e.to_string()) - .unwrap(); + Flag::from_meta(&parse_quote!(this_flag("foo", "bar"))).map_err(|e| e.to_string()).unwrap(); } #[xtest] fn test_from_meta_flag_nv() -> syn::Result<()> { - assert_eq!( - Flag::from_meta(&parse_quote!(this_flag = true))?, - Flag::present() - ); - assert_eq!( - Flag::from_meta(&parse_quote!(this_flag = false))?, - Flag::from(false) - ); + assert_eq!(Flag::from_meta(&parse_quote!(this_flag = true))?, Flag::present()); + assert_eq!(Flag::from_meta(&parse_quote!(this_flag = false))?, Flag::from(false)); Ok(()) } } diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_expr.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_expr.rs index 04e61f55..4abfb7e4 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_expr.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_expr.rs @@ -1,6 +1,13 @@ -use darling::{Error, FromMeta, Result}; +use darling::{ + Error, + FromMeta, + Result, +}; use smart_default::SmartDefault; -use syn::{Expr, Meta}; +use syn::{ + Expr, + Meta, +}; #[derive(Debug, SmartDefault, Clone, PartialEq, Hash)] pub struct FlagOrExpr { @@ -14,27 +21,18 @@ impl FromMeta for FlagOrExpr { fn from_meta(meta: &Meta) -> Result { match meta { // `#[this_flag]` - Meta::Path(_) => Ok(FlagOrExpr { - present: true, - expr: None, - }), + Meta::Path(_) => Ok(FlagOrExpr { present: true, expr: None }), // `#[this_flag(...)]` Meta::List(list) => { let parsed: Expr = list.parse_args().map_err(|_| { Error::unsupported_format("list with multiple parameters").with_span(list) })?; - Ok(FlagOrExpr { - present: true, - expr: Some(parsed), - }) + Ok(FlagOrExpr { present: true, expr: Some(parsed) }) } // `#[this_flag = ...]` - Meta::NameValue(nv) => Ok(FlagOrExpr { - present: true, - expr: Some(nv.value.clone()), - }), + Meta::NameValue(nv) => Ok(FlagOrExpr { present: true, expr: Some(nv.value.clone()) }), } } } @@ -49,10 +47,7 @@ mod tests { fn test_from_meta_flag_present() -> syn::Result<()> { assert_eq!( FlagOrExpr::from_meta(&parse_quote!(this_flag))?, - FlagOrExpr { - present: true, - expr: None, - } + FlagOrExpr { present: true, expr: None } ); Ok(()) } @@ -60,10 +55,7 @@ mod tests { fn test_from_meta_flag_list_single() -> syn::Result<()> { assert_eq!( FlagOrExpr::from_meta(&parse_quote!(this_flag("foo")))?, - FlagOrExpr { - present: true, - expr: Some(parse_quote!("foo")), - } + FlagOrExpr { present: true, expr: Some(parse_quote!("foo")) } ); Ok(()) } @@ -76,10 +68,7 @@ mod tests { fn test_from_meta_flag_nv() -> syn::Result<()> { assert_eq!( FlagOrExpr::from_meta(&parse_quote!(this_flag = "foo"))?, - FlagOrExpr { - present: true, - expr: Some(parse_quote!("foo")), - } + FlagOrExpr { present: true, expr: Some(parse_quote!("foo")) } ); Ok(()) } diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs index e3347f0f..9ef8aacd 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_list.rs @@ -1,9 +1,16 @@ -use darling::{Error, FromMeta, Result}; +use darling::{ + Error, + FromMeta, + Result, +}; use quote::ToTokens; use smart_default::SmartDefault; -use syn::parse::Parse; -use syn::punctuated::Punctuated; -use syn::{Meta, Token}; +use syn::{ + Meta, + Token, + parse::Parse, + punctuated::Punctuated, +}; #[derive(Debug, SmartDefault, Clone, PartialEq, Hash)] pub struct FlagOrList @@ -45,20 +52,14 @@ where fn from_meta(meta: &Meta) -> Result { match meta { // `#[this_flag]` - Meta::Path(_) => Ok(FlagOrList { - present: true, - items: vec![], - }), + Meta::Path(_) => Ok(FlagOrList { present: true, items: vec![] }), // `#[this_flag(A, B)]` Meta::List(list) => { let parsed: Punctuated = list .parse_args_with(Punctuated::parse_terminated) .map_err(|e| Error::custom(e).with_span(list))?; - Ok(FlagOrList { - present: true, - items: parsed.into_iter().collect(), - }) + Ok(FlagOrList { present: true, items: parsed.into_iter().collect() }) } // Not supported: `#[this_flag = ...]` @@ -78,9 +79,7 @@ mod tests { #[xtest] fn test_flag_or_list_to_outer_tokens_not_present() { assert_eq!( - FlagOrList::::default() - .to_outer_tokens("this_flag") - .to_string(), + FlagOrList::::default().to_outer_tokens("this_flag").to_string(), quote! {}.to_string() ) } @@ -88,12 +87,9 @@ mod tests { #[xtest] fn test_flag_or_list_to_outer_tokens_empty() { assert_eq!( - FlagOrList:: { - present: true, - items: vec![] - } - .to_outer_tokens("this_flag") - .to_string(), + FlagOrList:: { present: true, items: vec![] } + .to_outer_tokens("this_flag") + .to_string(), quote! { this_flag }.to_string() ) } @@ -101,12 +97,9 @@ mod tests { #[xtest] fn test_flag_or_list_to_outer_tokens_single_item() { assert_eq!( - FlagOrList:: { - present: true, - items: vec![parse_quote!(A)] - } - .to_outer_tokens("this_flag") - .to_string(), + FlagOrList:: { present: true, items: vec![parse_quote!(A)] } + .to_outer_tokens("this_flag") + .to_string(), quote! { this_flag(A) }.to_string() ) } @@ -114,12 +107,9 @@ mod tests { #[xtest] fn test_flag_or_list_to_outer_tokens_multiple_item() { assert_eq!( - FlagOrList:: { - present: true, - items: vec![parse_quote!(A), parse_quote!(B)] - } - .to_outer_tokens("this_flag") - .to_string(), + FlagOrList:: { present: true, items: vec![parse_quote!(A), parse_quote!(B)] } + .to_outer_tokens("this_flag") + .to_string(), quote! { this_flag(A, B) }.to_string() ) } diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs index 8330ee40..14c15298 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_lit.rs @@ -1,7 +1,15 @@ -use darling::{Error, FromMeta, Result}; +use darling::{ + Error, + FromMeta, + Result, +}; use smart_default::SmartDefault; -use syn::spanned::Spanned; -use syn::{Expr, Lit, Meta}; +use syn::{ + Expr, + Lit, + Meta, + spanned::Spanned, +}; #[derive(Debug, SmartDefault, Clone, PartialEq, Hash)] pub struct FlagOrLit { @@ -34,20 +42,14 @@ impl FromMeta for FlagOrLit { fn from_meta(meta: &Meta) -> Result { match meta { // `#[this_flag]` - Meta::Path(_) => Ok(FlagOrLit { - present: true, - lit: None, - }), + Meta::Path(_) => Ok(FlagOrLit { present: true, lit: None }), // `#[this_flag(A, B)]` Meta::List(list) => Err(Error::unsupported_format("list").with_span(list)), // Not supported: `#[this_flag = ...]` Meta::NameValue(nv) => match &nv.value { - Expr::Lit(lit) => Ok(FlagOrLit { - present: true, - lit: Some(lit.lit.clone()), - }), + Expr::Lit(lit) => Ok(FlagOrLit { present: true, lit: Some(lit.lit.clone()) }), other => Err(Error::unexpected_expr_type(other).with_span(&other.span())), }, } @@ -65,10 +67,7 @@ mod tests { fn test_from_meta_flag_present() -> syn::Result<()> { assert_eq!( FlagOrLit::from_meta(&parse_quote!(this_flag))?, - FlagOrLit { - present: true, - lit: None, - } + FlagOrLit { present: true, lit: None } ); Ok(()) } @@ -76,43 +75,30 @@ mod tests { fn test_from_meta_flag_set() -> syn::Result<()> { assert_eq!( FlagOrLit::from_meta(&parse_quote!(this_flag = "foo"))?, - FlagOrLit { - present: true, - lit: Some(parse_quote!("foo")), - } + FlagOrLit { present: true, lit: Some(parse_quote!("foo")) } ); Ok(()) } #[xtest] fn test_flag_or_lit_to_outer_tokens_not_present() { assert_eq!( - FlagOrLit::default() - .to_outer_tokens("this_flag") - .to_string(), + FlagOrLit::default().to_outer_tokens("this_flag").to_string(), quote! {}.to_string() ) } #[xtest] fn test_flag_or_lit_to_outer_tokens_present() { assert_eq!( - FlagOrLit { - present: true, - lit: None, - } - .to_outer_tokens("this_flag") - .to_string(), + FlagOrLit { present: true, lit: None }.to_outer_tokens("this_flag").to_string(), quote! { this_flag }.to_string() ) } #[xtest] fn test_flag_or_lit_to_outer_tokens_set() { assert_eq!( - FlagOrLit { - present: true, - lit: Some(parse_quote!("foo")) - } - .to_outer_tokens("this_flag") - .to_string(), + FlagOrLit { present: true, lit: Some(parse_quote!("foo")) } + .to_outer_tokens("this_flag") + .to_string(), quote! { this_flag = "foo" }.to_string() ) } diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_meta.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_meta.rs index 813c2437..5fe56826 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_meta.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/flag_or_meta.rs @@ -1,9 +1,21 @@ -use darling::{Error, FromMeta, Result}; -use proc_macro2::{Ident, TokenStream}; -use quote::{ToTokens, quote}; +use darling::{ + Error, + FromMeta, + Result, +}; +use proc_macro2::{ + Ident, + TokenStream, +}; +use quote::{ + ToTokens, + quote, +}; use smart_default::SmartDefault; -use syn::Meta; -use syn::parse::Parse; +use syn::{ + Meta, + parse::Parse, +}; #[derive(Debug, SmartDefault, Clone, PartialEq, Hash)] pub struct FlagOrMeta @@ -43,19 +55,13 @@ where fn from_meta(meta: &Meta) -> Result { match meta { // `#[this_flag]` - Meta::Path(_) => Ok(FlagOrMeta { - present: true, - inner_meta: None, - }), + Meta::Path(_) => Ok(FlagOrMeta { present: true, inner_meta: None }), // `#[this_flag(A, B)]` Meta::List(_) => { // (T::from_meta sees Meta::List and can do `list.tokens` parsing inside) let t = T::from_meta(meta)?; - Ok(Self { - present: true, - inner_meta: Some(t), - }) + Ok(Self { present: true, inner_meta: Some(t) }) } // Not supported: `#[this_flag = ...]` @@ -71,10 +77,7 @@ where fn parse(input: syn::parse::ParseStream) -> syn::Result { // #[flag] -> no tokens after the key if input.is_empty() { - return Ok(Self { - present: true, - inner_meta: None, - }); + return Ok(Self { present: true, inner_meta: None }); } // #[flag(...)] -> parenthesized payload parsed as T @@ -86,10 +89,7 @@ where if !input.is_empty() { return Err(input.error("unexpected tokens after parenthesized payload")); } - return Ok(Self { - present: true, - inner_meta: Some(inner), - }); + return Ok(Self { present: true, inner_meta: Some(inner) }); } Err(input.error("expected nothing or a parenthesized payload")) @@ -124,9 +124,7 @@ mod tests { #[xtest] fn test_flag_or_list_to_outer_tokens_not_present() { assert_eq!( - FlagOrMeta::::default() - .to_outer_tokens("this_flag") - .to_string(), + FlagOrMeta::::default().to_outer_tokens("this_flag").to_string(), quote! {}.to_string() ) } @@ -134,12 +132,9 @@ mod tests { #[xtest] fn test_flag_or_list_to_outer_tokens_empty() { assert_eq!( - FlagOrMeta:: { - present: true, - inner_meta: None, - } - .to_outer_tokens("this_flag") - .to_string(), + FlagOrMeta:: { present: true, inner_meta: None } + .to_outer_tokens("this_flag") + .to_string(), quote! { this_flag }.to_string() ) } @@ -147,15 +142,9 @@ mod tests { #[xtest] fn test_flag_or_list_to_outer_tokens_single_item() { assert_eq!( - FlagOrMeta:: { - present: true, - inner_meta: Some(Test { - a: Some(1), - b: None, - }), - } - .to_outer_tokens("this_flag") - .to_string(), + FlagOrMeta:: { present: true, inner_meta: Some(Test { a: Some(1), b: None }) } + .to_outer_tokens("this_flag") + .to_string(), quote! { this_flag(a = 1u32) }.to_string() ) } @@ -163,15 +152,9 @@ mod tests { #[xtest] fn test_flag_or_list_to_outer_tokens_multiple_item() { assert_eq!( - FlagOrMeta:: { - present: true, - inner_meta: Some(Test { - a: Some(1), - b: Some(2), - }), - } - .to_outer_tokens("this_flag") - .to_string(), + FlagOrMeta:: { present: true, inner_meta: Some(Test { a: Some(1), b: Some(2) }) } + .to_outer_tokens("this_flag") + .to_string(), quote! { this_flag(a = 1u32, b = 2u32) }.to_string() ) } @@ -182,10 +165,7 @@ mod tests { let item = syn::parse2::>(input).map_err(|e| e.to_string()); let expected = Ok(FlagOrMeta:: { present: true, - inner_meta: Some(Test { - a: Some(1), - b: Some(2), - }), + inner_meta: Some(Test { a: Some(1), b: Some(2) }), }); assert_eq!(item, expected); } diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs index 2fa1331d..519591cc 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs @@ -1,9 +1,20 @@ -use darling::{Error, FromMeta}; +use darling::{ + Error, + FromMeta, +}; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; -use syn::parse::Parser; -use syn::spanned::Spanned; -use syn::{Meta, Token, Type, punctuated::Punctuated}; +use quote::{ + ToTokens, + quote, +}; +use syn::{ + Meta, + Token, + Type, + parse::Parser, + punctuated::Punctuated, + spanned::Spanned, +}; #[derive(Debug, Clone, Default, PartialEq, Hash)] pub struct TypeList(pub Vec); @@ -45,10 +56,7 @@ impl From for TokenStream { } fn failed_err(e: syn::Error, span: &proc_macro2::Span) -> Error { - Error::multiple(vec![ - Error::custom("failed to parse TypeList").with_span(span), - Error::from(e), - ]) + Error::multiple(vec![Error::custom("failed to parse TypeList").with_span(span), Error::from(e)]) } impl FromMeta for TypeList { @@ -65,7 +73,11 @@ impl FromMeta for TypeList { impl syn::parse::Parse for TypeList { fn parse(input: syn::parse::ParseStream) -> syn::Result { - use syn::{Token, Type, punctuated::Punctuated}; + use syn::{ + Token, + Type, + punctuated::Punctuated, + }; let elems = Punctuated::::parse_terminated(input) .map_err(|e| failed_err(e, &input.span()))? .into_iter() @@ -78,7 +90,11 @@ impl syn::parse::Parse for TypeList { mod tests { use super::*; use internal_test_proc_macro::xtest; - use syn::{Meta, Type, parse_quote}; + use syn::{ + Meta, + Type, + parse_quote, + }; #[derive(Debug, FromMeta)] pub struct FooAttr { @@ -98,10 +114,7 @@ mod tests { Type::Path(tp) => { let seg = tp.path.segments.last().unwrap(); assert_eq!(seg.ident, "FooBar"); - assert!(matches!( - seg.arguments, - syn::PathArguments::AngleBracketed(_) - )); + assert!(matches!(seg.arguments, syn::PathArguments::AngleBracketed(_))); } _ => panic!("expected Type::Path for element 2"), } diff --git a/crates/bevy_auto_plugin_shared/src/syntax/diagnostic/kind.rs b/crates/bevy_auto_plugin_shared/src/syntax/diagnostic/kind.rs index 129f6ce2..44e140e1 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/diagnostic/kind.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/diagnostic/kind.rs @@ -1,4 +1,8 @@ -use syn::{Item, Pat, Type}; +use syn::{ + Item, + Pat, + Type, +}; #[allow(dead_code)] pub fn pat_kind(pat: &Pat) -> &'static str { diff --git a/crates/bevy_auto_plugin_shared/src/syntax/extensions/generics.rs b/crates/bevy_auto_plugin_shared/src/syntax/extensions/generics.rs index 22161d8a..a4d7e8a0 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/extensions/generics.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/extensions/generics.rs @@ -1,5 +1,12 @@ use crate::syntax::extensions::path::PathExt; -use syn::{Lifetime, Path, TraitBound, TraitBoundModifier, TypeParamBound, parse_quote}; +use syn::{ + Lifetime, + Path, + TraitBound, + TraitBoundModifier, + TypeParamBound, + parse_quote, +}; /// Injects `Send + Sync + 'static` constraints to any generics that don't have them pub fn inject_send_sync_static(generics: &mut syn::Generics) { @@ -61,7 +68,10 @@ pub fn inject_send_sync_static(generics: &mut syn::Generics) { mod tests { use super::*; use internal_test_proc_macro::xtest; - use quote::{ToTokens, quote}; + use quote::{ + ToTokens, + quote, + }; use syn::parse_quote; #[xtest] diff --git a/crates/bevy_auto_plugin_shared/src/syntax/extensions/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/extensions/item.rs index f4e50f58..2651f330 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/extensions/item.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/extensions/item.rs @@ -1,7 +1,10 @@ #![allow(dead_code)] use quote::ToTokens; -use syn::{Attribute, Item}; +use syn::{ + Attribute, + Item, +}; use thiserror::Error; #[derive(Error, Debug)] @@ -16,8 +19,7 @@ pub trait ItemAttrsExt { where Self: ToTokens, { - self.get_ident() - .ok_or_else(|| syn::Error::new_spanned(self, "Item does not have ident")) + self.get_ident().ok_or_else(|| syn::Error::new_spanned(self, "Item does not have ident")) } fn clone_attrs(&self) -> Option>; fn attrs(&self) -> Option<&[Attribute]>; diff --git a/crates/bevy_auto_plugin_shared/src/syntax/extensions/path.rs b/crates/bevy_auto_plugin_shared/src/syntax/extensions/path.rs index 70a8ffe4..e31d9d68 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/extensions/path.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/extensions/path.rs @@ -1,5 +1,7 @@ -use crate::syntax::analysis::path; -use crate::syntax::ast::type_list::TypeList; +use crate::syntax::{ + analysis::path, + ast::type_list::TypeList, +}; use syn::Path; pub trait PathExt { diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs index ad5fef83..ac9c4b05 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs @@ -1,15 +1,18 @@ -use crate::syntax::extensions::item::ItemAttrsExt; -use crate::syntax::extensions::path::PathExt; -use syn::{Attribute, Item}; +use crate::syntax::extensions::{ + item::ItemAttrsExt, + path::PathExt, +}; +use syn::{ + Attribute, + Item, +}; pub fn item_has_attr(item: &Item, path: &syn::Path) -> syn::Result { Ok(has_attr(item.attrs().unwrap_or_default(), path)) } pub fn has_attr(attrs: &[Attribute], path: &syn::Path) -> bool { - attrs - .iter() - .any(|attr| attr.path().is_similar_path_or_ident(path)) + attrs.iter().any(|attr| attr.path().is_similar_path_or_ident(path)) } #[cfg(test)] diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index 72049f2f..749c5410 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -2,10 +2,18 @@ use crate::syntax::extensions::item::ItemAttrsExt; use darling::FromMeta; use proc_macro2::TokenStream; -use quote::{ToTokens, quote}; -use syn::spanned::Spanned; -use syn::visit_mut::VisitMut; -use syn::{Attribute, Ident, Item, Meta}; +use quote::{ + ToTokens, + quote, +}; +use syn::{ + Attribute, + Ident, + Item, + Meta, + spanned::Spanned, + visit_mut::VisitMut, +}; /// Where an attribute was attached. #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -137,18 +145,12 @@ impl ScrubOutcome { for group in self.observed.iter() { let mut attrs = vec![]; // linear search is fine here, since we expect the number of groups to be small - if let Some(removed_attrs) = self - .removed - .iter() - .find(|g| g.site == group.site) - .map(|g| g.attrs.clone()) + if let Some(removed_attrs) = + self.removed.iter().find(|g| g.site == group.site).map(|g| g.attrs.clone()) { attrs.extend(removed_attrs); } - out.push(SiteAttrs { - site: group.site.clone(), - attrs, - }); + out.push(SiteAttrs { site: group.site.clone(), attrs }); } out } @@ -159,20 +161,10 @@ impl ScrubOutcome { &self, token_stream: &mut TokenStream, ) -> syn::Result<()> { - write_back( - token_stream, - self.item.span(), - self.errors.clone(), - "failed to scrub helpers", - ) + write_back(token_stream, self.item.span(), self.errors.clone(), "failed to scrub helpers") } pub fn write_back(&self, token_stream: &mut TokenStream) -> syn::Result<()> { - write_back_item( - token_stream, - &self.item, - self.errors.clone(), - "failed to scrub helpers", - ) + write_back_item(token_stream, &self.item, self.errors.clone(), "failed to scrub helpers") } } @@ -246,10 +238,8 @@ impl Scrubber { let mut attrs = match it.take_attrs() { Ok(attrs) => attrs, Err(err) => { - self.errors.push(syn::Error::new( - it.span(), - format!("Failed to parse attrs: {err}"), - )); + self.errors + .push(syn::Error::new(it.span(), format!("Failed to parse attrs: {err}"))); return Vec::new(); } }; @@ -278,12 +268,9 @@ impl VisitMut for Scrubber { let field_ident = field.ident.clone().expect("named struct field"); let KeepSplit { keep, removed } = self.drain_split(&mut field.attrs); field.attrs = keep.clone(); - self.out.observed.push( - AttrSite::StructFieldNamed { - field: field_ident.clone(), - }, - keep, - ); + self.out + .observed + .push(AttrSite::StructFieldNamed { field: field_ident.clone() }, keep); if !removed.is_empty() { self.out .removed @@ -295,13 +282,9 @@ impl VisitMut for Scrubber { for (index, field) in fields_unnamed.unnamed.iter_mut().enumerate() { let KeepSplit { keep, removed } = self.drain_split(&mut field.attrs); field.attrs = keep.clone(); - self.out - .observed - .push(AttrSite::StructFieldUnnamed { index }, keep); + self.out.observed.push(AttrSite::StructFieldUnnamed { index }, keep); if !removed.is_empty() { - self.out - .removed - .push(AttrSite::StructFieldUnnamed { index }, removed); + self.out.removed.push(AttrSite::StructFieldUnnamed { index }, removed); } } } @@ -317,19 +300,11 @@ impl VisitMut for Scrubber { // variant-level let KeepSplit { keep, removed } = self.drain_split(&mut variant.attrs); variant.attrs = keep.clone(); - self.out.observed.push( - AttrSite::Variant { - variant: variant_ident.clone(), - }, - keep, - ); + self.out.observed.push(AttrSite::Variant { variant: variant_ident.clone() }, keep); if !removed.is_empty() { - self.out.removed.push( - AttrSite::Variant { - variant: variant_ident.clone(), - }, - removed, - ); + self.out + .removed + .push(AttrSite::Variant { variant: variant_ident.clone() }, removed); } // fields @@ -362,10 +337,7 @@ impl VisitMut for Scrubber { let KeepSplit { keep, removed } = self.drain_split(&mut field.attrs); field.attrs = keep.clone(); self.out.observed.push( - AttrSite::VariantFieldUnnamed { - variant: variant_ident.clone(), - index, - }, + AttrSite::VariantFieldUnnamed { variant: variant_ident.clone(), index }, keep, ); if !removed.is_empty() { @@ -403,11 +375,7 @@ pub fn scrub_helpers_and_ident_with_filter( let mut item: Item = syn::parse2(input)?; let ident = resolve_ident(&item)?.clone(); - let mut scrubber = Scrubber { - is_helper, - out: ScrubberOut::default(), - errors: vec![], - }; + let mut scrubber = Scrubber { is_helper, out: ScrubberOut::default(), errors: vec![] }; scrubber.visit_item_mut(&mut item); // validate “removed” helpers against the site filter @@ -450,7 +418,10 @@ mod tests { use super::*; use crate::syntax::extensions::path::PathExt; use internal_test_proc_macro::xtest; - use quote::{ToTokens, quote}; + use quote::{ + ToTokens, + quote, + }; use syn::parse_quote; impl SiteAttrsVec { @@ -493,15 +464,15 @@ mod tests { Self::StructFieldUnnamed { index } => { format!("StructFieldUnnamed {{ index: {} }}", index) } - Self::Variant { variant } => format!("Variant {{ variant: {} }}", variant), - Self::VariantFieldNamed { variant, field } => format!( - "VariantFieldNamed {{ variant: {}, field: {} }}", - variant, field - ), - Self::VariantFieldUnnamed { variant, index } => format!( - "VariantFieldUnnamed {{ variant: {}, index: {} }}", - variant, index - ), + Self::Variant { variant } => { + format!("Variant {{ variant: {} }}", variant) + } + Self::VariantFieldNamed { variant, field } => { + format!("VariantFieldNamed {{ variant: {}, field: {} }}", variant, field) + } + Self::VariantFieldUnnamed { variant, index } => { + format!("VariantFieldUnnamed {{ variant: {}, index: {} }}", variant, index) + } } } } @@ -511,11 +482,7 @@ mod tests { #[inline] fn assert_no_errors(scrub_outcome: &ScrubOutcome) { assert_eq!( - scrub_outcome - .errors - .iter() - .map(|e| e.to_string()) - .collect::>(), + scrub_outcome.errors.iter().map(|e| e.to_string()).collect::>(), Vec::::new() ); } @@ -528,11 +495,7 @@ mod tests { #[inline] fn assert_no_helpers_remain_on_item(scrub_outcome: &ScrubOutcome) { let ts = scrub_outcome.item.to_token_stream().to_string(); - assert!( - !ts.contains("::helper"), - "item still has helper attributes: {}", - ts - ); + assert!(!ts.contains("::helper"), "item still has helper attributes: {}", ts); } fn is_helper(attr: &Attribute) -> bool { @@ -562,20 +525,13 @@ mod tests { assert_no_helpers_remain_on_item(&scrub_outcome); let got = scrub_outcome.removed; let expected = SiteAttrsVec::from_vec(vec![ + SiteAttrs { site: AttrSite::Item, attrs: vec![parse_quote!(#[item::helper])] }, SiteAttrs { - site: AttrSite::Item, - attrs: vec![parse_quote!(#[item::helper])], - }, - SiteAttrs { - site: AttrSite::StructFieldNamed { - field: parse_quote!(x), - }, + site: AttrSite::StructFieldNamed { field: parse_quote!(x) }, attrs: vec![parse_quote!(#[field::helper])], }, SiteAttrs { - site: AttrSite::StructFieldNamed { - field: parse_quote!(z), - }, + site: AttrSite::StructFieldNamed { field: parse_quote!(z) }, attrs: vec![ parse_quote!(#[field::_1::helper]), parse_quote!(#[field::_2::helper]), @@ -611,20 +567,13 @@ mod tests { assert_no_helpers_remain_on_item(&scrub_outcome); let got = scrub_outcome.removed; let expected = SiteAttrsVec::from_vec(vec![ + SiteAttrs { site: AttrSite::Item, attrs: vec![parse_quote!(#[item::helper])] }, SiteAttrs { - site: AttrSite::Item, - attrs: vec![parse_quote!(#[item::helper])], - }, - SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(A), - }, + site: AttrSite::Variant { variant: parse_quote!(A) }, attrs: vec![parse_quote!(#[field::helper])], }, SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(C), - }, + site: AttrSite::Variant { variant: parse_quote!(C) }, attrs: vec![ parse_quote!(#[field::_1::helper]), parse_quote!(#[field::_2::helper]), @@ -709,28 +658,16 @@ mod tests { assert_no_helpers_remain_on_item(&scrub_outcome); let got = scrub_outcome.observed; let expected = SiteAttrsVec::from_vec(vec![ + SiteAttrs { site: AttrSite::Item, attrs: vec![parse_quote!(#[non_helper])] }, SiteAttrs { - site: AttrSite::Item, - attrs: vec![parse_quote!(#[non_helper])], - }, - SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(A), - }, + site: AttrSite::Variant { variant: parse_quote!(A) }, attrs: vec![parse_quote!(#[non_helper])], }, SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(B), - }, + site: AttrSite::Variant { variant: parse_quote!(B) }, attrs: vec![parse_quote!(#[non_helper]), parse_quote!(#[non_helper])], }, - SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(C), - }, - attrs: vec![], - }, + SiteAttrs { site: AttrSite::Variant { variant: parse_quote!(C) }, attrs: vec![] }, ]); assert_eq!( got.to_test_string(), @@ -767,43 +704,24 @@ mod tests { let got = SiteAttrsVec::from_vec(scrub_outcome.all_with_removed_attrs()); let expected = SiteAttrsVec::from_vec(vec![ + SiteAttrs { site: AttrSite::Item, attrs: vec![parse_quote!(#[item::helper])] }, SiteAttrs { - site: AttrSite::Item, - attrs: vec![parse_quote!(#[item::helper])], - }, - SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(A), - }, + site: AttrSite::Variant { variant: parse_quote!(A) }, attrs: vec![parse_quote!(#[field::helper])], }, + SiteAttrs { site: AttrSite::Variant { variant: parse_quote!(B) }, attrs: vec![] }, SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(B), - }, - attrs: vec![], - }, - SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(C), - }, + site: AttrSite::Variant { variant: parse_quote!(C) }, attrs: vec![ parse_quote!(#[field::_1::helper]), parse_quote!(#[field::_2::helper]), ], }, SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(X), - }, + site: AttrSite::Variant { variant: parse_quote!(X) }, attrs: vec![parse_quote!(#[field::helper])], }, - SiteAttrs { - site: AttrSite::Variant { - variant: parse_quote!(Y), - }, - attrs: vec![], - }, + SiteAttrs { site: AttrSite::Variant { variant: parse_quote!(Y) }, attrs: vec![] }, ]); assert_eq!( diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/non_empty_path.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/non_empty_path.rs index fbcd4236..c12febed 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/non_empty_path.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/validated/non_empty_path.rs @@ -1,9 +1,18 @@ use darling::FromMeta; -use proc_macro2::{Ident, TokenStream}; +use proc_macro2::{ + Ident, + TokenStream, +}; use quote::ToTokens; -use syn::parse::{Parse, ParseStream}; -use syn::spanned::Spanned; -use syn::{Meta, Path}; +use syn::{ + Meta, + Path, + parse::{ + Parse, + ParseStream, + }, + spanned::Spanned, +}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[repr(transparent)] @@ -20,12 +29,7 @@ impl NonEmptyPath { Self(path) } pub fn into_last_ident(self) -> Ident { - self.0 - .segments - .into_iter() - .last() - .expect("non-empty path") - .ident + self.0.segments.into_iter().last().expect("non-empty path").ident } pub fn last_ident(&self) -> &Ident { &self.0.segments.last().expect("non-empty path").ident @@ -92,8 +96,12 @@ mod tests { use super::*; use internal_test_proc_macro::xtest; use quote::quote; - use syn::punctuated::Punctuated; - use syn::{PathSegment, Token, parse_quote}; + use syn::{ + PathSegment, + Token, + parse_quote, + punctuated::Punctuated, + }; #[xtest] fn test_parse() { @@ -114,22 +122,13 @@ mod tests { fn test_to_tokens() { let input_tokens = quote!(::this); let input: NonEmptyPath = parse_quote!(#input_tokens); - assert_eq!( - input.to_token_stream().to_string(), - input_tokens.to_string() - ); + assert_eq!(input.to_token_stream().to_string(), input_tokens.to_string()); let input_tokens = quote!(Foo); let input: NonEmptyPath = parse_quote!(#input_tokens); - assert_eq!( - input.to_token_stream().to_string(), - input_tokens.to_string() - ); + assert_eq!(input.to_token_stream().to_string(), input_tokens.to_string()); let input_tokens = quote!(this::Foo); let input: NonEmptyPath = parse_quote!(#input_tokens); - assert_eq!( - input.to_token_stream().to_string(), - input_tokens.to_string() - ); + assert_eq!(input.to_token_stream().to_string(), input_tokens.to_string()); } #[xtest] @@ -137,7 +136,7 @@ mod tests { assert!( NonEmptyPath::new(Path { leading_colon: None, - segments: Punctuated::::new(), + segments: Punctuated::::new() }) .is_err() ); diff --git a/crates/bevy_auto_plugin_shared/src/syntax/validated/path_without_generics.rs b/crates/bevy_auto_plugin_shared/src/syntax/validated/path_without_generics.rs index 5ded5f47..8d9fb15f 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/validated/path_without_generics.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/validated/path_without_generics.rs @@ -1,10 +1,17 @@ use crate::syntax::extensions::path::PathExt; -use proc_macro2::{Ident, TokenStream}; +use proc_macro2::{ + Ident, + TokenStream, +}; use quote::ToTokens; -use syn::parse::Parse; -use syn::punctuated::Punctuated; -use syn::spanned::Spanned; -use syn::{Path, PathArguments, PathSegment}; +use syn::{ + Path, + PathArguments, + PathSegment, + parse::Parse, + punctuated::Punctuated, + spanned::Spanned, +}; use thiserror::Error; #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -24,10 +31,7 @@ impl From for syn::Error { TryFromPathWithoutGenericsError::HasGenerics(path) => path, TryFromPathWithoutGenericsError::InvalidPath(err) => return err, }; - syn::Error::new( - path.span(), - TryFromPathWithoutGenericsError::HasGenerics(path).to_string(), - ) + syn::Error::new(path.span(), TryFromPathWithoutGenericsError::HasGenerics(path).to_string()) } } @@ -71,10 +75,7 @@ pub fn ident_to_path_without_generics(ident: Ident) -> PathWithoutGenerics { leading_colon: None, segments: { let mut segments = Punctuated::new(); - segments.push(PathSegment { - ident, - arguments: PathArguments::None, - }); + segments.push(PathSegment { ident, arguments: PathArguments::None }); segments }, }) diff --git a/crates/bevy_auto_plugin_shared/src/test_util/combo.rs b/crates/bevy_auto_plugin_shared/src/test_util/combo.rs index 5ba3c3f6..f411b454 100644 --- a/crates/bevy_auto_plugin_shared/src/test_util/combo.rs +++ b/crates/bevy_auto_plugin_shared/src/test_util/combo.rs @@ -61,9 +61,5 @@ where } // filter out empty sets - combos - .into_iter() - .filter(|c| !c.is_empty()) - .map(|g| vec_spread![with.clone(), ..g,]) - .collect() + combos.into_iter().filter(|c| !c.is_empty()).map(|g| vec_spread![with.clone(), ..g,]).collect() } diff --git a/crates/bevy_auto_plugin_shared/src/util/macros.rs b/crates/bevy_auto_plugin_shared/src/util/macros.rs index c3dad5ab..d57b4750 100644 --- a/crates/bevy_auto_plugin_shared/src/util/macros.rs +++ b/crates/bevy_auto_plugin_shared/src/util/macros.rs @@ -151,8 +151,14 @@ pub(crate) use { #[cfg(test)] mod tests { use internal_test_proc_macro::xtest; - use proc_macro2::{Span, TokenStream}; - use quote::{ToTokens, quote}; + use proc_macro2::{ + Span, + TokenStream, + }; + use quote::{ + ToTokens, + quote, + }; #[xtest] fn test_bevy_crate_path() { @@ -171,10 +177,7 @@ mod tests { fn process(ts: syn::Result) -> TokenStream { ok_or_emit!(ts) } - assert_eq!( - process(Ok(quote! { foo_bar })).to_string(), - quote! { foo_bar }.to_string() - ); + assert_eq!(process(Ok(quote! { foo_bar })).to_string(), quote! { foo_bar }.to_string()); } #[test] diff --git a/crates/internal_test_proc_macro/src/lib.rs b/crates/internal_test_proc_macro/src/lib.rs index 2aed1cb0..4e7c2a31 100644 --- a/crates/internal_test_proc_macro/src/lib.rs +++ b/crates/internal_test_proc_macro/src/lib.rs @@ -1,6 +1,10 @@ use proc_macro::TokenStream; use quote::quote; -use syn::{Attribute, ItemFn, parse_macro_input}; +use syn::{ + Attribute, + ItemFn, + parse_macro_input, +}; /// #[xtest] => #[wasm_bindgen_test] on wasm32, else #[xtest] #[proc_macro_attribute] diff --git a/crates/internal_test_util/src/lib.rs b/crates/internal_test_util/src/lib.rs index 4c69cbc2..fba57338 100644 --- a/crates/internal_test_util/src/lib.rs +++ b/crates/internal_test_util/src/lib.rs @@ -4,8 +4,10 @@ use bevy_app::App; use bevy_internal::MinimalPlugins; use darling::ast::NestedMeta; use std::any::TypeId; -use syn::punctuated::Punctuated; -use syn::token::Comma; +use syn::{ + punctuated::Punctuated, + token::Comma, +}; pub fn create_minimal_app() -> App { let mut app = App::new(); @@ -24,10 +26,9 @@ pub fn extract_punctuated_paths(punctuated: Punctuated) -> Ve punctuated .into_iter() .map(|nested_meta| match nested_meta { - NestedMeta::Meta(meta) => meta - .require_path_only() - .cloned() - .expect("expected path only"), + NestedMeta::Meta(meta) => { + meta.require_path_only().cloned().expect("expected path only") + } NestedMeta::Lit(_) => panic!("unexpected literal"), }) .collect::>() @@ -75,15 +76,9 @@ mod tests { assert_eq!(vec_spread![1], vec![1]); assert_eq!(vec_spread![1, 2, 3], vec![1, 2, 3]); assert_eq!(vec_spread![1, 2, 3, 4, 5, 6], vec![1, 2, 3, 4, 5, 6]); - assert_eq!( - vec_spread![1, 2, 3, ..[4, 5, 6], 7, 8], - vec![1, 2, 3, 4, 5, 6, 7, 8] - ); + assert_eq!(vec_spread![1, 2, 3, ..[4, 5, 6], 7, 8], vec![1, 2, 3, 4, 5, 6, 7, 8]); assert_eq!(vec_spread![..[4, 5, 6], 7, 8], vec![4, 5, 6, 7, 8]); assert_eq!(vec_spread![1, 2, 3, ..[4, 5, 6]], vec![1, 2, 3, 4, 5, 6]); - assert_eq!( - vec_spread![1, 2, 3, ..[4, 5, 6], 7, 8, ..[9]], - vec![1, 2, 3, 4, 5, 6, 7, 8, 9] - ); + assert_eq!(vec_spread![1, 2, 3, ..[4, 5, 6], 7, 8, ..[9]], vec![1, 2, 3, 4, 5, 6, 7, 8, 9]); } } diff --git a/crates/internal_test_util/src/ui_util.rs b/crates/internal_test_util/src/ui_util.rs index 5cb2346c..a69070ff 100644 --- a/crates/internal_test_util/src/ui_util.rs +++ b/crates/internal_test_util/src/ui_util.rs @@ -1,4 +1,7 @@ -use std::fmt::{Display, Formatter}; +use std::fmt::{ + Display, + Formatter, +}; pub enum SubDir { Root, @@ -44,9 +47,21 @@ pub trait UiTest { pub mod utils { - use std::fs::{DirEntry, File, read_dir}; - use std::io::{Read, Result}; - use std::path::{Path, PathBuf}; + use std::{ + fs::{ + DirEntry, + File, + read_dir, + }, + io::{ + Read, + Result, + }, + path::{ + Path, + PathBuf, + }, + }; fn is_extension_factory(extension: Option<&str>) -> impl Fn(&DirEntry) -> bool { move |entry: &DirEntry| { @@ -86,9 +101,7 @@ pub mod utils { path: impl AsRef, extension: Option<&str>, ) -> Result> { - let rs_files = files_in_dir(path, extension)? - .map(|entry| entry.path()) - .collect::>(); + let rs_files = files_in_dir(path, extension)?.map(|entry| entry.path()).collect::>(); Ok(rs_files) } @@ -124,9 +137,11 @@ macro_rules! ui_tests { mod tests { use super::*; use internal_test_proc_macro::xtest; - use internal_test_util::ui_util::SubDir; - use internal_test_util::ui_util::UiTest; - use internal_test_util::ui_util::utils; + use internal_test_util::ui_util::{ + SubDir, + UiTest, + utils, + }; #[xtest] fn ui_tests() { let t = trybuild::TestCases::new(); diff --git a/tests/e2e/auto_add_message_generic.rs b/tests/e2e/auto_add_message_generic.rs index 10bd8a2c..8890e510 100644 --- a/tests/e2e/auto_add_message_generic.rs +++ b/tests/e2e/auto_add_message_generic.rs @@ -22,10 +22,6 @@ fn test_auto_add_message_generic() { let mut app = app(); let mut messages = app.world_mut().resource_mut::>>(); messages.write(Test(true)); - assert_eq!( - messages.drain().next(), - Some(Test(true)), - "did not auto add event" - ); + assert_eq!(messages.drain().next(), Some(Test(true)), "did not auto add event"); assert_eq!(messages.drain().next(), None, "expected only 1 event"); } diff --git a/tests/e2e/auto_add_observer.rs b/tests/e2e/auto_add_observer.rs index 4d5cd0fb..ef8b20f1 100644 --- a/tests/e2e/auto_add_observer.rs +++ b/tests/e2e/auto_add_observer.rs @@ -22,12 +22,7 @@ fn test_observer( added_foo_q: Query, Added>, mut foo_component_added: ResMut, ) { - assert!( - added_foo_q - .get(add.event().entity) - .expect("FooComponent not spawned") - .is_added() - ); + assert!(added_foo_q.get(add.event().entity).expect("FooComponent not spawned").is_added()); foo_component_added.is_added = true; } @@ -41,18 +36,12 @@ fn app() -> App { fn test_auto_add_observer() { let mut app = app(); assert!( - !app.world() - .get_resource::() - .unwrap() - .is_added, + !app.world().get_resource::().unwrap().is_added, "FooComponent should not be added yet" ); app.world_mut().spawn(FooComponent); assert!( - app.world() - .get_resource::() - .unwrap() - .is_added, + app.world().get_resource::().unwrap().is_added, "FooComponent should be added" ); } diff --git a/tests/e2e/auto_add_plugin.rs b/tests/e2e/auto_add_plugin.rs index 71d76947..6ca7b099 100644 --- a/tests/e2e/auto_add_plugin.rs +++ b/tests/e2e/auto_add_plugin.rs @@ -25,8 +25,5 @@ fn app() -> App { #[xtest] fn test_auto_add_plugin() { let app = app(); - assert!( - app.world().get_resource::().is_some(), - "did not auto add plugin" - ); + assert!(app.world().get_resource::().is_some(), "did not auto add plugin"); } diff --git a/tests/e2e/auto_add_plugin_with_default_init.rs b/tests/e2e/auto_add_plugin_with_default_init.rs index 006cb968..083c27ef 100644 --- a/tests/e2e/auto_add_plugin_with_default_init.rs +++ b/tests/e2e/auto_add_plugin_with_default_init.rs @@ -36,9 +36,5 @@ fn app() -> App { #[xtest] fn test_auto_add_plugin_with_default_init() { let app = app(); - assert_eq!( - app.world().get_resource::(), - Some(&Test(1)), - "did not auto add plugin" - ); + assert_eq!(app.world().get_resource::(), Some(&Test(1)), "did not auto add plugin"); } diff --git a/tests/e2e/auto_add_plugin_with_init.rs b/tests/e2e/auto_add_plugin_with_init.rs index c7f86564..2ec7c622 100644 --- a/tests/e2e/auto_add_plugin_with_init.rs +++ b/tests/e2e/auto_add_plugin_with_init.rs @@ -30,9 +30,5 @@ fn app() -> App { #[xtest] fn test_auto_add_plugin_with_init() { let app = app(); - assert_eq!( - app.world().get_resource::(), - Some(&Test(1)), - "did not auto add plugin" - ); + assert_eq!(app.world().get_resource::(), Some(&Test(1)), "did not auto add plugin"); } diff --git a/tests/e2e/auto_add_systems_complex_with_generics.rs b/tests/e2e/auto_add_systems_complex_with_generics.rs index 5d618769..452b86d0 100644 --- a/tests/e2e/auto_add_systems_complex_with_generics.rs +++ b/tests/e2e/auto_add_systems_complex_with_generics.rs @@ -2,8 +2,13 @@ use bevy_app::prelude::*; use bevy_auto_plugin::prelude::*; use bevy_ecs::prelude::*; use internal_test_proc_macro::xtest; -use std::fmt::Debug; -use std::ops::{Add, AddAssign}; +use std::{ + fmt::Debug, + ops::{ + Add, + AddAssign, + }, +}; trait One { const ONE: Self; diff --git a/tests/e2e/auto_add_systems_with_generics.rs b/tests/e2e/auto_add_systems_with_generics.rs index fd271cf0..6ba54e24 100644 --- a/tests/e2e/auto_add_systems_with_generics.rs +++ b/tests/e2e/auto_add_systems_with_generics.rs @@ -2,8 +2,13 @@ use bevy_app::prelude::*; use bevy_auto_plugin::prelude::*; use bevy_ecs::prelude::*; use internal_test_proc_macro::xtest; -use std::fmt::Debug; -use std::ops::{Add, AddAssign}; +use std::{ + fmt::Debug, + ops::{ + Add, + AddAssign, + }, +}; trait One { const ONE: Self; diff --git a/tests/e2e/auto_add_systems_with_set.rs b/tests/e2e/auto_add_systems_with_set.rs index 92d59be0..a634b116 100644 --- a/tests/e2e/auto_add_systems_with_set.rs +++ b/tests/e2e/auto_add_systems_with_set.rs @@ -10,10 +10,7 @@ impl Plugin for TestPlugin { #[auto_plugin] fn build(&self, app: &mut App) { app.init_resource::(); - app.configure_sets( - Update, - (TestSet::First, TestSet::Second, TestSet::Third).chain(), - ); + app.configure_sets(Update, (TestSet::First, TestSet::Second, TestSet::Third).chain()); } } diff --git a/tests/e2e/auto_bind_plugin.rs b/tests/e2e/auto_bind_plugin.rs index f13f887e..aa9fdbe1 100644 --- a/tests/e2e/auto_bind_plugin.rs +++ b/tests/e2e/auto_bind_plugin.rs @@ -4,7 +4,10 @@ use bevy::prelude::*; use bevy_auto_plugin::prelude::*; use bevy_state::app::StatesPlugin; use internal_test_proc_macro::xtest; -use internal_test_util::{create_minimal_app, type_id_of}; +use internal_test_util::{ + create_minimal_app, + type_id_of, +}; use std::ops::Deref; #[derive(AutoPlugin)] @@ -97,12 +100,7 @@ fn foo_observer( added_foo_q: Query, Added>, mut foo_component_added: ResMut, ) { - assert!( - added_foo_q - .get(add.event().entity) - .expect("FooComponent not spawned") - .is_added() - ); + assert!(added_foo_q.get(add.event().entity).expect("FooComponent not spawned").is_added()); foo_component_added.is_added = true; } @@ -118,10 +116,7 @@ fn test_auto_register_type_foo_component() { let app = app(); let type_registry = app.world().resource::().0.clone(); let type_registry = type_registry.read(); - assert!( - type_registry.contains(type_id_of::()), - "did not auto register type" - ); + assert!(type_registry.contains(type_id_of::()), "did not auto register type"); } #[xtest] @@ -133,11 +128,7 @@ fn test_auto_name_foo_component() { .query_filtered::<&Name, With>() .single(app.world()) .expect("failed to query FooComponent"); - assert_eq!( - name, - &Name::new("FooComponent"), - "did not auto name FooComponent" - ); + assert_eq!(name, &Name::new("FooComponent"), "did not auto name FooComponent"); } #[xtest] @@ -169,11 +160,7 @@ fn test_auto_add_system_foo_system() { "did not auto init resource" ); app.update(); - assert_eq!( - app.world().get_resource::(), - Some(&FooRes(2)), - "did not register system" - ); + assert_eq!(app.world().get_resource::(), Some(&FooRes(2)), "did not register system"); } #[xtest] @@ -187,10 +174,7 @@ fn test_auto_register_state_type_foo_state() { let app = app(); let type_registry = app.world().resource::().0.clone(); let type_registry = type_registry.read(); - assert!( - type_registry.contains(type_id_of::>()), - "did not auto register type" - ); + assert!(type_registry.contains(type_id_of::>()), "did not auto register type"); assert!( type_registry.contains(type_id_of::>()), "did not auto register type" @@ -201,9 +185,7 @@ fn test_auto_register_state_type_foo_state() { fn test_auto_init_state_type_foo_state() { let app = app(); assert_eq!( - app.world() - .get_resource::>() - .map(Deref::deref), + app.world().get_resource::>().map(Deref::deref), Some(&FooState::Start), "did not auto init state" ); @@ -213,18 +195,12 @@ fn test_auto_init_state_type_foo_state() { fn test_auto_add_observer_foo_observer() { let mut app = app(); assert!( - !app.world() - .get_resource::() - .unwrap() - .is_added, + !app.world().get_resource::().unwrap().is_added, "FooComponent should not be added yet" ); app.world_mut().spawn(FooComponent); assert!( - app.world() - .get_resource::() - .unwrap() - .is_added, + app.world().get_resource::().unwrap().is_added, "FooComponent should be added" ); } diff --git a/tests/e2e/auto_component.rs b/tests/e2e/auto_component.rs index 07d1f350..6d3ebea7 100644 --- a/tests/e2e/auto_component.rs +++ b/tests/e2e/auto_component.rs @@ -4,7 +4,10 @@ use bevy::prelude::*; use bevy_auto_plugin::prelude::*; use bevy_state::app::StatesPlugin; use internal_test_proc_macro::xtest; -use internal_test_util::{create_minimal_app, type_id_of}; +use internal_test_util::{ + create_minimal_app, + type_id_of, +}; #[derive(AutoPlugin)] #[auto_plugin(impl_plugin_trait)] @@ -25,10 +28,7 @@ fn test_auto_register_type_foo_component() { let app = app(); let type_registry = app.world().resource::().0.clone(); let type_registry = type_registry.read(); - assert!( - type_registry.contains(type_id_of::()), - "did not auto register type" - ); + assert!(type_registry.contains(type_id_of::()), "did not auto register type"); } #[xtest] @@ -40,9 +40,5 @@ fn test_auto_name_foo_component() { .query_filtered::<&Name, With>() .single(app.world()) .expect("failed to query FooComponent"); - assert_eq!( - name, - &Name::new("FooComponent"), - "did not auto name FooComponent" - ); + assert_eq!(name, &Name::new("FooComponent"), "did not auto name FooComponent"); } diff --git a/tests/e2e/auto_configure_system_set_schedule_config_multiple_groups.rs b/tests/e2e/auto_configure_system_set_schedule_config_multiple_groups.rs index 673c0a70..932234d8 100644 --- a/tests/e2e/auto_configure_system_set_schedule_config_multiple_groups.rs +++ b/tests/e2e/auto_configure_system_set_schedule_config_multiple_groups.rs @@ -1,4 +1,8 @@ -use bevy::prelude::{Fixed, Time, Virtual}; +use bevy::prelude::{ + Fixed, + Time, + Virtual, +}; use bevy_app::prelude::*; use bevy_auto_plugin::prelude::*; use bevy_ecs::prelude::*; diff --git a/tests/e2e/auto_init_resource.rs b/tests/e2e/auto_init_resource.rs index 6c07533d..dbf75dee 100644 --- a/tests/e2e/auto_init_resource.rs +++ b/tests/e2e/auto_init_resource.rs @@ -20,8 +20,5 @@ fn app() -> App { #[xtest] fn test_auto_init_resource() { let app = app(); - assert!( - app.world().get_resource::().is_some(), - "did not auto init resource" - ); + assert!(app.world().get_resource::().is_some(), "did not auto init resource"); } diff --git a/tests/e2e/auto_init_resource_generic.rs b/tests/e2e/auto_init_resource_generic.rs index 68664ffb..89dbe05f 100644 --- a/tests/e2e/auto_init_resource_generic.rs +++ b/tests/e2e/auto_init_resource_generic.rs @@ -20,8 +20,5 @@ fn app() -> App { #[xtest] fn test_auto_init_resource_generic() { let app = app(); - assert!( - app.world().get_resource::>().is_some(), - "did not auto init resource" - ); + assert!(app.world().get_resource::>().is_some(), "did not auto init resource"); } diff --git a/tests/e2e/auto_init_state.rs b/tests/e2e/auto_init_state.rs index 0902a3cd..bd6704b8 100644 --- a/tests/e2e/auto_init_state.rs +++ b/tests/e2e/auto_init_state.rs @@ -1,7 +1,9 @@ use bevy_app::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_state::app::StatesPlugin; -use bevy_state::prelude::*; +use bevy_state::{ + app::StatesPlugin, + prelude::*, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin)] @@ -27,12 +29,6 @@ fn app() -> App { #[xtest] fn test_auto_init_state() { let app = app(); - assert!( - app.world().get_resource::>().is_some(), - "did not auto init state" - ); - assert!( - app.world().get_resource::>().is_some(), - "did not auto init state" - ); + assert!(app.world().get_resource::>().is_some(), "did not auto init state"); + assert!(app.world().get_resource::>().is_some(), "did not auto init state"); } diff --git a/tests/e2e/auto_init_sub_state.rs b/tests/e2e/auto_init_sub_state.rs index d4ba5f18..3105c2bf 100644 --- a/tests/e2e/auto_init_sub_state.rs +++ b/tests/e2e/auto_init_sub_state.rs @@ -1,7 +1,9 @@ use bevy_app::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_state::app::StatesPlugin; -use bevy_state::prelude::*; +use bevy_state::{ + app::StatesPlugin, + prelude::*, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin)] @@ -59,48 +61,23 @@ fn test_update_state() { app.update(); - assert_eq!( - app.world() - .get_resource::>() - .map(|state| state.get()), - None, - ); + assert_eq!(app.world().get_resource::>().map(|state| state.get()), None,); - app.world_mut() - .resource_mut::>() - .into_inner() - .set(AppState::InGame); + app.world_mut().resource_mut::>().into_inner().set(AppState::InGame); app.update(); - assert_eq!( - app.world().resource::>().get(), - &IsPaused::Running, - ); + assert_eq!(app.world().resource::>().get(), &IsPaused::Running,); - app.world_mut() - .resource_mut::>() - .into_inner() - .set(IsPaused::Paused); + app.world_mut().resource_mut::>().into_inner().set(IsPaused::Paused); app.update(); - assert_eq!( - app.world().resource::>().get(), - &IsPaused::Paused, - ); + assert_eq!(app.world().resource::>().get(), &IsPaused::Paused,); - app.world_mut() - .resource_mut::>() - .into_inner() - .set(AppState::Menu); + app.world_mut().resource_mut::>().into_inner().set(AppState::Menu); app.update(); - assert_eq!( - app.world() - .get_resource::>() - .map(|state| state.get()), - None, - ); + assert_eq!(app.world().get_resource::>().map(|state| state.get()), None,); } diff --git a/tests/e2e/auto_insert_resource.rs b/tests/e2e/auto_insert_resource.rs index 00bb09d6..ba299869 100644 --- a/tests/e2e/auto_insert_resource.rs +++ b/tests/e2e/auto_insert_resource.rs @@ -21,9 +21,5 @@ fn app() -> App { #[xtest] fn test_auto_insert_resource() { let app = app(); - assert_eq!( - app.world().get_resource::(), - Some(&Test(1)), - "did not auto insert resource" - ); + assert_eq!(app.world().get_resource::(), Some(&Test(1)), "did not auto insert resource"); } diff --git a/tests/e2e/auto_name.rs b/tests/e2e/auto_name.rs index 29618ad4..f428138a 100644 --- a/tests/e2e/auto_name.rs +++ b/tests/e2e/auto_name.rs @@ -1,7 +1,9 @@ use bevy_app::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_ecs::name::Name; -use bevy_ecs::prelude::*; +use bevy_ecs::{ + name::Name, + prelude::*, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin)] @@ -27,10 +29,7 @@ fn test_auto_name() { let mut app = app(); let entity = app.world_mut().spawn(Test).id(); app.update(); - assert_eq!( - app.world().entity(entity).get::(), - Some(&Name::new("Test")) - ); + assert_eq!(app.world().entity(entity).get::(), Some(&Name::new("Test"))); } #[xtest] @@ -38,8 +37,5 @@ fn test_auto_name_with_custom_name() { let mut app = app(); let entity = app.world_mut().spawn(TestCustom).id(); app.update(); - assert_eq!( - app.world().entity(entity).get::(), - Some(&Name::new("barfoo")) - ); + assert_eq!(app.world().entity(entity).get::(), Some(&Name::new("barfoo"))); } diff --git a/tests/e2e/auto_name_with_generics.rs b/tests/e2e/auto_name_with_generics.rs index 07f18a83..9d7e936f 100644 --- a/tests/e2e/auto_name_with_generics.rs +++ b/tests/e2e/auto_name_with_generics.rs @@ -1,7 +1,9 @@ use bevy_app::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_ecs::name::Name; -use bevy_ecs::prelude::*; +use bevy_ecs::{ + name::Name, + prelude::*, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin)] @@ -23,8 +25,5 @@ fn test_auto_name() { let mut app = app(); let entity = app.world_mut().spawn(Test(true)).id(); app.update(); - assert_eq!( - app.world().entity(entity).get::(), - Some(&Name::new("Test")) - ); + assert_eq!(app.world().entity(entity).get::(), Some(&Name::new("Test"))); } diff --git a/tests/e2e/auto_plugin.rs b/tests/e2e/auto_plugin.rs index 0d947e89..4257a1cd 100644 --- a/tests/e2e/auto_plugin.rs +++ b/tests/e2e/auto_plugin.rs @@ -5,7 +5,11 @@ use bevy_auto_plugin::prelude::*; use bevy_ecs::entity::EntityHashMap; use bevy_state::app::StatesPlugin; use internal_test_proc_macro::xtest; -use internal_test_util::{create_minimal_app, type_id_of, vec_spread}; +use internal_test_util::{ + create_minimal_app, + type_id_of, + vec_spread, +}; use std::ops::Deref; #[derive(AutoPlugin)] @@ -97,12 +101,7 @@ fn foo_observer( added_foo_q: Query, Added>, mut foo_component_added: ResMut, ) { - assert!( - added_foo_q - .get(add.event().entity) - .expect("FooComponent not spawned") - .is_added() - ); + assert!(added_foo_q.get(add.event().entity).expect("FooComponent not spawned").is_added()); foo_component_added.is_added = true; } @@ -121,10 +120,7 @@ fn test_auto_register_type_foo_component() { let app = app(); let type_registry = app.world().resource::().0.clone(); let type_registry = type_registry.read(); - assert!( - type_registry.contains(type_id_of::()), - "did not auto register type" - ); + assert!(type_registry.contains(type_id_of::()), "did not auto register type"); } #[xtest] @@ -136,11 +132,7 @@ fn test_auto_name_foo_component() { .query_filtered::<&Name, With>() .single(app.world()) .expect("failed to query FooComponent"); - assert_eq!( - name, - &Name::new("FooComponent"), - "did not auto name FooComponent" - ); + assert_eq!(name, &Name::new("FooComponent"), "did not auto name FooComponent"); } #[xtest] @@ -172,11 +164,7 @@ fn test_auto_add_system_foo_system() { "did not auto init resource" ); app.update(); - assert_eq!( - app.world().get_resource::(), - Some(&FooRes(2)), - "did not register system" - ); + assert_eq!(app.world().get_resource::(), Some(&FooRes(2)), "did not register system"); } #[xtest] @@ -232,20 +220,14 @@ fn test_auto_event_foo_entity_event() { } for e in entities { - app.world_mut() - .entity_mut(e) - .trigger(|entity| FooEntityEvent { entity, value: 1 }); + app.world_mut().entity_mut(e).trigger(|entity| FooEntityEvent { entity, value: 1 }); } for e in entities { - app.world_mut() - .entity_mut(e) - .trigger(|entity| FooEntityEvent { entity, value: 2 }); + app.world_mut().entity_mut(e).trigger(|entity| FooEntityEvent { entity, value: 2 }); } - app.world_mut() - .entity_mut(c) - .trigger(|entity| FooEntityEvent { entity, value: 1 }); + app.world_mut().entity_mut(c).trigger(|entity| FooEntityEvent { entity, value: 1 }); for e in entities { let &v = app.world_mut().resource::().0.get(&e).unwrap(); @@ -258,10 +240,7 @@ fn test_auto_register_state_type_foo_state() { let app = app(); let type_registry = app.world().resource::().0.clone(); let type_registry = type_registry.read(); - assert!( - type_registry.contains(type_id_of::>()), - "did not auto register type" - ); + assert!(type_registry.contains(type_id_of::>()), "did not auto register type"); assert!( type_registry.contains(type_id_of::>()), "did not auto register type" @@ -272,9 +251,7 @@ fn test_auto_register_state_type_foo_state() { fn test_auto_init_state_type_foo_state() { let app = app(); assert_eq!( - app.world() - .get_resource::>() - .map(Deref::deref), + app.world().get_resource::>().map(Deref::deref), Some(&FooState::Start), "did not auto init state" ); @@ -284,18 +261,12 @@ fn test_auto_init_state_type_foo_state() { fn test_auto_add_observer_foo_observer() { let mut app = app(); assert!( - !app.world() - .get_resource::() - .unwrap() - .is_added, + !app.world().get_resource::().unwrap().is_added, "FooComponent should not be added yet" ); app.world_mut().spawn(FooComponent); assert!( - app.world() - .get_resource::() - .unwrap() - .is_added, + app.world().get_resource::().unwrap().is_added, "FooComponent should be added" ); } diff --git a/tests/e2e/auto_plugin_param.rs b/tests/e2e/auto_plugin_param.rs index 8922ef9f..66cc6a7e 100644 --- a/tests/e2e/auto_plugin_param.rs +++ b/tests/e2e/auto_plugin_param.rs @@ -24,8 +24,5 @@ fn test_auto_plugin_param() { let app = app(); let type_registry = app.world().resource::().0.clone(); let type_registry = type_registry.read(); - assert!( - type_registry.contains(type_id_of::()), - "did not auto register type" - ); + assert!(type_registry.contains(type_id_of::()), "did not auto register type"); } diff --git a/tests/e2e/auto_plugin_with_generics.rs b/tests/e2e/auto_plugin_with_generics.rs index 1060d1ae..22565dc4 100644 --- a/tests/e2e/auto_plugin_with_generics.rs +++ b/tests/e2e/auto_plugin_with_generics.rs @@ -3,10 +3,16 @@ use bevy_auto_plugin::prelude::*; use bevy_ecs::entity::EntityHashMap; use bevy_state::app::StatesPlugin; use internal_test_proc_macro::xtest; -use internal_test_util::{create_minimal_app, type_id_of, vec_spread}; -use std::fmt::Debug; -use std::hash::Hash; -use std::ops::AddAssign; +use internal_test_util::{ + create_minimal_app, + type_id_of, + vec_spread, +}; +use std::{ + fmt::Debug, + hash::Hash, + ops::AddAssign, +}; #[derive(AutoPlugin, Default)] #[auto_plugin(impl_plugin_trait)] @@ -83,12 +89,7 @@ fn foo_observer( T1: Debug + Default + Copy + Clone + PartialEq + Eq + Hash + Send + Sync + 'static, T2: Debug + Default + Copy + Clone + PartialEq + Eq + Hash + Send + Sync + 'static, { - assert!( - added_foo_q - .get(add.event().entity) - .expect("FooComponent not spawned") - .is_added() - ); + assert!(added_foo_q.get(add.event().entity).expect("FooComponent not spawned").is_added()); foo_component_added.is_added = true; } @@ -149,11 +150,7 @@ fn test_auto_name_foo_component() { .query_filtered::<&Name, With>>() .single(app.world()) .expect("failed to query FooComponent"); - assert_eq!( - name, - &Name::new("FooComponent"), - "did not auto name FooComponent" - ); + assert_eq!(name, &Name::new("FooComponent"), "did not auto name FooComponent"); } #[xtest] @@ -196,9 +193,7 @@ fn test_auto_add_system_foo_system() { fn test_auto_add_message_foo_event() { let mut app = app(); assert!( - app.world_mut() - .write_message(FooMessage(1u8, false)) - .is_some(), + app.world_mut().write_message(FooMessage(1u8, false)).is_some(), "did not add message type FooMessage" ); } @@ -212,12 +207,10 @@ fn test_auto_event_foo_global_event() { app.insert_resource(Counter(0)); - app.add_observer( - |on: On>, mut counter: ResMut| { - counter.0 += 1; - assert_eq!(counter.0, on.event().0); - }, - ); + app.add_observer(|on: On>, mut counter: ResMut| { + counter.0 += 1; + assert_eq!(counter.0, on.event().0); + }); app.world_mut().trigger(FooGlobalEvent(1, false)); app.world_mut().trigger(FooGlobalEvent(2, false)); @@ -252,32 +245,26 @@ fn test_auto_event_foo_entity_event() { } for e in entities { - app.world_mut() - .entity_mut(e) - .trigger(|entity| FooEntityEvent { - entity, - value1: 1, - value2: false, - }); + app.world_mut().entity_mut(e).trigger(|entity| FooEntityEvent { + entity, + value1: 1, + value2: false, + }); } for e in entities { - app.world_mut() - .entity_mut(e) - .trigger(|entity| FooEntityEvent { - entity, - value1: 2, - value2: false, - }); - } - - app.world_mut() - .entity_mut(c) - .trigger(|entity| FooEntityEvent { + app.world_mut().entity_mut(e).trigger(|entity| FooEntityEvent { entity, - value1: 1, + value1: 2, value2: false, }); + } + + app.world_mut().entity_mut(c).trigger(|entity| FooEntityEvent { + entity, + value1: 1, + value2: false, + }); for e in entities { let &v = app.world_mut().resource::().0.get(&e).unwrap(); @@ -289,18 +276,12 @@ fn test_auto_event_foo_entity_event() { fn test_auto_add_observer_foo_observer() { let mut app = app(); assert!( - !app.world() - .get_resource::() - .unwrap() - .is_added, + !app.world().get_resource::().unwrap().is_added, "FooComponent should not be added yet" ); app.world_mut().spawn(FooComponent::::default()); assert!( - app.world() - .get_resource::() - .unwrap() - .is_added, + app.world().get_resource::().unwrap().is_added, "FooComponent should be added" ); } @@ -314,10 +295,7 @@ where #[xtest] fn test_auto_component_auto_name_regression_test() { let mut app = app(); - let a = app - .world_mut() - .spawn(FooAutoNameComponent::::default()) - .id(); + let a = app.world_mut().spawn(FooAutoNameComponent::::default()).id(); let name = app .world_mut() .query::<&Name>() diff --git a/tests/e2e/auto_register_state_type.rs b/tests/e2e/auto_register_state_type.rs index af358d9a..6a886e4c 100644 --- a/tests/e2e/auto_register_state_type.rs +++ b/tests/e2e/auto_register_state_type.rs @@ -2,8 +2,10 @@ use bevy_app::prelude::*; use bevy_auto_plugin::prelude::*; use bevy_ecs::prelude::*; use bevy_reflect::prelude::*; -use bevy_state::app::StatesPlugin; -use bevy_state::prelude::*; +use bevy_state::{ + app::StatesPlugin, + prelude::*, +}; use internal_test_proc_macro::xtest; use internal_test_util::type_id_of; diff --git a/tests/e2e/auto_register_type.rs b/tests/e2e/auto_register_type.rs index 3ad09fb2..3f09b978 100644 --- a/tests/e2e/auto_register_type.rs +++ b/tests/e2e/auto_register_type.rs @@ -24,8 +24,5 @@ fn test_auto_register_type() { let app = app(); let type_registry = app.world().resource::().0.clone(); let type_registry = type_registry.read(); - assert!( - type_registry.contains(type_id_of::()), - "did not auto register type" - ); + assert!(type_registry.contains(type_id_of::()), "did not auto register type"); } diff --git a/tests/e2e/auto_register_type_generic.rs b/tests/e2e/auto_register_type_generic.rs index c750910b..acb4a700 100644 --- a/tests/e2e/auto_register_type_generic.rs +++ b/tests/e2e/auto_register_type_generic.rs @@ -24,8 +24,5 @@ fn test_auto_register_type_generic() { let app = app(); let type_registry = app.world().resource::().0.clone(); let type_registry = type_registry.read(); - assert!( - type_registry.contains(type_id_of::>()), - "did not auto register type" - ); + assert!(type_registry.contains(type_id_of::>()), "did not auto register type"); } diff --git a/tests/e2e/auto_run_on_build_with_generics.rs b/tests/e2e/auto_run_on_build_with_generics.rs index d01a5921..c0f74251 100644 --- a/tests/e2e/auto_run_on_build_with_generics.rs +++ b/tests/e2e/auto_run_on_build_with_generics.rs @@ -29,14 +29,8 @@ struct FooResource(usize); #[auto_run_on_build(plugin = Test, generics(Foo), generics(Bar))] fn run_this(app: &mut App) { - let value = app - .world_mut() - .get_resource::() - .copied() - .unwrap_or_default() - .0; - app.world_mut() - .insert_resource(FooResource(value + T::AMOUNT)); + let value = app.world_mut().get_resource::().copied().unwrap_or_default().0; + app.world_mut().insert_resource(FooResource(value + T::AMOUNT)); } fn foo(mut res: ResMut) { diff --git a/tests/e2e/auto_system_schedule_multiple.rs b/tests/e2e/auto_system_schedule_multiple.rs index 66f90ecb..4673343a 100644 --- a/tests/e2e/auto_system_schedule_multiple.rs +++ b/tests/e2e/auto_system_schedule_multiple.rs @@ -76,17 +76,11 @@ mod test { assert_eq!(app.world().get_resource::().unwrap().0, 0); - assert_eq!( - app.world().get_resource::().unwrap().get(), - (0, None) - ); + assert_eq!(app.world().get_resource::().unwrap().get(), (0, None)); app.update(); - assert_eq!( - app.world().get_resource::().unwrap().get(), - (3, Some("system_c")) - ); + assert_eq!(app.world().get_resource::().unwrap().get(), (3, Some("system_c"))); assert_eq!(app.world().get_resource::().unwrap().0, 0); } diff --git a/tests/e2e/auto_system_schedule_non_path.rs b/tests/e2e/auto_system_schedule_non_path.rs index 841187f9..a6695ac2 100644 --- a/tests/e2e/auto_system_schedule_non_path.rs +++ b/tests/e2e/auto_system_schedule_non_path.rs @@ -75,16 +75,10 @@ mod test { let mut app = app(); app.add_plugins(TestPlugin); - assert_eq!( - app.world().get_resource::().unwrap().get(), - (0, None) - ); + assert_eq!(app.world().get_resource::().unwrap().get(), (0, None)); app.update(); - assert_eq!( - app.world().get_resource::().unwrap().get(), - (3, Some("system_c")) - ); + assert_eq!(app.world().get_resource::().unwrap().get(), (3, Some("system_c"))); } } diff --git a/tests/e2e/auto_system_schedule_on_state.rs b/tests/e2e/auto_system_schedule_on_state.rs index e9aff6e9..0556b913 100644 --- a/tests/e2e/auto_system_schedule_on_state.rs +++ b/tests/e2e/auto_system_schedule_on_state.rs @@ -51,9 +51,7 @@ mod test { app.update(); assert_eq!(app.world().get_resource::().unwrap().0, 0); - app.world_mut() - .resource_mut::>() - .set(TestState::Run); + app.world_mut().resource_mut::>().set(TestState::Run); app.update(); assert_eq!(app.world().get_resource::().unwrap().0, 1); diff --git a/tests/e2e/bare_fn.rs b/tests/e2e/bare_fn.rs index baced1d8..0e646155 100644 --- a/tests/e2e/bare_fn.rs +++ b/tests/e2e/bare_fn.rs @@ -1,6 +1,9 @@ use bevy::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_auto_plugin_proc_macros::{auto_init_resource, auto_insert_resource}; +use bevy_auto_plugin_proc_macros::{ + auto_init_resource, + auto_insert_resource, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin)] diff --git a/tests/e2e/bare_fn_default_app_param.rs b/tests/e2e/bare_fn_default_app_param.rs index 41669843..ed6aa8fd 100644 --- a/tests/e2e/bare_fn_default_app_param.rs +++ b/tests/e2e/bare_fn_default_app_param.rs @@ -1,6 +1,9 @@ use bevy::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_auto_plugin_proc_macros::{auto_init_resource, auto_insert_resource}; +use bevy_auto_plugin_proc_macros::{ + auto_init_resource, + auto_insert_resource, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin)] diff --git a/tests/e2e/self_impl_plugin.rs b/tests/e2e/self_impl_plugin.rs index 16aba578..0f024e2d 100644 --- a/tests/e2e/self_impl_plugin.rs +++ b/tests/e2e/self_impl_plugin.rs @@ -1,6 +1,9 @@ use bevy::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_auto_plugin_proc_macros::{auto_init_resource, auto_insert_resource}; +use bevy_auto_plugin_proc_macros::{ + auto_init_resource, + auto_insert_resource, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin)] diff --git a/tests/e2e/self_impl_plugin_default_app_param.rs b/tests/e2e/self_impl_plugin_default_app_param.rs index 054dc692..1d72322e 100644 --- a/tests/e2e/self_impl_plugin_default_app_param.rs +++ b/tests/e2e/self_impl_plugin_default_app_param.rs @@ -1,6 +1,9 @@ use bevy::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_auto_plugin_proc_macros::{auto_init_resource, auto_insert_resource}; +use bevy_auto_plugin_proc_macros::{ + auto_init_resource, + auto_insert_resource, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin)] diff --git a/tests/e2e/self_impl_plugin_with_generics.rs b/tests/e2e/self_impl_plugin_with_generics.rs index 17f99213..02e6bb07 100644 --- a/tests/e2e/self_impl_plugin_with_generics.rs +++ b/tests/e2e/self_impl_plugin_with_generics.rs @@ -1,6 +1,9 @@ use bevy::prelude::*; use bevy_auto_plugin::prelude::*; -use bevy_auto_plugin_proc_macros::{auto_init_resource, auto_insert_resource}; +use bevy_auto_plugin_proc_macros::{ + auto_init_resource, + auto_insert_resource, +}; use internal_test_proc_macro::xtest; #[derive(AutoPlugin, Default)] diff --git a/tests/e2e/ui_tests.rs b/tests/e2e/ui_tests.rs index 67f01b8c..da52212b 100644 --- a/tests/e2e/ui_tests.rs +++ b/tests/e2e/ui_tests.rs @@ -1,5 +1,7 @@ -use internal_test_util::ui_tests; -use internal_test_util::ui_util::UiTest; +use internal_test_util::{ + ui_tests, + ui_util::UiTest, +}; struct UiTests; From 7c2b2a152b0bf3120fcc69a16d17739ad39e5c8c Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 14:09:18 -0400 Subject: [PATCH 108/162] chore(config): switch CI Rust toolchain to nightly for rustfmt jobs --- .github/workflows/ci.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 102e548d..c60934ce 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -54,15 +54,15 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Setup Rust with rustfmt + - name: Setup Rust (nightly) with rustfmt uses: actions-rust-lang/setup-rust-toolchain@v1 with: - toolchain: stable + toolchain: nightly components: rustfmt override: true - - name: Run rustfmt - run: cargo +stable fmt --all -- --check + - name: Run rustfmt (nightly) + run: cargo +nightly fmt --all -- --check clippy: runs-on: ubuntu-latest From d79dccd772b4cea07efe0b45e42aeaa693c6e5b1 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 14:33:39 -0400 Subject: [PATCH 109/162] chore(config): set `array_width` to 60 in `rustfmt.toml` --- rustfmt.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/rustfmt.toml b/rustfmt.toml index 4eb77fda..40b2b528 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -3,6 +3,7 @@ normalize_comments = true use_field_init_shorthand = true newline_style = "Unix" style_edition = "2024" +array_width = 60 unstable_features = true imports_granularity = "Crate" # consolidate use by crate From 79436e068566757a8ac922eaf8b6f8906f66a3a0 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 14:33:53 -0400 Subject: [PATCH 110/162] refactor: apply rustfmt --- .../src/codegen/tokens.rs | 32 ++++++++++++++++--- .../src/syntax/ast/type_list.rs | 5 ++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs index 16fa2a97..017f21eb 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs @@ -89,27 +89,49 @@ pub fn derive_component<'a>( extra_items: impl IntoIterator, ) -> TokenStream { derive_from( - [vec![&derive_component_path()], extra_items.into_iter().collect::>()].concat(), + [ + vec![&derive_component_path()], + extra_items.into_iter().collect::>(), + ] + .concat(), ) } pub fn derive_resource<'a>(extra_items: impl IntoIterator) -> TokenStream { derive_from( - [vec![&derive_resource_path()], extra_items.into_iter().collect::>()].concat(), + [ + vec![&derive_resource_path()], + extra_items.into_iter().collect::>(), + ] + .concat(), ) } pub fn derive_event<'a>(extra_items: impl IntoIterator) -> TokenStream { - derive_from([vec![&derive_event_path()], extra_items.into_iter().collect::>()].concat()) + derive_from( + [ + vec![&derive_event_path()], + extra_items.into_iter().collect::>(), + ] + .concat(), + ) } pub fn derive_entity_event<'a>( extra_items: impl IntoIterator, ) -> TokenStream { derive_from( - [vec![&derive_entity_event_path()], extra_items.into_iter().collect::>()].concat(), + [ + vec![&derive_entity_event_path()], + extra_items.into_iter().collect::>(), + ] + .concat(), ) } pub fn derive_message<'a>(extra_items: impl IntoIterator) -> TokenStream { derive_from( - [vec![&derive_message_path()], extra_items.into_iter().collect::>()].concat(), + [ + vec![&derive_message_path()], + extra_items.into_iter().collect::>(), + ] + .concat(), ) } pub fn derive_states<'a>(extra_items: impl IntoIterator) -> ExpandAttrs { diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs index 519591cc..e8c3ed9d 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs @@ -56,7 +56,10 @@ impl From for TokenStream { } fn failed_err(e: syn::Error, span: &proc_macro2::Span) -> Error { - Error::multiple(vec![Error::custom("failed to parse TypeList").with_span(span), Error::from(e)]) + Error::multiple(vec![ + Error::custom("failed to parse TypeList").with_span(span), + Error::from(e), + ]) } impl FromMeta for TypeList { From 1313467a7c048e04e28ddb1927f01fe21e1e7452 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 14:57:25 -0400 Subject: [PATCH 111/162] refactor: improve error handling and literal detection in `TypeList` parsing --- .../src/syntax/ast/type_list.rs | 75 +++++++++++++++++-- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs b/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs index e8c3ed9d..6aeb71ad 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/ast/type_list.rs @@ -2,7 +2,10 @@ use darling::{ Error, FromMeta, }; -use proc_macro2::TokenStream; +use proc_macro2::{ + TokenStream, + TokenTree, +}; use quote::{ ToTokens, quote, @@ -55,21 +58,50 @@ impl From for TokenStream { } } +fn failed_err_literal(e: syn::Error, span: &proc_macro2::Span) -> Error { + Error::multiple(vec![ + Error::custom( + "Failed to parse TypeList: expected a list of *types*, but found literal value(s). \ + Use types like `Foo`, `Vec`, `Option`; not `1`, `true`, or string literals." + ).with_span(span), + Error::from(e), + ]) +} + fn failed_err(e: syn::Error, span: &proc_macro2::Span) -> Error { Error::multiple(vec![ - Error::custom("failed to parse TypeList").with_span(span), + Error::custom("Failed to parse TypeList").with_span(span), Error::from(e), ]) } +/// Inspect `TokenStream` for `Literal` +fn contains_literal(ts: &TokenStream) -> bool { + ts.clone().into_iter().any(|tt| matches!(tt, TokenTree::Literal(_))) +} + +/// Inspect `ParseStream` for `Literal` +fn fork_has_literal(input: syn::parse::ParseStream) -> bool { + let f = input.fork(); + let ts: TokenStream = match f.parse() { + Ok(ts) => ts, + Err(_) => return false, + }; + ts.into_iter().any(|tt| matches!(tt, TokenTree::Literal(_))) +} + impl FromMeta for TypeList { fn from_meta(meta: &Meta) -> Result { let list = meta.require_list()?; // Parse its tokens as `T, T, ...` where each `T` is a syn::Type let parser = Punctuated::::parse_terminated; - let elems = parser - .parse2(list.tokens.clone()) - .map_err(|e| failed_err(e, &list.tokens.to_token_stream().span()))?; + let elems = parser.parse2(list.tokens.clone()).map_err(|e| { + if contains_literal(&list.tokens) { + failed_err_literal(e, &list.tokens.span()) + } else { + failed_err(e, &list.tokens.span()) + } + })?; Ok(TypeList(elems.into_iter().collect())) } } @@ -82,7 +114,13 @@ impl syn::parse::Parse for TypeList { punctuated::Punctuated, }; let elems = Punctuated::::parse_terminated(input) - .map_err(|e| failed_err(e, &input.span()))? + .map_err(|e| { + if fork_has_literal(input) { + failed_err_literal(e, &input.span()) + } else { + failed_err(e, &input.span()) + } + })? .into_iter() .collect(); Ok(TypeList(elems)) @@ -97,15 +135,40 @@ mod tests { Meta, Type, parse_quote, + parse2, }; #[derive(Debug, FromMeta)] + #[darling(derive_syn_parse)] pub struct FooAttr { pub types: TypeList, } #[xtest] fn parse_types() { + let types = quote! { u32, i32, FooBar, [u8; 4] }; + let meta: Meta = parse_quote!(types(#types)); + let attr: FooAttr = parse2(meta.to_token_stream()).unwrap(); + + assert_eq!(attr.types.0.len(), 4); + + // The third element should be `Foo` with generics preserved. + match &attr.types.0[2] { + Type::Path(tp) => { + let seg = tp.path.segments.last().unwrap(); + assert_eq!(seg.ident, "FooBar"); + assert!(matches!(seg.arguments, syn::PathArguments::AngleBracketed(_))); + } + _ => panic!("expected Type::Path for element 2"), + } + + let type_list = &attr.types; + let tokens = quote! { #type_list }; + assert_eq!(tokens.to_string(), types.to_string()); + } + + #[xtest] + fn from_meta_types() { let types = quote! { u32, i32, FooBar, [u8; 4] }; let meta: Meta = parse_quote!(foo(types(#types))); let attr: FooAttr = FooAttr::from_meta(&meta).unwrap(); From 756d14dbd27b4b5380ea1547ec8c9c90ce5f8891 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 15:01:49 -0400 Subject: [PATCH 112/162] refactor: use call site span for attribute highlighting --- .../bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index c485ffe2..9a44cf1f 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -5,6 +5,7 @@ use crate::{ }; use proc_macro2::{ Ident, + Span, TokenStream, }; use quote::format_ident; @@ -18,7 +19,6 @@ use syn::{ parse::Parse, parse_quote, parse2, - spanned::Spanned, }; mod actions; @@ -283,7 +283,8 @@ where let mut input_item = InputItem::Tokens(input); let item = input_item.ensure_ast()?; let Some(target) = Resolver::resolve_ident_path(item) else { - return Err(syn::Error::new(input_item.span(), Resolver::NOT_ALLOWED_MESSAGE)); + // call-site because we want to highlight the attribute + return Err(syn::Error::new(Span::call_site(), Resolver::NOT_ALLOWED_MESSAGE)); }; Ok(Self { args: parse2::(attr)?, context, input_item, target, _resolver: PhantomData }) } From f18f17fc827f0e1c54ee0821872bf282656da625 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 15:51:43 -0400 Subject: [PATCH 113/162] refactor: use from_meta instead of parse2 to restore meaningful error messages --- .../src/macro_api/attributes/mod.rs | 28 +++++++++++++++---- .../ui/auto_register_type_wrong_item.stderr | 2 +- tests/e2e/ui/bad_generics_type.stderr | 4 +-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs index 9a44cf1f..96b7784d 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/mod.rs @@ -3,6 +3,10 @@ use crate::{ syntax::validated::non_empty_path::NonEmptyPath, util::macros::impl_from_default, }; +use darling::{ + FromMeta, + ast::NestedMeta, +}; use proc_macro2::{ Ident, Span, @@ -16,9 +20,10 @@ use std::{ use syn::{ Item, Path, - parse::Parse, + Token, + parse::Parser, parse_quote, - parse2, + punctuated::Punctuated, }; mod actions; @@ -258,7 +263,7 @@ pub trait ItemAttributeParse { impl ItemAttributeParse for ItemAttribute where - T: Parse, + T: FromMeta, Resolver: IdentPathResolver, { fn from_attr_input_with_context( @@ -272,7 +277,7 @@ where impl ItemAttribute where - T: Parse, + T: FromMeta, Resolver: IdentPathResolver, { pub fn from_attr_input( @@ -286,7 +291,20 @@ where // call-site because we want to highlight the attribute return Err(syn::Error::new(Span::call_site(), Resolver::NOT_ALLOWED_MESSAGE)); }; - Ok(Self { args: parse2::(attr)?, context, input_item, target, _resolver: PhantomData }) + // Parse the attribute’s inner tokens as: Meta, Meta, ... + let metas: Punctuated = + Punctuated::::parse_terminated.parse2(attr)?; + + // darling expects a slice of `Meta` + let metas_vec: Vec = metas.into_iter().collect(); + + Ok(Self { + args: T::from_list(&metas_vec)?, + context, + input_item, + target, + _resolver: PhantomData, + }) } } diff --git a/tests/e2e/ui/auto_register_type_wrong_item.stderr b/tests/e2e/ui/auto_register_type_wrong_item.stderr index 04e8839f..b4b6dae1 100644 --- a/tests/e2e/ui/auto_register_type_wrong_item.stderr +++ b/tests/e2e/ui/auto_register_type_wrong_item.stderr @@ -1,4 +1,4 @@ -error: Attribute macro is not allowed on Fn: Expected Struct or Enum +error: Only allowed on Struct Or Enum items --> tests/e2e/ui/auto_register_type_wrong_item.rs:7:1 | 7 | #[auto_register_type(plugin = TestPlugin)] diff --git a/tests/e2e/ui/bad_generics_type.stderr b/tests/e2e/ui/bad_generics_type.stderr index adc6739d..79bb6e12 100644 --- a/tests/e2e/ui/bad_generics_type.stderr +++ b/tests/e2e/ui/bad_generics_type.stderr @@ -1,8 +1,8 @@ -error: failed to parse TypeList +error: Failed to parse TypeList: expected a list of *types*, but found literal value(s). Use types like `Foo`, `Vec`, `Option`; not `1`, `true`, or string literals. --> tests/e2e/ui/bad_generics_type.rs:7:52 | 7 | #[auto_register_type(plugin = TestPlugin, generics(1, 1))] - | ^ + | ^^^^ error: expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, `dyn`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime --> tests/e2e/ui/bad_generics_type.rs:7:52 From 1d5cf0a235a080f2152fee1a20190a86647a7b7e Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 15:54:26 -0400 Subject: [PATCH 114/162] fix(tests): correct error highlighting in `bad_generics_type` test output --- tests/e2e/ui/bad_generics_type.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/ui/bad_generics_type.stderr b/tests/e2e/ui/bad_generics_type.stderr index 79bb6e12..5ed51757 100644 --- a/tests/e2e/ui/bad_generics_type.stderr +++ b/tests/e2e/ui/bad_generics_type.stderr @@ -2,7 +2,7 @@ error: Failed to parse TypeList: expected a list of *types*, but found literal v --> tests/e2e/ui/bad_generics_type.rs:7:52 | 7 | #[auto_register_type(plugin = TestPlugin, generics(1, 1))] - | ^^^^ + | ^ error: expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, `dyn`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime --> tests/e2e/ui/bad_generics_type.rs:7:52 From 3fd6ed02efccfd2ec5dfab48456989b61884659c Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 15:57:24 -0400 Subject: [PATCH 115/162] refactor(tests): split `bad_generics_type` tests to separate `nightly` and `stable` folders --- tests/e2e/ui/{ => nightly}/bad_generics_type.rs | 0 tests/e2e/ui/nightly/bad_generics_type.stderr | 11 +++++++++++ tests/e2e/ui/stable/bad_generics_type.rs | 11 +++++++++++ tests/e2e/ui/{ => stable}/bad_generics_type.stderr | 4 ++-- 4 files changed, 24 insertions(+), 2 deletions(-) rename tests/e2e/ui/{ => nightly}/bad_generics_type.rs (100%) create mode 100644 tests/e2e/ui/nightly/bad_generics_type.stderr create mode 100644 tests/e2e/ui/stable/bad_generics_type.rs rename tests/e2e/ui/{ => stable}/bad_generics_type.stderr (84%) diff --git a/tests/e2e/ui/bad_generics_type.rs b/tests/e2e/ui/nightly/bad_generics_type.rs similarity index 100% rename from tests/e2e/ui/bad_generics_type.rs rename to tests/e2e/ui/nightly/bad_generics_type.rs diff --git a/tests/e2e/ui/nightly/bad_generics_type.stderr b/tests/e2e/ui/nightly/bad_generics_type.stderr new file mode 100644 index 00000000..c420ab04 --- /dev/null +++ b/tests/e2e/ui/nightly/bad_generics_type.stderr @@ -0,0 +1,11 @@ +error: Failed to parse TypeList: expected a list of *types*, but found literal value(s). Use types like `Foo`, `Vec`, `Option`; not `1`, `true`, or string literals. + --> tests/e2e/ui/nightly/bad_generics_type.rs:7:52 + | +7 | #[auto_register_type(plugin = TestPlugin, generics(1, 1))] + | ^^^^ + +error: expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, `dyn`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime + --> tests/e2e/ui/nightly/bad_generics_type.rs:7:52 + | +7 | #[auto_register_type(plugin = TestPlugin, generics(1, 1))] + | ^ diff --git a/tests/e2e/ui/stable/bad_generics_type.rs b/tests/e2e/ui/stable/bad_generics_type.rs new file mode 100644 index 00000000..cb4c39b7 --- /dev/null +++ b/tests/e2e/ui/stable/bad_generics_type.rs @@ -0,0 +1,11 @@ +use bevy_auto_plugin::prelude::*; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct TestPlugin; + +#[auto_register_type(plugin = TestPlugin, generics(1, 1))] +struct Foo(T1, T2); + +// dummy main +fn main() {} diff --git a/tests/e2e/ui/bad_generics_type.stderr b/tests/e2e/ui/stable/bad_generics_type.stderr similarity index 84% rename from tests/e2e/ui/bad_generics_type.stderr rename to tests/e2e/ui/stable/bad_generics_type.stderr index 5ed51757..3d7d33fe 100644 --- a/tests/e2e/ui/bad_generics_type.stderr +++ b/tests/e2e/ui/stable/bad_generics_type.stderr @@ -1,11 +1,11 @@ error: Failed to parse TypeList: expected a list of *types*, but found literal value(s). Use types like `Foo`, `Vec`, `Option`; not `1`, `true`, or string literals. - --> tests/e2e/ui/bad_generics_type.rs:7:52 + --> tests/e2e/ui/stable/bad_generics_type.rs:7:52 | 7 | #[auto_register_type(plugin = TestPlugin, generics(1, 1))] | ^ error: expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, `dyn`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime - --> tests/e2e/ui/bad_generics_type.rs:7:52 + --> tests/e2e/ui/stable/bad_generics_type.rs:7:52 | 7 | #[auto_register_type(plugin = TestPlugin, generics(1, 1))] | ^ From 136cce3037b3eea13b7945d3dcc197c602ffc980 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 15:59:54 -0400 Subject: [PATCH 116/162] refactor: remove deprecated modes export --- src/lib.rs | 73 ------------------------------------------------------ 1 file changed, 73 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 588561a4..9f6860a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,76 +77,3 @@ pub mod prelude { #[doc(inline)] pub use bevy_auto_plugin_proc_macros::auto_configure_system_set; } - -#[deprecated(since = "0.7.0", note = "bevy_auto_plugin::prelude::* instead")] -pub mod modes { - #[deprecated(since = "0.7.0", note = "bevy_auto_plugin::prelude::* instead")] - pub mod global { - #[deprecated(since = "0.7.0", note = "bevy_auto_plugin::prelude::* instead")] - pub mod prelude { - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::AutoPlugin; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_add_message; - - #[doc(inline)] - #[deprecated(since = "0.6.0", note = "Use `auto_add_message` instead.")] - pub use bevy_auto_plugin_proc_macros::auto_add_message as auto_add_event; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_add_system; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_init_resource; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_init_state; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_insert_resource; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_name; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_plugin; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_register_state_type; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_register_type; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_add_observer; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_component; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_resource; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_event; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_message; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_states; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_system; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_observer; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_run_on_build; - - #[doc(inline)] - pub use bevy_auto_plugin_proc_macros::auto_bind_plugin; - } - } -} From 55f0f9428234c362c5623b4284f88876a598c172 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:08:36 -0400 Subject: [PATCH 117/162] refactor: move docs to root crate --- .../bevy_auto_plugin_proc_macros/src/lib.rs | 23 --------- .../proc_attributes/auto_add_message.md | 0 .../proc_attributes/auto_add_observer.md | 0 .../proc_attributes/auto_add_plugin.md | 0 .../proc_attributes/auto_add_system.md | 0 .../proc_attributes/auto_bind_plugin.md | 0 .../proc_attributes/auto_component.md | 0 .../auto_configure_system_set.md | 2 +- .../auto_configure_system_set_config.md | 0 .../proc_attributes/auto_event.md | 0 .../proc_attributes/auto_init_resource.md | 0 .../proc_attributes/auto_init_state.md | 0 .../proc_attributes/auto_init_sub_state.md | 0 .../proc_attributes/auto_insert_resource.md | 0 .../proc_attributes/auto_message.md | 0 .../proc_attributes/auto_name.md | 0 .../proc_attributes/auto_observer.md | 0 .../proc_attributes/auto_plugin.md | 0 .../auto_register_state_type.md | 0 .../proc_attributes/auto_register_type.md | 0 .../proc_attributes/auto_resource.md | 0 .../proc_attributes/auto_run_on_build.md | 0 .../proc_attributes/auto_states.md | 0 .../proc_attributes/auto_system.md | 0 .../proc_attributes/derive_auto_plugin.md | 0 src/lib.rs | 48 +++++++++---------- 26 files changed, 25 insertions(+), 48 deletions(-) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_add_message.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_add_observer.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_add_plugin.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_add_system.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_bind_plugin.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_component.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_configure_system_set.md (97%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_configure_system_set_config.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_event.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_init_resource.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_init_state.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_init_sub_state.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_insert_resource.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_message.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_name.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_observer.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_plugin.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_register_state_type.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_register_type.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_resource.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_run_on_build.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_states.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/auto_system.md (100%) rename {crates/bevy_auto_plugin_proc_macros/docs => docs}/proc_attributes/derive_auto_plugin.md (100%) diff --git a/crates/bevy_auto_plugin_proc_macros/src/lib.rs b/crates/bevy_auto_plugin_proc_macros/src/lib.rs index f7e65967..a4e51e02 100644 --- a/crates/bevy_auto_plugin_proc_macros/src/lib.rs +++ b/crates/bevy_auto_plugin_proc_macros/src/lib.rs @@ -13,14 +13,12 @@ fn handle_attribute MacroStream>( } /// Derives `AutoPlugin` which generates the initialization function that automatically registering types, events, and resources in the `App`. -#[doc = include_str!("../docs/proc_attributes/derive_auto_plugin.md")] #[proc_macro_derive(AutoPlugin, attributes(auto_plugin))] pub fn derive_auto_plugin(input: CompilerStream) -> CompilerStream { expand::derive::auto_plugin::expand_derive_auto_plugin(input.into()).into() } /// Attaches to a fn and injects a call to the initialization function that automatically registering types, events, and resources in the `App`. -#[doc = include_str!("../docs/proc_attributes/auto_plugin.md")] #[allow(unused_variables, unused_mut, unreachable_code)] #[proc_macro_attribute] pub fn auto_plugin(attr: CompilerStream, input: CompilerStream) -> CompilerStream { @@ -28,147 +26,126 @@ pub fn auto_plugin(attr: CompilerStream, input: CompilerStream) -> CompilerStrea } /// Automatically registers a type with the Bevy `App`. -#[doc = include_str!("../docs/proc_attributes/auto_register_type.md")] #[proc_macro_attribute] pub fn auto_register_type(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_register_type, attr, input) } /// Automatically adds a message type to the Bevy `App`. -#[doc = include_str!("../docs/proc_attributes/auto_add_message.md")] #[proc_macro_attribute] pub fn auto_add_message(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_add_message, attr, input) } /// Automatically configures a `SystemSet`. -#[doc = include_str!("../docs/proc_attributes/auto_configure_system_set.md")] #[proc_macro_attribute] pub fn auto_configure_system_set(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_configure_system_set, attr, input) } /// Automatically inserts a resource in the Bevy `App`. -#[doc = include_str!("../docs/proc_attributes/auto_init_resource.md")] #[proc_macro_attribute] pub fn auto_init_resource(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_init_resource, attr, input) } /// Automatically inserts a resource in the Bevy `App`. -#[doc = include_str!("../docs/proc_attributes/auto_insert_resource.md")] #[proc_macro_attribute] pub fn auto_insert_resource(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_insert_resource, attr, input) } /// Automatically initializes a State in the Bevy `App`. -#[doc = include_str!("../docs/proc_attributes/auto_init_state.md")] #[proc_macro_attribute] pub fn auto_init_state(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_init_state, attr, input) } /// Automatically initializes a SubState in the Bevy `App`. -#[doc = include_str!("../docs/proc_attributes/auto_init_sub_state.md")] #[proc_macro_attribute] pub fn auto_init_sub_state(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_init_sub_state, attr, input) } /// Automatically registers a required component `Name` with a value using the concrete name of the item. -#[doc = include_str!("../docs/proc_attributes/auto_name.md")] #[proc_macro_attribute] pub fn auto_name(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_name, attr, input) } /// Automatically registers item as States for bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_register_state_type.md")] #[proc_macro_attribute] pub fn auto_register_state_type(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_register_state_type, attr, input) } /// Automatically adds the fn as a system for bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_add_system.md")] #[proc_macro_attribute] pub fn auto_add_system(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_add_system, attr, input) } /// Automatically adds the fn as a proc_attributes observer to bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_add_observer.md")] #[proc_macro_attribute] pub fn auto_add_observer(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_add_observer, attr, input) } /// Automatically adds the plugin as a sub-plugin to bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_add_system.md")] #[proc_macro_attribute] pub fn auto_add_plugin(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_add_plugin, attr, input) } /// Automatically registers item as Component for bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_component.md")] #[proc_macro_attribute] pub fn auto_component(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_component, attr, input) } /// Automatically registers item as Resource for bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_resource.md")] #[proc_macro_attribute] pub fn auto_resource(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_resource, attr, input) } /// Automatically registers item as Event for bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_event.md")] #[proc_macro_attribute] pub fn auto_event(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_event, attr, input) } /// Automatically registers item as Message for bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_message.md")] #[proc_macro_attribute] pub fn auto_message(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_message, attr, input) } /// Automatically registers item as States for bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_states.md")] #[proc_macro_attribute] pub fn auto_states(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_states, attr, input) } /// Automatically adds the fn as a system for bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_system.md")] #[proc_macro_attribute] pub fn auto_system(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_system, attr, input) } /// Automatically adds proc_attributes observer to bevy app. (See below for additional options) -#[doc = include_str!("../docs/proc_attributes/auto_observer.md")] #[proc_macro_attribute] pub fn auto_observer(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_observer, attr, input) } /// Automatically binds `plugin = _` to every auto_* attribute below it -#[doc = include_str!("../docs/proc_attributes/auto_run_on_build.md")] #[proc_macro_attribute] pub fn auto_run_on_build(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_run_on_build, attr, input) } /// Automatically binds `plugin = _` to every auto_* attribute below it -#[doc = include_str!("../docs/proc_attributes/auto_bind_plugin.md")] #[proc_macro_attribute] pub fn auto_bind_plugin(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_bind_plugin::auto_bind_plugin_outer, attr, input) diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_add_message.md b/docs/proc_attributes/auto_add_message.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_add_message.md rename to docs/proc_attributes/auto_add_message.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_add_observer.md b/docs/proc_attributes/auto_add_observer.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_add_observer.md rename to docs/proc_attributes/auto_add_observer.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_add_plugin.md b/docs/proc_attributes/auto_add_plugin.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_add_plugin.md rename to docs/proc_attributes/auto_add_plugin.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_add_system.md b/docs/proc_attributes/auto_add_system.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_add_system.md rename to docs/proc_attributes/auto_add_system.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_bind_plugin.md b/docs/proc_attributes/auto_bind_plugin.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_bind_plugin.md rename to docs/proc_attributes/auto_bind_plugin.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_component.md b/docs/proc_attributes/auto_component.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_component.md rename to docs/proc_attributes/auto_component.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_configure_system_set.md b/docs/proc_attributes/auto_configure_system_set.md similarity index 97% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_configure_system_set.md rename to docs/proc_attributes/auto_configure_system_set.md index 689fcc6f..bac1b867 100644 --- a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_configure_system_set.md +++ b/docs/proc_attributes/auto_configure_system_set.md @@ -36,7 +36,7 @@ struct MySet; # Example Enum -See [auto_configure_system_set_config](./auto_configure_system_set_config.md) for details. +See [auto_configure_system_set_config](auto_configure_system_set_config.md) for details. ```rust use bevy::prelude::*; diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_configure_system_set_config.md b/docs/proc_attributes/auto_configure_system_set_config.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_configure_system_set_config.md rename to docs/proc_attributes/auto_configure_system_set_config.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_event.md b/docs/proc_attributes/auto_event.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_event.md rename to docs/proc_attributes/auto_event.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_init_resource.md b/docs/proc_attributes/auto_init_resource.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_init_resource.md rename to docs/proc_attributes/auto_init_resource.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_init_state.md b/docs/proc_attributes/auto_init_state.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_init_state.md rename to docs/proc_attributes/auto_init_state.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_init_sub_state.md b/docs/proc_attributes/auto_init_sub_state.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_init_sub_state.md rename to docs/proc_attributes/auto_init_sub_state.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_insert_resource.md b/docs/proc_attributes/auto_insert_resource.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_insert_resource.md rename to docs/proc_attributes/auto_insert_resource.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_message.md b/docs/proc_attributes/auto_message.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_message.md rename to docs/proc_attributes/auto_message.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_name.md b/docs/proc_attributes/auto_name.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_name.md rename to docs/proc_attributes/auto_name.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_observer.md b/docs/proc_attributes/auto_observer.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_observer.md rename to docs/proc_attributes/auto_observer.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_plugin.md b/docs/proc_attributes/auto_plugin.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_plugin.md rename to docs/proc_attributes/auto_plugin.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_register_state_type.md b/docs/proc_attributes/auto_register_state_type.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_register_state_type.md rename to docs/proc_attributes/auto_register_state_type.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_register_type.md b/docs/proc_attributes/auto_register_type.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_register_type.md rename to docs/proc_attributes/auto_register_type.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_resource.md b/docs/proc_attributes/auto_resource.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_resource.md rename to docs/proc_attributes/auto_resource.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_run_on_build.md b/docs/proc_attributes/auto_run_on_build.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_run_on_build.md rename to docs/proc_attributes/auto_run_on_build.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_states.md b/docs/proc_attributes/auto_states.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_states.md rename to docs/proc_attributes/auto_states.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_system.md b/docs/proc_attributes/auto_system.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/auto_system.md rename to docs/proc_attributes/auto_system.md diff --git a/crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/derive_auto_plugin.md b/docs/proc_attributes/derive_auto_plugin.md similarity index 100% rename from crates/bevy_auto_plugin_proc_macros/docs/proc_attributes/derive_auto_plugin.md rename to docs/proc_attributes/derive_auto_plugin.md diff --git a/src/lib.rs b/src/lib.rs index 9f6860a3..2e0c4634 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,76 +4,76 @@ pub mod __private { } pub mod prelude { - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/derive_auto_plugin.md")] pub use bevy_auto_plugin_proc_macros::AutoPlugin; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_add_message.md")] pub use bevy_auto_plugin_proc_macros::auto_add_message; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_add_plugin.md")] #[deprecated(since = "0.6.0", note = "Use `auto_add_message` instead.")] pub use bevy_auto_plugin_proc_macros::auto_add_message as auto_add_event; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_add_plugin.md")] pub use bevy_auto_plugin_proc_macros::auto_add_plugin; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_add_system.md")] pub use bevy_auto_plugin_proc_macros::auto_add_system; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_init_resource.md")] pub use bevy_auto_plugin_proc_macros::auto_init_resource; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_init_state.md")] pub use bevy_auto_plugin_proc_macros::auto_init_state; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_init_sub_state.md")] pub use bevy_auto_plugin_proc_macros::auto_init_sub_state; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_insert_resource.md")] pub use bevy_auto_plugin_proc_macros::auto_insert_resource; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_name.md")] pub use bevy_auto_plugin_proc_macros::auto_name; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_plugin.md")] pub use bevy_auto_plugin_proc_macros::auto_plugin; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_register_state_type.md")] pub use bevy_auto_plugin_proc_macros::auto_register_state_type; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_register_type.md")] pub use bevy_auto_plugin_proc_macros::auto_register_type; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_add_observer.md")] pub use bevy_auto_plugin_proc_macros::auto_add_observer; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_component.md")] pub use bevy_auto_plugin_proc_macros::auto_component; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_resource.md")] pub use bevy_auto_plugin_proc_macros::auto_resource; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_event.md")] pub use bevy_auto_plugin_proc_macros::auto_event; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_message.md")] pub use bevy_auto_plugin_proc_macros::auto_message; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_states.md")] pub use bevy_auto_plugin_proc_macros::auto_states; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_system.md")] pub use bevy_auto_plugin_proc_macros::auto_system; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_observer.md")] pub use bevy_auto_plugin_proc_macros::auto_observer; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_run_on_build.md")] pub use bevy_auto_plugin_proc_macros::auto_run_on_build; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_bind_plugin.md")] pub use bevy_auto_plugin_proc_macros::auto_bind_plugin; - #[doc(inline)] + #[doc = include_str!("../docs/proc_attributes/auto_configure_system_set.md")] pub use bevy_auto_plugin_proc_macros::auto_configure_system_set; } From 7703d9290c00fc0f05ca7940b719d8252377c530 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:14:19 -0400 Subject: [PATCH 118/162] refactor: remove unused `#[allow(dead_code)]` attribute --- crates/bevy_auto_plugin_proc_macros/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_auto_plugin_proc_macros/src/lib.rs b/crates/bevy_auto_plugin_proc_macros/src/lib.rs index a4e51e02..98211feb 100644 --- a/crates/bevy_auto_plugin_proc_macros/src/lib.rs +++ b/crates/bevy_auto_plugin_proc_macros/src/lib.rs @@ -2,7 +2,6 @@ use bevy_auto_plugin_shared::__private::expand; use proc_macro::TokenStream as CompilerStream; use proc_macro2::TokenStream as MacroStream; -#[allow(dead_code)] /// thin adapter converting between the compiler-level and proc_macro2 streams fn handle_attribute MacroStream>( handler: F, From c6a4a71168832874d51728d0ac62fb0dbc4175e0 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:22:55 -0400 Subject: [PATCH 119/162] chore(docs): cleanup inline docs for proc macros --- .../bevy_auto_plugin_proc_macros/src/lib.rs | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/crates/bevy_auto_plugin_proc_macros/src/lib.rs b/crates/bevy_auto_plugin_proc_macros/src/lib.rs index 98211feb..ca1ae1dc 100644 --- a/crates/bevy_auto_plugin_proc_macros/src/lib.rs +++ b/crates/bevy_auto_plugin_proc_macros/src/lib.rs @@ -2,7 +2,7 @@ use bevy_auto_plugin_shared::__private::expand; use proc_macro::TokenStream as CompilerStream; use proc_macro2::TokenStream as MacroStream; -/// thin adapter converting between the compiler-level and proc_macro2 streams +/// Thin adapter converting between the compiler-level and proc_macro2 streams fn handle_attribute MacroStream>( handler: F, attr: CompilerStream, @@ -11,56 +11,56 @@ fn handle_attribute MacroStream>( handler(attr.into(), input.into()).into() } -/// Derives `AutoPlugin` which generates the initialization function that automatically registering types, events, and resources in the `App`. +/// Derives `AutoPlugin`, which generates the initialization function that automatically registers types, events, resources, system, ..., etc. in the `App`. #[proc_macro_derive(AutoPlugin, attributes(auto_plugin))] pub fn derive_auto_plugin(input: CompilerStream) -> CompilerStream { expand::derive::auto_plugin::expand_derive_auto_plugin(input.into()).into() } -/// Attaches to a fn and injects a call to the initialization function that automatically registering types, events, and resources in the `App`. +/// Attaches to an `fn` and injects a call to the `AutoPlugin` initialization function that automatically registers types, events, resources, system, ..., etc. in the `App`. #[allow(unused_variables, unused_mut, unreachable_code)] #[proc_macro_attribute] pub fn auto_plugin(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_plugin::expand_auto_plugin, attr, input) } -/// Automatically registers a type with the Bevy `App`. +/// Automatically registers item deriving `Reflect` in `TypeRegistry` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_register_type(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_register_type, attr, input) } -/// Automatically adds a message type to the Bevy `App`. +/// Automatically adds a `Message` to the Bevy `App`. #[proc_macro_attribute] pub fn auto_add_message(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_add_message, attr, input) } -/// Automatically configures a `SystemSet`. +/// Automatically configures a `SystemSet` in the Bevy `App`. #[proc_macro_attribute] pub fn auto_configure_system_set(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_configure_system_set, attr, input) } -/// Automatically inserts a resource in the Bevy `App`. +/// Automatically initializes a `Resource` in the Bevy `App`. #[proc_macro_attribute] pub fn auto_init_resource(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_init_resource, attr, input) } -/// Automatically inserts a resource in the Bevy `App`. +/// Automatically inserts a `Resource` in the Bevy `App`. #[proc_macro_attribute] pub fn auto_insert_resource(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_insert_resource, attr, input) } -/// Automatically initializes a State in the Bevy `App`. +/// Automatically initializes a `State` in the Bevy `App`. #[proc_macro_attribute] pub fn auto_init_state(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_init_state, attr, input) } -/// Automatically initializes a SubState in the Bevy `App`. +/// Automatically initializes a `SubState` in the Bevy `App`. #[proc_macro_attribute] pub fn auto_init_sub_state(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_init_sub_state, attr, input) @@ -72,73 +72,73 @@ pub fn auto_name(attr: CompilerStream, input: CompilerStream) -> CompilerStream handle_attribute(expand::attr::auto_name, attr, input) } -/// Automatically registers item as States for bevy app. (See below for additional options) +/// Automatically registers item representing `States` in `TypeRegistry` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_register_state_type(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_register_state_type, attr, input) } -/// Automatically adds the fn as a system for bevy app. (See below for additional options) +/// Automatically adds the `fn` as a `System` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_add_system(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_add_system, attr, input) } -/// Automatically adds the fn as a proc_attributes observer to bevy app. (See below for additional options) +/// Automatically adds the `fn` as a `Observer` to the Bevy `App`. #[proc_macro_attribute] pub fn auto_add_observer(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_add_observer, attr, input) } -/// Automatically adds the plugin as a sub-plugin to bevy app. (See below for additional options) +/// Automatically adds the `Plugin` as a sub-plugin to the Bevy `App`. #[proc_macro_attribute] pub fn auto_add_plugin(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_add_plugin, attr, input) } -/// Automatically registers item as Component for bevy app. (See below for additional options) +/// Automatically registers item as `Component` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_component(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_component, attr, input) } -/// Automatically registers item as Resource for bevy app. (See below for additional options) +/// Automatically registers item as `Resource` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_resource(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_resource, attr, input) } -/// Automatically registers item as Event for bevy app. (See below for additional options) +/// Automatically registers item as `Event` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_event(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_event, attr, input) } -/// Automatically registers item as Message for bevy app. (See below for additional options) +/// Automatically registers item as `Message` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_message(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_message, attr, input) } -/// Automatically registers item as States for bevy app. (See below for additional options) +/// Automatically registers item as `States` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_states(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_states, attr, input) } -/// Automatically adds the fn as a system for bevy app. (See below for additional options) +/// Automatically adds the `fn` as a `System` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_system(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_system, attr, input) } -/// Automatically adds proc_attributes observer to bevy app. (See below for additional options) +/// Automatically adds `Observer` to the Bevy `App`. #[proc_macro_attribute] pub fn auto_observer(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_observer, attr, input) } -/// Automatically binds `plugin = _` to every auto_* attribute below it +/// Automatically runs the `fn` on build. #[proc_macro_attribute] pub fn auto_run_on_build(attr: CompilerStream, input: CompilerStream) -> CompilerStream { handle_attribute(expand::attr::auto_run_on_build, attr, input) From 80e190d360457028e56faf31ff2f9659e6ecdb15 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:23:14 -0400 Subject: [PATCH 120/162] chore(cargo): clean up dependencies in `bevy_auto_plugin_proc_macros` --- crates/bevy_auto_plugin_proc_macros/Cargo.toml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/crates/bevy_auto_plugin_proc_macros/Cargo.toml b/crates/bevy_auto_plugin_proc_macros/Cargo.toml index dcf2559b..b1d2b869 100644 --- a/crates/bevy_auto_plugin_proc_macros/Cargo.toml +++ b/crates/bevy_auto_plugin_proc_macros/Cargo.toml @@ -18,13 +18,4 @@ log_plugin_build = ["bevy_auto_plugin_shared/log_plugin_build"] [dependencies] bevy_auto_plugin_shared = { workspace = true } -syn = { workspace = true } -proc-macro2 = { workspace = true } -quote = { workspace = true } -darling = { workspace = true } - -[dev-dependencies] -# needed for doc-tests -bevy = { workspace = true } -bevy_app = { workspace = true } -bevy_auto_plugin = { path = "../../.", default-features = false } \ No newline at end of file +proc-macro2 = { workspace = true } \ No newline at end of file From b3d60a227b201b4641183efddc306574d7092385 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:33:35 -0400 Subject: [PATCH 121/162] chore(docs): add example usage and guidelines for `AutoPlugin` in crate-level documentation --- src/lib.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 2e0c4634..27ed7224 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,50 @@ +//! # Bevy Auto Plugin +//! [GitHub repository](https://github.com/strikeforcezero/bevy_auto_plugin) +//! +//! ## Getting Started: +//! +//! ### Plugin +//! +//! There are three distinct ways to make a bindable plugin: +//! +//! ```rust +//! use bevy::prelude::*; +//! use bevy_auto_plugin::prelude::*; +//! +//! #[derive(AutoPlugin)] +//! #[auto_plugin(impl_plugin_trait)] +//! struct MyPlugin; +//! ``` +//! +//! ```rust +//! use bevy::prelude::*; +//! use bevy_auto_plugin::prelude::*; +//! +//! #[derive(AutoPlugin)] +//! struct MyPlugin; +//! +//! impl Plugin for MyPlugin { +//! #[auto_plugin] +//! fn build(&self, app: &mut App) { +//! // +//! } +//! } +//! ``` +//! +//! ```rust +//! use bevy::prelude::*; +//! use bevy_auto_plugin::prelude::*; +//! +//! #[derive(AutoPlugin)] +//! struct MyPlugin; +//! +//! #[auto_plugin(plugin = MyPlugin)] +//! fn plugin(app: &mut App) { +//! // +//! } +//! ``` + +/// Private Re-exports #[doc(hidden)] pub mod __private { pub use bevy_auto_plugin_shared as shared; From 451cc32b074c239e7e73954452b8644478eb8061 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:37:04 -0400 Subject: [PATCH 122/162] chore(docs): split docs into derives, proc_attributes::{actions, rewrites} --- .../AutoPlugin.md} | 0 .../{ => actions}/auto_add_message.md | 0 .../{ => actions}/auto_add_observer.md | 0 .../{ => actions}/auto_add_plugin.md | 0 .../{ => actions}/auto_add_system.md | 0 .../{ => actions}/auto_bind_plugin.md | 0 .../auto_configure_system_set.md | 0 .../auto_configure_system_set_config.md | 0 .../{ => actions}/auto_init_resource.md | 0 .../{ => actions}/auto_init_state.md | 0 .../{ => actions}/auto_init_sub_state.md | 0 .../{ => actions}/auto_insert_resource.md | 0 .../{ => actions}/auto_name.md | 0 .../{ => actions}/auto_register_state_type.md | 0 .../{ => actions}/auto_register_type.md | 0 .../{ => actions}/auto_run_on_build.md | 0 .../{ => rewrites}/auto_component.md | 0 .../{ => rewrites}/auto_event.md | 0 .../{ => rewrites}/auto_message.md | 0 .../{ => rewrites}/auto_observer.md | 0 .../{ => rewrites}/auto_resource.md | 0 .../{ => rewrites}/auto_states.md | 0 .../{ => rewrites}/auto_system.md | 0 src/lib.rs | 46 +++++++++---------- 24 files changed, 23 insertions(+), 23 deletions(-) rename docs/{proc_attributes/derive_auto_plugin.md => derives/AutoPlugin.md} (100%) rename docs/proc_attributes/{ => actions}/auto_add_message.md (100%) rename docs/proc_attributes/{ => actions}/auto_add_observer.md (100%) rename docs/proc_attributes/{ => actions}/auto_add_plugin.md (100%) rename docs/proc_attributes/{ => actions}/auto_add_system.md (100%) rename docs/proc_attributes/{ => actions}/auto_bind_plugin.md (100%) rename docs/proc_attributes/{ => actions}/auto_configure_system_set.md (100%) rename docs/proc_attributes/{ => actions}/auto_configure_system_set_config.md (100%) rename docs/proc_attributes/{ => actions}/auto_init_resource.md (100%) rename docs/proc_attributes/{ => actions}/auto_init_state.md (100%) rename docs/proc_attributes/{ => actions}/auto_init_sub_state.md (100%) rename docs/proc_attributes/{ => actions}/auto_insert_resource.md (100%) rename docs/proc_attributes/{ => actions}/auto_name.md (100%) rename docs/proc_attributes/{ => actions}/auto_register_state_type.md (100%) rename docs/proc_attributes/{ => actions}/auto_register_type.md (100%) rename docs/proc_attributes/{ => actions}/auto_run_on_build.md (100%) rename docs/proc_attributes/{ => rewrites}/auto_component.md (100%) rename docs/proc_attributes/{ => rewrites}/auto_event.md (100%) rename docs/proc_attributes/{ => rewrites}/auto_message.md (100%) rename docs/proc_attributes/{ => rewrites}/auto_observer.md (100%) rename docs/proc_attributes/{ => rewrites}/auto_resource.md (100%) rename docs/proc_attributes/{ => rewrites}/auto_states.md (100%) rename docs/proc_attributes/{ => rewrites}/auto_system.md (100%) diff --git a/docs/proc_attributes/derive_auto_plugin.md b/docs/derives/AutoPlugin.md similarity index 100% rename from docs/proc_attributes/derive_auto_plugin.md rename to docs/derives/AutoPlugin.md diff --git a/docs/proc_attributes/auto_add_message.md b/docs/proc_attributes/actions/auto_add_message.md similarity index 100% rename from docs/proc_attributes/auto_add_message.md rename to docs/proc_attributes/actions/auto_add_message.md diff --git a/docs/proc_attributes/auto_add_observer.md b/docs/proc_attributes/actions/auto_add_observer.md similarity index 100% rename from docs/proc_attributes/auto_add_observer.md rename to docs/proc_attributes/actions/auto_add_observer.md diff --git a/docs/proc_attributes/auto_add_plugin.md b/docs/proc_attributes/actions/auto_add_plugin.md similarity index 100% rename from docs/proc_attributes/auto_add_plugin.md rename to docs/proc_attributes/actions/auto_add_plugin.md diff --git a/docs/proc_attributes/auto_add_system.md b/docs/proc_attributes/actions/auto_add_system.md similarity index 100% rename from docs/proc_attributes/auto_add_system.md rename to docs/proc_attributes/actions/auto_add_system.md diff --git a/docs/proc_attributes/auto_bind_plugin.md b/docs/proc_attributes/actions/auto_bind_plugin.md similarity index 100% rename from docs/proc_attributes/auto_bind_plugin.md rename to docs/proc_attributes/actions/auto_bind_plugin.md diff --git a/docs/proc_attributes/auto_configure_system_set.md b/docs/proc_attributes/actions/auto_configure_system_set.md similarity index 100% rename from docs/proc_attributes/auto_configure_system_set.md rename to docs/proc_attributes/actions/auto_configure_system_set.md diff --git a/docs/proc_attributes/auto_configure_system_set_config.md b/docs/proc_attributes/actions/auto_configure_system_set_config.md similarity index 100% rename from docs/proc_attributes/auto_configure_system_set_config.md rename to docs/proc_attributes/actions/auto_configure_system_set_config.md diff --git a/docs/proc_attributes/auto_init_resource.md b/docs/proc_attributes/actions/auto_init_resource.md similarity index 100% rename from docs/proc_attributes/auto_init_resource.md rename to docs/proc_attributes/actions/auto_init_resource.md diff --git a/docs/proc_attributes/auto_init_state.md b/docs/proc_attributes/actions/auto_init_state.md similarity index 100% rename from docs/proc_attributes/auto_init_state.md rename to docs/proc_attributes/actions/auto_init_state.md diff --git a/docs/proc_attributes/auto_init_sub_state.md b/docs/proc_attributes/actions/auto_init_sub_state.md similarity index 100% rename from docs/proc_attributes/auto_init_sub_state.md rename to docs/proc_attributes/actions/auto_init_sub_state.md diff --git a/docs/proc_attributes/auto_insert_resource.md b/docs/proc_attributes/actions/auto_insert_resource.md similarity index 100% rename from docs/proc_attributes/auto_insert_resource.md rename to docs/proc_attributes/actions/auto_insert_resource.md diff --git a/docs/proc_attributes/auto_name.md b/docs/proc_attributes/actions/auto_name.md similarity index 100% rename from docs/proc_attributes/auto_name.md rename to docs/proc_attributes/actions/auto_name.md diff --git a/docs/proc_attributes/auto_register_state_type.md b/docs/proc_attributes/actions/auto_register_state_type.md similarity index 100% rename from docs/proc_attributes/auto_register_state_type.md rename to docs/proc_attributes/actions/auto_register_state_type.md diff --git a/docs/proc_attributes/auto_register_type.md b/docs/proc_attributes/actions/auto_register_type.md similarity index 100% rename from docs/proc_attributes/auto_register_type.md rename to docs/proc_attributes/actions/auto_register_type.md diff --git a/docs/proc_attributes/auto_run_on_build.md b/docs/proc_attributes/actions/auto_run_on_build.md similarity index 100% rename from docs/proc_attributes/auto_run_on_build.md rename to docs/proc_attributes/actions/auto_run_on_build.md diff --git a/docs/proc_attributes/auto_component.md b/docs/proc_attributes/rewrites/auto_component.md similarity index 100% rename from docs/proc_attributes/auto_component.md rename to docs/proc_attributes/rewrites/auto_component.md diff --git a/docs/proc_attributes/auto_event.md b/docs/proc_attributes/rewrites/auto_event.md similarity index 100% rename from docs/proc_attributes/auto_event.md rename to docs/proc_attributes/rewrites/auto_event.md diff --git a/docs/proc_attributes/auto_message.md b/docs/proc_attributes/rewrites/auto_message.md similarity index 100% rename from docs/proc_attributes/auto_message.md rename to docs/proc_attributes/rewrites/auto_message.md diff --git a/docs/proc_attributes/auto_observer.md b/docs/proc_attributes/rewrites/auto_observer.md similarity index 100% rename from docs/proc_attributes/auto_observer.md rename to docs/proc_attributes/rewrites/auto_observer.md diff --git a/docs/proc_attributes/auto_resource.md b/docs/proc_attributes/rewrites/auto_resource.md similarity index 100% rename from docs/proc_attributes/auto_resource.md rename to docs/proc_attributes/rewrites/auto_resource.md diff --git a/docs/proc_attributes/auto_states.md b/docs/proc_attributes/rewrites/auto_states.md similarity index 100% rename from docs/proc_attributes/auto_states.md rename to docs/proc_attributes/rewrites/auto_states.md diff --git a/docs/proc_attributes/auto_system.md b/docs/proc_attributes/rewrites/auto_system.md similarity index 100% rename from docs/proc_attributes/auto_system.md rename to docs/proc_attributes/rewrites/auto_system.md diff --git a/src/lib.rs b/src/lib.rs index 27ed7224..87caea45 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,76 +51,76 @@ pub mod __private { } pub mod prelude { - #[doc = include_str!("../docs/proc_attributes/derive_auto_plugin.md")] + #[doc = include_str!("../docs/derives/AutoPlugin.md")] pub use bevy_auto_plugin_proc_macros::AutoPlugin; - #[doc = include_str!("../docs/proc_attributes/auto_add_message.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_add_message.md")] pub use bevy_auto_plugin_proc_macros::auto_add_message; - #[doc = include_str!("../docs/proc_attributes/auto_add_plugin.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_add_plugin.md")] #[deprecated(since = "0.6.0", note = "Use `auto_add_message` instead.")] pub use bevy_auto_plugin_proc_macros::auto_add_message as auto_add_event; - #[doc = include_str!("../docs/proc_attributes/auto_add_plugin.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_add_plugin.md")] pub use bevy_auto_plugin_proc_macros::auto_add_plugin; - #[doc = include_str!("../docs/proc_attributes/auto_add_system.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_add_system.md")] pub use bevy_auto_plugin_proc_macros::auto_add_system; - #[doc = include_str!("../docs/proc_attributes/auto_init_resource.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_init_resource.md")] pub use bevy_auto_plugin_proc_macros::auto_init_resource; - #[doc = include_str!("../docs/proc_attributes/auto_init_state.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_init_state.md")] pub use bevy_auto_plugin_proc_macros::auto_init_state; - #[doc = include_str!("../docs/proc_attributes/auto_init_sub_state.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_init_sub_state.md")] pub use bevy_auto_plugin_proc_macros::auto_init_sub_state; - #[doc = include_str!("../docs/proc_attributes/auto_insert_resource.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_insert_resource.md")] pub use bevy_auto_plugin_proc_macros::auto_insert_resource; - #[doc = include_str!("../docs/proc_attributes/auto_name.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_name.md")] pub use bevy_auto_plugin_proc_macros::auto_name; #[doc = include_str!("../docs/proc_attributes/auto_plugin.md")] pub use bevy_auto_plugin_proc_macros::auto_plugin; - #[doc = include_str!("../docs/proc_attributes/auto_register_state_type.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_register_state_type.md")] pub use bevy_auto_plugin_proc_macros::auto_register_state_type; - #[doc = include_str!("../docs/proc_attributes/auto_register_type.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_register_type.md")] pub use bevy_auto_plugin_proc_macros::auto_register_type; - #[doc = include_str!("../docs/proc_attributes/auto_add_observer.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_add_observer.md")] pub use bevy_auto_plugin_proc_macros::auto_add_observer; - #[doc = include_str!("../docs/proc_attributes/auto_component.md")] + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_component.md")] pub use bevy_auto_plugin_proc_macros::auto_component; - #[doc = include_str!("../docs/proc_attributes/auto_resource.md")] + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_resource.md")] pub use bevy_auto_plugin_proc_macros::auto_resource; - #[doc = include_str!("../docs/proc_attributes/auto_event.md")] + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_event.md")] pub use bevy_auto_plugin_proc_macros::auto_event; - #[doc = include_str!("../docs/proc_attributes/auto_message.md")] + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_message.md")] pub use bevy_auto_plugin_proc_macros::auto_message; - #[doc = include_str!("../docs/proc_attributes/auto_states.md")] + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_states.md")] pub use bevy_auto_plugin_proc_macros::auto_states; - #[doc = include_str!("../docs/proc_attributes/auto_system.md")] + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_system.md")] pub use bevy_auto_plugin_proc_macros::auto_system; - #[doc = include_str!("../docs/proc_attributes/auto_observer.md")] + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_observer.md")] pub use bevy_auto_plugin_proc_macros::auto_observer; - #[doc = include_str!("../docs/proc_attributes/auto_run_on_build.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_run_on_build.md")] pub use bevy_auto_plugin_proc_macros::auto_run_on_build; - #[doc = include_str!("../docs/proc_attributes/auto_bind_plugin.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_bind_plugin.md")] pub use bevy_auto_plugin_proc_macros::auto_bind_plugin; - #[doc = include_str!("../docs/proc_attributes/auto_configure_system_set.md")] + #[doc = include_str!("../docs/proc_attributes/actions/auto_configure_system_set.md")] pub use bevy_auto_plugin_proc_macros::auto_configure_system_set; } From ace109746dcd8a0a5f003f93cbe831a27cbe900c Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:47:28 -0400 Subject: [PATCH 123/162] chore(docs): expand crate-level docs with attribute usage examples --- src/lib.rs | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 87caea45..92631f2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,6 +43,69 @@ //! // //! } //! ``` +//! +//! ### Using Attributes +//! When `Plugin::build` is called on `MyPlugin` (i.e., `app.add_plugins(MyPlugin)`), the code for each attribute will be executed. +//! +//! You can use the `auto_*` attributes in several different ways: +//! +//! ```rust +//! use bevy::prelude::*; +//! use bevy_auto_plugin::prelude::*; +//! +//! #[derive(AutoPlugin)] +//! #[auto_plugin(impl_plugin_trait)] +//! struct MyPlugin; +//! +//! #[auto_component( +//! plugin = MyPlugin, +//! derive(Debug, Default), +//! reflect(Debug, Default), +//! register, +//! auto_name, +//! )] +//! struct FooComponent; +//! ``` +//! +//! which gets rewritten into: +//! ```rust +//! use bevy::prelude::*; +//! use bevy_auto_plugin::prelude::*; +//! +//! #[derive(AutoPlugin)] +//! #[auto_plugin(impl_plugin_trait)] +//! struct MyPlugin; +//! +//! #[derive(Component, Reflect, Debug, Default)] +//! #[reflect(Component, Debug, Default)] +//! #[auto_name(plugin = MyPlugin)] +//! #[auto_register_type(plugin = MyPlugin)] +//! struct FooComponent; +//! ``` +//! +//! or maybe you want a template: +//! ```rust +//! use bevy::prelude::*; +//! use bevy_auto_plugin::prelude::*; +//! use meta_merge::*; +//! +//! #[derive(AutoPlugin)] +//! #[auto_plugin(impl_plugin_trait)] +//! struct MyPlugin; +//! +//! #[export(copy(prepend))] +//! #[derive(Component, Reflect, Debug, Default)] +//! #[reflect(Component, Debug, Default)] +//! #[auto_name(plugin = MyPlugin)] +//! #[auto_register_type(plugin = MyPlugin)] +//! struct DefaultComponentTemplate; +//! +//! #[apply(CopyDefaultComponentTemplate!)] +//! struct FooComponent; +//! +//! #[apply(CopyDefaultComponentTemplate!)] +//! struct BarComponent; +//! ``` /// Private Re-exports #[doc(hidden)] From c810d84be4d9da87194d4879da75ec09757798f1 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:56:52 -0400 Subject: [PATCH 124/162] chore(dev-deps): add meta_merge@^0.1.1 --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index bbcd24d0..dcdb9cce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,6 +79,7 @@ log = { workspace = true } wasm-bindgen-test = { workspace = true } internal_test_util = { workspace = true } internal_test_proc_macro = { workspace = true } +meta_merge = "0.1.1" [build-dependencies] rustc_version = "0.4" From ade6aa8ae69f49888d4677e78d4b88587c945cb2 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 16:57:07 -0400 Subject: [PATCH 125/162] chore(tests): restructure `e2e` tests into `actions`, `auto_plugin`, and `rewrites` modules --- tests/e2e/{ => actions}/auto_add_message.rs | 0 .../{ => actions}/auto_add_message_generic.rs | 0 tests/e2e/{ => actions}/auto_add_observer.rs | 0 tests/e2e/{ => actions}/auto_add_plugin.rs | 0 .../auto_add_plugin_with_default_init.rs | 0 ...d_plugin_with_generics_and_default_init.rs | 0 .../auto_add_plugin_with_generics_and_init.rs | 0 .../auto_add_plugin_with_init.rs | 0 tests/e2e/{ => actions}/auto_add_systems.rs | 0 .../auto_add_systems_complex_with_generics.rs | 0 .../auto_add_systems_with_generics.rs | 0 .../auto_add_systems_with_set.rs | 0 tests/e2e/{ => actions}/auto_bind_plugin.rs | 0 .../auto_configure_system_set.rs | 0 ...to_configure_system_set_schedule_config.rs | 0 ...tem_set_schedule_config_multiple_groups.rs | 0 tests/e2e/{ => actions}/auto_init_resource.rs | 0 .../auto_init_resource_generic.rs | 0 tests/e2e/{ => actions}/auto_init_state.rs | 0 .../e2e/{ => actions}/auto_init_sub_state.rs | 0 .../e2e/{ => actions}/auto_insert_resource.rs | 0 .../auto_insert_resource_with_generics.rs | 0 tests/e2e/{ => actions}/auto_name.rs | 0 .../{ => actions}/auto_name_with_generics.rs | 0 .../auto_plugin_default_param.rs | 0 .../auto_plugin_default_param_method.rs | 0 tests/e2e/{ => actions}/auto_plugin_param.rs | 0 .../auto_plugin_with_generics.rs | 0 .../{ => actions}/auto_register_state_type.rs | 0 tests/e2e/{ => actions}/auto_register_type.rs | 0 .../auto_register_type_generic.rs | 0 tests/e2e/{ => actions}/auto_run_on_build.rs | 0 .../auto_run_on_build_with_generics.rs | 0 .../auto_system_schedule_multiple.rs | 0 .../auto_system_schedule_non_path.rs | 0 .../auto_system_schedule_on_state.rs | 0 tests/e2e/actions/mod.rs | 36 +++++++++++++++ tests/e2e/{ => auto_plugin}/bare_fn.rs | 0 .../bare_fn_default_app_param.rs | 0 tests/e2e/auto_plugin/mod.rs | 5 +++ .../e2e/{ => auto_plugin}/self_impl_plugin.rs | 0 .../self_impl_plugin_default_app_param.rs | 0 .../self_impl_plugin_with_generics.rs | 0 tests/e2e/{auto_plugin.rs => general.rs} | 0 tests/e2e/mod.rs | 45 ++----------------- tests/e2e/{ => rewrites}/auto_component.rs | 0 tests/e2e/rewrites/mod.rs | 1 + 47 files changed, 45 insertions(+), 42 deletions(-) rename tests/e2e/{ => actions}/auto_add_message.rs (100%) rename tests/e2e/{ => actions}/auto_add_message_generic.rs (100%) rename tests/e2e/{ => actions}/auto_add_observer.rs (100%) rename tests/e2e/{ => actions}/auto_add_plugin.rs (100%) rename tests/e2e/{ => actions}/auto_add_plugin_with_default_init.rs (100%) rename tests/e2e/{ => actions}/auto_add_plugin_with_generics_and_default_init.rs (100%) rename tests/e2e/{ => actions}/auto_add_plugin_with_generics_and_init.rs (100%) rename tests/e2e/{ => actions}/auto_add_plugin_with_init.rs (100%) rename tests/e2e/{ => actions}/auto_add_systems.rs (100%) rename tests/e2e/{ => actions}/auto_add_systems_complex_with_generics.rs (100%) rename tests/e2e/{ => actions}/auto_add_systems_with_generics.rs (100%) rename tests/e2e/{ => actions}/auto_add_systems_with_set.rs (100%) rename tests/e2e/{ => actions}/auto_bind_plugin.rs (100%) rename tests/e2e/{ => actions}/auto_configure_system_set.rs (100%) rename tests/e2e/{ => actions}/auto_configure_system_set_schedule_config.rs (100%) rename tests/e2e/{ => actions}/auto_configure_system_set_schedule_config_multiple_groups.rs (100%) rename tests/e2e/{ => actions}/auto_init_resource.rs (100%) rename tests/e2e/{ => actions}/auto_init_resource_generic.rs (100%) rename tests/e2e/{ => actions}/auto_init_state.rs (100%) rename tests/e2e/{ => actions}/auto_init_sub_state.rs (100%) rename tests/e2e/{ => actions}/auto_insert_resource.rs (100%) rename tests/e2e/{ => actions}/auto_insert_resource_with_generics.rs (100%) rename tests/e2e/{ => actions}/auto_name.rs (100%) rename tests/e2e/{ => actions}/auto_name_with_generics.rs (100%) rename tests/e2e/{ => actions}/auto_plugin_default_param.rs (100%) rename tests/e2e/{ => actions}/auto_plugin_default_param_method.rs (100%) rename tests/e2e/{ => actions}/auto_plugin_param.rs (100%) rename tests/e2e/{ => actions}/auto_plugin_with_generics.rs (100%) rename tests/e2e/{ => actions}/auto_register_state_type.rs (100%) rename tests/e2e/{ => actions}/auto_register_type.rs (100%) rename tests/e2e/{ => actions}/auto_register_type_generic.rs (100%) rename tests/e2e/{ => actions}/auto_run_on_build.rs (100%) rename tests/e2e/{ => actions}/auto_run_on_build_with_generics.rs (100%) rename tests/e2e/{ => actions}/auto_system_schedule_multiple.rs (100%) rename tests/e2e/{ => actions}/auto_system_schedule_non_path.rs (100%) rename tests/e2e/{ => actions}/auto_system_schedule_on_state.rs (100%) create mode 100644 tests/e2e/actions/mod.rs rename tests/e2e/{ => auto_plugin}/bare_fn.rs (100%) rename tests/e2e/{ => auto_plugin}/bare_fn_default_app_param.rs (100%) create mode 100644 tests/e2e/auto_plugin/mod.rs rename tests/e2e/{ => auto_plugin}/self_impl_plugin.rs (100%) rename tests/e2e/{ => auto_plugin}/self_impl_plugin_default_app_param.rs (100%) rename tests/e2e/{ => auto_plugin}/self_impl_plugin_with_generics.rs (100%) rename tests/e2e/{auto_plugin.rs => general.rs} (100%) rename tests/e2e/{ => rewrites}/auto_component.rs (100%) create mode 100644 tests/e2e/rewrites/mod.rs diff --git a/tests/e2e/auto_add_message.rs b/tests/e2e/actions/auto_add_message.rs similarity index 100% rename from tests/e2e/auto_add_message.rs rename to tests/e2e/actions/auto_add_message.rs diff --git a/tests/e2e/auto_add_message_generic.rs b/tests/e2e/actions/auto_add_message_generic.rs similarity index 100% rename from tests/e2e/auto_add_message_generic.rs rename to tests/e2e/actions/auto_add_message_generic.rs diff --git a/tests/e2e/auto_add_observer.rs b/tests/e2e/actions/auto_add_observer.rs similarity index 100% rename from tests/e2e/auto_add_observer.rs rename to tests/e2e/actions/auto_add_observer.rs diff --git a/tests/e2e/auto_add_plugin.rs b/tests/e2e/actions/auto_add_plugin.rs similarity index 100% rename from tests/e2e/auto_add_plugin.rs rename to tests/e2e/actions/auto_add_plugin.rs diff --git a/tests/e2e/auto_add_plugin_with_default_init.rs b/tests/e2e/actions/auto_add_plugin_with_default_init.rs similarity index 100% rename from tests/e2e/auto_add_plugin_with_default_init.rs rename to tests/e2e/actions/auto_add_plugin_with_default_init.rs diff --git a/tests/e2e/auto_add_plugin_with_generics_and_default_init.rs b/tests/e2e/actions/auto_add_plugin_with_generics_and_default_init.rs similarity index 100% rename from tests/e2e/auto_add_plugin_with_generics_and_default_init.rs rename to tests/e2e/actions/auto_add_plugin_with_generics_and_default_init.rs diff --git a/tests/e2e/auto_add_plugin_with_generics_and_init.rs b/tests/e2e/actions/auto_add_plugin_with_generics_and_init.rs similarity index 100% rename from tests/e2e/auto_add_plugin_with_generics_and_init.rs rename to tests/e2e/actions/auto_add_plugin_with_generics_and_init.rs diff --git a/tests/e2e/auto_add_plugin_with_init.rs b/tests/e2e/actions/auto_add_plugin_with_init.rs similarity index 100% rename from tests/e2e/auto_add_plugin_with_init.rs rename to tests/e2e/actions/auto_add_plugin_with_init.rs diff --git a/tests/e2e/auto_add_systems.rs b/tests/e2e/actions/auto_add_systems.rs similarity index 100% rename from tests/e2e/auto_add_systems.rs rename to tests/e2e/actions/auto_add_systems.rs diff --git a/tests/e2e/auto_add_systems_complex_with_generics.rs b/tests/e2e/actions/auto_add_systems_complex_with_generics.rs similarity index 100% rename from tests/e2e/auto_add_systems_complex_with_generics.rs rename to tests/e2e/actions/auto_add_systems_complex_with_generics.rs diff --git a/tests/e2e/auto_add_systems_with_generics.rs b/tests/e2e/actions/auto_add_systems_with_generics.rs similarity index 100% rename from tests/e2e/auto_add_systems_with_generics.rs rename to tests/e2e/actions/auto_add_systems_with_generics.rs diff --git a/tests/e2e/auto_add_systems_with_set.rs b/tests/e2e/actions/auto_add_systems_with_set.rs similarity index 100% rename from tests/e2e/auto_add_systems_with_set.rs rename to tests/e2e/actions/auto_add_systems_with_set.rs diff --git a/tests/e2e/auto_bind_plugin.rs b/tests/e2e/actions/auto_bind_plugin.rs similarity index 100% rename from tests/e2e/auto_bind_plugin.rs rename to tests/e2e/actions/auto_bind_plugin.rs diff --git a/tests/e2e/auto_configure_system_set.rs b/tests/e2e/actions/auto_configure_system_set.rs similarity index 100% rename from tests/e2e/auto_configure_system_set.rs rename to tests/e2e/actions/auto_configure_system_set.rs diff --git a/tests/e2e/auto_configure_system_set_schedule_config.rs b/tests/e2e/actions/auto_configure_system_set_schedule_config.rs similarity index 100% rename from tests/e2e/auto_configure_system_set_schedule_config.rs rename to tests/e2e/actions/auto_configure_system_set_schedule_config.rs diff --git a/tests/e2e/auto_configure_system_set_schedule_config_multiple_groups.rs b/tests/e2e/actions/auto_configure_system_set_schedule_config_multiple_groups.rs similarity index 100% rename from tests/e2e/auto_configure_system_set_schedule_config_multiple_groups.rs rename to tests/e2e/actions/auto_configure_system_set_schedule_config_multiple_groups.rs diff --git a/tests/e2e/auto_init_resource.rs b/tests/e2e/actions/auto_init_resource.rs similarity index 100% rename from tests/e2e/auto_init_resource.rs rename to tests/e2e/actions/auto_init_resource.rs diff --git a/tests/e2e/auto_init_resource_generic.rs b/tests/e2e/actions/auto_init_resource_generic.rs similarity index 100% rename from tests/e2e/auto_init_resource_generic.rs rename to tests/e2e/actions/auto_init_resource_generic.rs diff --git a/tests/e2e/auto_init_state.rs b/tests/e2e/actions/auto_init_state.rs similarity index 100% rename from tests/e2e/auto_init_state.rs rename to tests/e2e/actions/auto_init_state.rs diff --git a/tests/e2e/auto_init_sub_state.rs b/tests/e2e/actions/auto_init_sub_state.rs similarity index 100% rename from tests/e2e/auto_init_sub_state.rs rename to tests/e2e/actions/auto_init_sub_state.rs diff --git a/tests/e2e/auto_insert_resource.rs b/tests/e2e/actions/auto_insert_resource.rs similarity index 100% rename from tests/e2e/auto_insert_resource.rs rename to tests/e2e/actions/auto_insert_resource.rs diff --git a/tests/e2e/auto_insert_resource_with_generics.rs b/tests/e2e/actions/auto_insert_resource_with_generics.rs similarity index 100% rename from tests/e2e/auto_insert_resource_with_generics.rs rename to tests/e2e/actions/auto_insert_resource_with_generics.rs diff --git a/tests/e2e/auto_name.rs b/tests/e2e/actions/auto_name.rs similarity index 100% rename from tests/e2e/auto_name.rs rename to tests/e2e/actions/auto_name.rs diff --git a/tests/e2e/auto_name_with_generics.rs b/tests/e2e/actions/auto_name_with_generics.rs similarity index 100% rename from tests/e2e/auto_name_with_generics.rs rename to tests/e2e/actions/auto_name_with_generics.rs diff --git a/tests/e2e/auto_plugin_default_param.rs b/tests/e2e/actions/auto_plugin_default_param.rs similarity index 100% rename from tests/e2e/auto_plugin_default_param.rs rename to tests/e2e/actions/auto_plugin_default_param.rs diff --git a/tests/e2e/auto_plugin_default_param_method.rs b/tests/e2e/actions/auto_plugin_default_param_method.rs similarity index 100% rename from tests/e2e/auto_plugin_default_param_method.rs rename to tests/e2e/actions/auto_plugin_default_param_method.rs diff --git a/tests/e2e/auto_plugin_param.rs b/tests/e2e/actions/auto_plugin_param.rs similarity index 100% rename from tests/e2e/auto_plugin_param.rs rename to tests/e2e/actions/auto_plugin_param.rs diff --git a/tests/e2e/auto_plugin_with_generics.rs b/tests/e2e/actions/auto_plugin_with_generics.rs similarity index 100% rename from tests/e2e/auto_plugin_with_generics.rs rename to tests/e2e/actions/auto_plugin_with_generics.rs diff --git a/tests/e2e/auto_register_state_type.rs b/tests/e2e/actions/auto_register_state_type.rs similarity index 100% rename from tests/e2e/auto_register_state_type.rs rename to tests/e2e/actions/auto_register_state_type.rs diff --git a/tests/e2e/auto_register_type.rs b/tests/e2e/actions/auto_register_type.rs similarity index 100% rename from tests/e2e/auto_register_type.rs rename to tests/e2e/actions/auto_register_type.rs diff --git a/tests/e2e/auto_register_type_generic.rs b/tests/e2e/actions/auto_register_type_generic.rs similarity index 100% rename from tests/e2e/auto_register_type_generic.rs rename to tests/e2e/actions/auto_register_type_generic.rs diff --git a/tests/e2e/auto_run_on_build.rs b/tests/e2e/actions/auto_run_on_build.rs similarity index 100% rename from tests/e2e/auto_run_on_build.rs rename to tests/e2e/actions/auto_run_on_build.rs diff --git a/tests/e2e/auto_run_on_build_with_generics.rs b/tests/e2e/actions/auto_run_on_build_with_generics.rs similarity index 100% rename from tests/e2e/auto_run_on_build_with_generics.rs rename to tests/e2e/actions/auto_run_on_build_with_generics.rs diff --git a/tests/e2e/auto_system_schedule_multiple.rs b/tests/e2e/actions/auto_system_schedule_multiple.rs similarity index 100% rename from tests/e2e/auto_system_schedule_multiple.rs rename to tests/e2e/actions/auto_system_schedule_multiple.rs diff --git a/tests/e2e/auto_system_schedule_non_path.rs b/tests/e2e/actions/auto_system_schedule_non_path.rs similarity index 100% rename from tests/e2e/auto_system_schedule_non_path.rs rename to tests/e2e/actions/auto_system_schedule_non_path.rs diff --git a/tests/e2e/auto_system_schedule_on_state.rs b/tests/e2e/actions/auto_system_schedule_on_state.rs similarity index 100% rename from tests/e2e/auto_system_schedule_on_state.rs rename to tests/e2e/actions/auto_system_schedule_on_state.rs diff --git a/tests/e2e/actions/mod.rs b/tests/e2e/actions/mod.rs new file mode 100644 index 00000000..652d29c0 --- /dev/null +++ b/tests/e2e/actions/mod.rs @@ -0,0 +1,36 @@ +mod auto_add_message; +mod auto_add_message_generic; +mod auto_add_observer; +mod auto_add_plugin; +mod auto_add_plugin_with_default_init; +mod auto_add_plugin_with_generics_and_default_init; +mod auto_add_plugin_with_generics_and_init; +mod auto_add_plugin_with_init; +mod auto_add_systems; +mod auto_add_systems_complex_with_generics; +mod auto_add_systems_with_generics; +mod auto_add_systems_with_set; +mod auto_bind_plugin; +mod auto_configure_system_set; +mod auto_configure_system_set_schedule_config; +mod auto_configure_system_set_schedule_config_multiple_groups; +mod auto_init_resource; +mod auto_init_resource_generic; +mod auto_init_state; +mod auto_init_sub_state; +mod auto_insert_resource; +mod auto_insert_resource_with_generics; +mod auto_name; +mod auto_name_with_generics; +mod auto_plugin_default_param; +mod auto_plugin_default_param_method; +mod auto_plugin_param; +mod auto_plugin_with_generics; +mod auto_register_state_type; +mod auto_register_type; +mod auto_register_type_generic; +mod auto_run_on_build; +mod auto_run_on_build_with_generics; +mod auto_system_schedule_multiple; +mod auto_system_schedule_non_path; +mod auto_system_schedule_on_state; diff --git a/tests/e2e/bare_fn.rs b/tests/e2e/auto_plugin/bare_fn.rs similarity index 100% rename from tests/e2e/bare_fn.rs rename to tests/e2e/auto_plugin/bare_fn.rs diff --git a/tests/e2e/bare_fn_default_app_param.rs b/tests/e2e/auto_plugin/bare_fn_default_app_param.rs similarity index 100% rename from tests/e2e/bare_fn_default_app_param.rs rename to tests/e2e/auto_plugin/bare_fn_default_app_param.rs diff --git a/tests/e2e/auto_plugin/mod.rs b/tests/e2e/auto_plugin/mod.rs new file mode 100644 index 00000000..2dea6eb4 --- /dev/null +++ b/tests/e2e/auto_plugin/mod.rs @@ -0,0 +1,5 @@ +mod bare_fn; +mod bare_fn_default_app_param; +mod self_impl_plugin; +mod self_impl_plugin_default_app_param; +mod self_impl_plugin_with_generics; diff --git a/tests/e2e/self_impl_plugin.rs b/tests/e2e/auto_plugin/self_impl_plugin.rs similarity index 100% rename from tests/e2e/self_impl_plugin.rs rename to tests/e2e/auto_plugin/self_impl_plugin.rs diff --git a/tests/e2e/self_impl_plugin_default_app_param.rs b/tests/e2e/auto_plugin/self_impl_plugin_default_app_param.rs similarity index 100% rename from tests/e2e/self_impl_plugin_default_app_param.rs rename to tests/e2e/auto_plugin/self_impl_plugin_default_app_param.rs diff --git a/tests/e2e/self_impl_plugin_with_generics.rs b/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs similarity index 100% rename from tests/e2e/self_impl_plugin_with_generics.rs rename to tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs diff --git a/tests/e2e/auto_plugin.rs b/tests/e2e/general.rs similarity index 100% rename from tests/e2e/auto_plugin.rs rename to tests/e2e/general.rs diff --git a/tests/e2e/mod.rs b/tests/e2e/mod.rs index 47c862e7..6f7e1f30 100644 --- a/tests/e2e/mod.rs +++ b/tests/e2e/mod.rs @@ -1,45 +1,6 @@ -mod auto_add_message; -mod auto_add_message_generic; -mod auto_add_observer; -mod auto_add_plugin; -mod auto_add_plugin_with_default_init; -mod auto_add_plugin_with_generics_and_default_init; -mod auto_add_plugin_with_generics_and_init; -mod auto_add_plugin_with_init; -mod auto_add_systems; -mod auto_add_systems_complex_with_generics; -mod auto_add_systems_with_generics; -mod auto_add_systems_with_set; -mod auto_bind_plugin; -mod auto_component; -mod auto_configure_system_set; -mod auto_configure_system_set_schedule_config; -mod auto_configure_system_set_schedule_config_multiple_groups; -mod auto_init_resource; -mod auto_init_resource_generic; -mod auto_init_state; -mod auto_init_sub_state; -mod auto_insert_resource; -mod auto_insert_resource_with_generics; -mod auto_name; -mod auto_name_with_generics; +mod actions; mod auto_plugin; -mod auto_plugin_default_param; -mod auto_plugin_default_param_method; -mod auto_plugin_param; -mod auto_plugin_with_generics; -mod auto_register_state_type; -mod auto_register_type; -mod auto_register_type_generic; -mod auto_run_on_build; -mod auto_run_on_build_with_generics; -mod auto_system_schedule_multiple; -mod auto_system_schedule_non_path; -mod auto_system_schedule_on_state; -mod bare_fn; -mod bare_fn_default_app_param; -mod self_impl_plugin; -mod self_impl_plugin_default_app_param; -mod self_impl_plugin_with_generics; +mod general; +mod rewrites; #[cfg(not(wasm))] mod ui_tests; diff --git a/tests/e2e/auto_component.rs b/tests/e2e/rewrites/auto_component.rs similarity index 100% rename from tests/e2e/auto_component.rs rename to tests/e2e/rewrites/auto_component.rs diff --git a/tests/e2e/rewrites/mod.rs b/tests/e2e/rewrites/mod.rs new file mode 100644 index 00000000..859c775f --- /dev/null +++ b/tests/e2e/rewrites/mod.rs @@ -0,0 +1 @@ +mod auto_component; From 4969ea19769128192571fba7ff34e6cf94bfc001 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 17:08:36 -0400 Subject: [PATCH 126/162] refactor(auto_plugin): remove deprecated `app_param` attribute and update related docs and tests --- .../src/macro_api/attributes/auto_plugin.rs | 12 ++++++++++++ docs/proc_attributes/auto_plugin.md | 10 ++++------ tests/e2e/auto_plugin/bare_fn.rs | 2 +- tests/e2e/auto_plugin/self_impl_plugin.rs | 2 +- .../auto_plugin/self_impl_plugin_with_generics.rs | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs index c53be868..e2220fb5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs @@ -40,9 +40,21 @@ pub struct AutoPluginFnArgs { #[darling(multiple)] pub generics: Vec, pub plugin: Option, + #[darling(and_then = app_param_check)] pub app_param: Option, } +fn app_param_check(app_param: Option) -> darling::Result> { + if let Some(app_param) = app_param { + Err(darling::error::Error::custom( + "manually specifying `app_param` is no longer needed - remove `app_param = ...`", + ) + .with_span(&app_param.span())) + } else { + Ok(app_param) + } +} + pub fn resolve_app_param_name<'a>( input: &'a ItemFn, app_param_name: Option<&'a Ident>, diff --git a/docs/proc_attributes/auto_plugin.md b/docs/proc_attributes/auto_plugin.md index 144771ea..67e4402e 100644 --- a/docs/proc_attributes/auto_plugin.md +++ b/docs/proc_attributes/auto_plugin.md @@ -3,8 +3,6 @@ Attribute to mark the build function for the plugin, or impl Plugin trait build # Parameters - `plugin = PluginType` - **Required for bare functions only.** Specifies the plugin this build function belongs to. **Not allowed on `impl Plugin` methods**, since the plugin type is already known. -- `app_param = identifier` - *(Optional)* Specifies the name of the `App` parameter that code will be injected into. - Defaults to `app` if omitted. # Example - impl Plugin ```rust @@ -15,8 +13,8 @@ use bevy_auto_plugin::prelude::*; struct MyPlugin; impl Plugin for MyPlugin { - #[auto_plugin(app_param=non_default_app_param_name)] - fn build(&self, non_default_app_param_name: &mut App) { + #[auto_plugin] + fn build(&self, app: &mut App) { // code injected here // your code @@ -32,8 +30,8 @@ use bevy_auto_plugin::prelude::*; #[derive(AutoPlugin)] struct MyPlugin; -#[auto_plugin(plugin = MyPlugin, app_param=non_default_app_param_name)] -fn build(non_default_app_param_name: &mut App) { +#[auto_plugin(plugin = MyPlugin)] +fn build(app: &mut App) { // code injected here // your code diff --git a/tests/e2e/auto_plugin/bare_fn.rs b/tests/e2e/auto_plugin/bare_fn.rs index 0e646155..5ac9ead4 100644 --- a/tests/e2e/auto_plugin/bare_fn.rs +++ b/tests/e2e/auto_plugin/bare_fn.rs @@ -18,7 +18,7 @@ pub struct MyResourceAuto(usize); #[auto_init_resource(plugin = MyPlugin)] pub struct MyResourceBuild(usize); -#[auto_plugin(plugin = MyPlugin, app_param = non_default_app_param_name)] +#[auto_plugin(plugin = MyPlugin)] fn build(non_default_app_param_name: &mut App) { non_default_app_param_name.insert_resource(MyResourceBuild(1)); } diff --git a/tests/e2e/auto_plugin/self_impl_plugin.rs b/tests/e2e/auto_plugin/self_impl_plugin.rs index 0f024e2d..425ce475 100644 --- a/tests/e2e/auto_plugin/self_impl_plugin.rs +++ b/tests/e2e/auto_plugin/self_impl_plugin.rs @@ -19,7 +19,7 @@ pub struct MyResourceAuto(usize); pub struct MyResourceBuild(usize); impl Plugin for MyPlugin { - #[auto_plugin(app_param=non_default_app_param_name)] + #[auto_plugin] fn build(&self, non_default_app_param_name: &mut App) { non_default_app_param_name.insert_resource(MyResourceBuild(1)); } diff --git a/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs b/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs index 02e6bb07..e3e58345 100644 --- a/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs +++ b/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs @@ -33,7 +33,7 @@ where T1: Default + Send + Sync + 'static, T2: Default + Send + Sync + 'static, { - #[auto_plugin(app_param=non_default_app_param_name)] + #[auto_plugin] fn build(&self, non_default_app_param_name: &mut App) { non_default_app_param_name.insert_resource(MyResourceBuild(1u8, true)); } From 3fa6af0835489f7a074441a72e9800549498df2d Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 17:33:12 -0400 Subject: [PATCH 127/162] refactor(auto_insert_resource): deprecate `resource` in favor of `init`, update validation, docs, and tests --- .../actions/auto_insert_resource.rs | 39 +++++++++++++++++-- .../actions/auto_insert_resource.md | 4 +- tests/e2e/actions/auto_bind_plugin.rs | 2 +- tests/e2e/actions/auto_insert_resource.rs | 2 +- .../auto_insert_resource_with_generics.rs | 2 +- .../e2e/actions/auto_plugin_with_generics.rs | 2 +- tests/e2e/auto_plugin/bare_fn.rs | 2 +- .../auto_plugin/bare_fn_default_app_param.rs | 2 +- tests/e2e/auto_plugin/self_impl_plugin.rs | 2 +- .../self_impl_plugin_default_app_param.rs | 2 +- .../self_impl_plugin_with_generics.rs | 2 +- tests/e2e/general.rs | 2 +- 12 files changed, 48 insertions(+), 15 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs index 801bbb20..910485ef 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_insert_resource.rs @@ -8,11 +8,37 @@ use quote::{ ToTokens, quote, }; +use syn::spanned::Spanned; #[derive(FromMeta, Debug, Clone, PartialEq, Hash)] -#[darling(derive_syn_parse)] +#[darling(derive_syn_parse, and_then = Self::validate)] pub struct InsertResourceArgs { - pub resource: AnyExprCallClosureMacroPath, + // TODO: after removing resource, remove _resolved, make init required + pub resource: Option, + pub init: Option, + #[darling(skip)] + _resolved: Option, +} + +impl InsertResourceArgs { + fn validate(self) -> darling::Result { + Ok(Self { _resolved: Some(Self::resolve_resource(&self)?.clone()), ..self }) + } + fn resolve_resource(&self) -> darling::Result<&AnyExprCallClosureMacroPath> { + if let Some(resolved) = self._resolved.as_ref() { + Ok(resolved) + } else { + let deprecated = |msg| darling::Error::custom(msg).with_span(&self.resource.span()); + match (self.resource.as_ref(), self.init.as_ref()) { + (Some(_), Some(_)) => { + Err(deprecated("resource and init are mutually exclusive, use init instead")) + } + (None, None) => Err(darling::Error::missing_field("init")), + (Some(_), None) => Err(deprecated("resource is deprecated, use init instead")), + (None, Some(res)) => Ok(res), + } + } + } } impl AttributeIdent for InsertResourceArgs { @@ -28,7 +54,14 @@ pub type InsertResourceAttrEmitter = AttrEmitter; impl EmitAppMutationTokens for InsertResourceAppMutEmitter { fn to_app_mutation_tokens(&self, tokens: &mut TokenStream, app_param: &syn::Ident) { - let resource = &self.args.args.base.resource; + let resource = match self.args.args.base.resolve_resource() { + Ok(resource) => resource, + Err(err) => { + let err = syn::Error::from(err); + tokens.extend(err.to_compile_error()); + return; + } + }; for concrete_path in self.args.concrete_paths() { tokens.extend(quote! { #app_param.insert_resource({ let resource: #concrete_path = #resource; resource}); diff --git a/docs/proc_attributes/actions/auto_insert_resource.md b/docs/proc_attributes/actions/auto_insert_resource.md index 1cbdcd30..47edc49e 100644 --- a/docs/proc_attributes/actions/auto_insert_resource.md +++ b/docs/proc_attributes/actions/auto_insert_resource.md @@ -18,7 +18,7 @@ struct MyPlugin; #[derive(Resource, Debug, Default, PartialEq, Reflect)] #[reflect(Resource)] #[auto_register_type(plugin = MyPlugin)] -#[auto_insert_resource(plugin = MyPlugin, resource(FooResource(42)))] +#[auto_insert_resource(plugin = MyPlugin, init(FooResource(42)))] struct FooResource(usize); ``` @@ -34,6 +34,6 @@ struct MyPlugin; #[derive(Resource, Debug, Default, PartialEq, Reflect)] #[reflect(Resource)] #[auto_register_type(plugin = MyPlugin, generics(usize))] -#[auto_insert_resource(plugin = MyPlugin, resource(FooResourceWithGeneric(42)), generics(usize))] +#[auto_insert_resource(plugin = MyPlugin, init(FooResourceWithGeneric(42)), generics(usize))] struct FooResourceWithGeneric(T); ``` \ No newline at end of file diff --git a/tests/e2e/actions/auto_bind_plugin.rs b/tests/e2e/actions/auto_bind_plugin.rs index aa9fdbe1..a009e9e4 100644 --- a/tests/e2e/actions/auto_bind_plugin.rs +++ b/tests/e2e/actions/auto_bind_plugin.rs @@ -41,7 +41,7 @@ struct FooDefaultRes(usize); #[reflect(Resource)] #[auto_register_type] #[auto_init_resource] -#[auto_insert_resource(resource(FooRes(1)))] +#[auto_insert_resource(init(FooRes(1)))] struct FooRes(usize); #[auto_bind_plugin(plugin = Test)] diff --git a/tests/e2e/actions/auto_insert_resource.rs b/tests/e2e/actions/auto_insert_resource.rs index ba299869..bb3ad85b 100644 --- a/tests/e2e/actions/auto_insert_resource.rs +++ b/tests/e2e/actions/auto_insert_resource.rs @@ -8,7 +8,7 @@ use internal_test_proc_macro::xtest; struct TestPlugin; #[auto_init_resource(plugin = TestPlugin)] -#[auto_insert_resource(plugin = TestPlugin, resource(Test(1)))] +#[auto_insert_resource(plugin = TestPlugin, init(Test(1)))] #[derive(Resource, Debug, Default, PartialEq)] struct Test(usize); diff --git a/tests/e2e/actions/auto_insert_resource_with_generics.rs b/tests/e2e/actions/auto_insert_resource_with_generics.rs index 58ffe656..01a1dd0f 100644 --- a/tests/e2e/actions/auto_insert_resource_with_generics.rs +++ b/tests/e2e/actions/auto_insert_resource_with_generics.rs @@ -8,7 +8,7 @@ use internal_test_proc_macro::xtest; struct TestPlugin; #[auto_init_resource(plugin = TestPlugin, generics(usize, bool))] -#[auto_insert_resource(plugin = TestPlugin, generics(usize, bool), resource(Test(1, true)))] +#[auto_insert_resource(plugin = TestPlugin, generics(usize, bool), init(Test(1, true)))] #[derive(Resource, Debug, Default, PartialEq)] struct Test(T1, T2); diff --git a/tests/e2e/actions/auto_plugin_with_generics.rs b/tests/e2e/actions/auto_plugin_with_generics.rs index 22565dc4..bbd3dccd 100644 --- a/tests/e2e/actions/auto_plugin_with_generics.rs +++ b/tests/e2e/actions/auto_plugin_with_generics.rs @@ -31,7 +31,7 @@ where #[reflect(Resource)] #[auto_register_type(plugin = Test::, generics(u8, bool))] #[auto_init_resource(plugin = Test::, generics(u8, bool))] -#[auto_insert_resource(plugin = Test::, generics(u8, bool), resource(FooRes(1, true)))] +#[auto_insert_resource(plugin = Test::, generics(u8, bool), init(FooRes(1, true)))] struct FooRes(T1, T2) where T1: Default + Send + Sync + 'static, diff --git a/tests/e2e/auto_plugin/bare_fn.rs b/tests/e2e/auto_plugin/bare_fn.rs index 5ac9ead4..c99574fa 100644 --- a/tests/e2e/auto_plugin/bare_fn.rs +++ b/tests/e2e/auto_plugin/bare_fn.rs @@ -11,7 +11,7 @@ pub struct MyPlugin; #[derive(Resource, Default, PartialEq, Debug)] #[auto_init_resource(plugin = MyPlugin)] -#[auto_insert_resource(plugin = MyPlugin, resource(MyResourceAuto(1)))] +#[auto_insert_resource(plugin = MyPlugin, init(MyResourceAuto(1)))] pub struct MyResourceAuto(usize); #[derive(Resource, Default, PartialEq, Debug)] diff --git a/tests/e2e/auto_plugin/bare_fn_default_app_param.rs b/tests/e2e/auto_plugin/bare_fn_default_app_param.rs index ed6aa8fd..7cd5e9f4 100644 --- a/tests/e2e/auto_plugin/bare_fn_default_app_param.rs +++ b/tests/e2e/auto_plugin/bare_fn_default_app_param.rs @@ -11,7 +11,7 @@ pub struct MyPlugin; #[derive(Resource, Default, PartialEq, Debug)] #[auto_init_resource(plugin = MyPlugin)] -#[auto_insert_resource(plugin = MyPlugin, resource(MyResourceAuto(1)))] +#[auto_insert_resource(plugin = MyPlugin, init(MyResourceAuto(1)))] pub struct MyResourceAuto(usize); #[derive(Resource, Default, PartialEq, Debug)] diff --git a/tests/e2e/auto_plugin/self_impl_plugin.rs b/tests/e2e/auto_plugin/self_impl_plugin.rs index 425ce475..e85795f8 100644 --- a/tests/e2e/auto_plugin/self_impl_plugin.rs +++ b/tests/e2e/auto_plugin/self_impl_plugin.rs @@ -11,7 +11,7 @@ pub struct MyPlugin; #[derive(Resource, Default, PartialEq, Debug)] #[auto_init_resource(plugin = MyPlugin)] -#[auto_insert_resource(plugin = MyPlugin, resource(MyResourceAuto(1)))] +#[auto_insert_resource(plugin = MyPlugin, init(MyResourceAuto(1)))] pub struct MyResourceAuto(usize); #[derive(Resource, Default, PartialEq, Debug)] diff --git a/tests/e2e/auto_plugin/self_impl_plugin_default_app_param.rs b/tests/e2e/auto_plugin/self_impl_plugin_default_app_param.rs index 1d72322e..0cb69e30 100644 --- a/tests/e2e/auto_plugin/self_impl_plugin_default_app_param.rs +++ b/tests/e2e/auto_plugin/self_impl_plugin_default_app_param.rs @@ -11,7 +11,7 @@ pub struct MyPlugin; #[derive(Resource, Default, PartialEq, Debug)] #[auto_init_resource(plugin = MyPlugin)] -#[auto_insert_resource(plugin = MyPlugin, resource(MyResourceAuto(1)))] +#[auto_insert_resource(plugin = MyPlugin, init(MyResourceAuto(1)))] pub struct MyResourceAuto(usize); #[derive(Resource, Default, PartialEq, Debug)] diff --git a/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs b/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs index e3e58345..3b8642d9 100644 --- a/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs +++ b/tests/e2e/auto_plugin/self_impl_plugin_with_generics.rs @@ -15,7 +15,7 @@ where #[derive(Resource, Default, PartialEq, Debug)] #[auto_init_resource(plugin = MyPlugin::, generics(u8, bool))] -#[auto_insert_resource(plugin = MyPlugin::, generics(u8, bool), resource(MyResourceAuto(1, true)))] +#[auto_insert_resource(plugin = MyPlugin::, generics(u8, bool), init(MyResourceAuto(1, true)))] pub struct MyResourceAuto(T1, T2) where T1: Default + Send + Sync + 'static, diff --git a/tests/e2e/general.rs b/tests/e2e/general.rs index 4257a1cd..6ab32f0d 100644 --- a/tests/e2e/general.rs +++ b/tests/e2e/general.rs @@ -37,7 +37,7 @@ struct FooDefaultRes(usize); #[reflect(Resource)] #[auto_register_type(plugin = Test)] #[auto_init_resource(plugin = Test)] -#[auto_insert_resource(plugin = Test, resource(FooRes(1)))] +#[auto_insert_resource(plugin = Test, init(FooRes(1)))] struct FooRes(usize); #[auto_resource(plugin = Test, derive, register, reflect, init)] From 5daa8c900bcea5ad4a22bc49f5b242ced9be96af Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 17:37:06 -0400 Subject: [PATCH 128/162] refactor(attr): move `attrs_inject_plugin_param` to `auto_bind_plugin.rs` --- .../__private/expand/attr/auto_bind_plugin.rs | 65 ++++++++++++++++++- .../src/__private/expand/attr/mod.rs | 62 ------------------ 2 files changed, 63 insertions(+), 64 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs index 6d974eb4..fd32ac81 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_bind_plugin.rs @@ -1,5 +1,4 @@ use crate::{ - __private::expand::attr, macro_api::prelude::*, syntax::extensions::item::ItemAttrsExt, util::macros::compile_error_with, @@ -25,7 +24,7 @@ pub fn auto_bind_plugin_inner( let item = item_attribute.input_item.ensure_ast_mut()?; let mut attrs = item.take_attrs().map_err(|err| syn::Error::new(item.span(), err))?; - attr::attrs_inject_plugin_param(&mut attrs, plugin_path); + attrs_inject_plugin_param(&mut attrs, plugin_path); let Ok(_) = item.put_attrs(attrs) else { unreachable!() }; @@ -66,3 +65,65 @@ mod tests { ); } } + +pub fn attrs_inject_plugin_param(attrs: &mut Vec, plugin: &syn::Path) { + use syn::Meta; + + for attr in attrs { + let last = attr.path().segments.last().map(|s| s.ident.to_string()).unwrap_or_default(); + + if !last.starts_with("auto_") { + continue; + } + + let already_has_plugin = match &attr.meta { + Meta::List(ml) => list_has_key(ml, "plugin"), + Meta::Path(_) => false, + Meta::NameValue(_) => true, + }; + + if already_has_plugin { + continue; + } + + attr_inject_plugin_param(attr, plugin); + } +} + +fn attr_inject_plugin_param(attr: &mut syn::Attribute, plugin: &syn::Path) { + use syn::{ + Meta, + parse_quote, + }; + match &attr.meta { + Meta::Path(path) => *attr = parse_quote!( #[#path(plugin = #plugin)] ), + Meta::List(ml) => { + let path = &ml.path; + let inner = &ml.tokens; + if inner.is_empty() { + *attr = parse_quote!( #[#path(plugin = #plugin)] ) + } else { + *attr = parse_quote!( #[#path(plugin = #plugin, #inner)] ) + } + } + _ => {} + } +} + +fn list_has_key(ml: &syn::MetaList, key: &str) -> bool { + use syn::{ + Meta, + Token, + parse::Parser, + punctuated::Punctuated, + }; + let parser = Punctuated::::parse_terminated; + match parser.parse2(ml.tokens.clone()) { + Ok(list) => list.iter().any(|m| match m { + Meta::NameValue(nv) => nv.path.is_ident(key), + Meta::List(ml2) => ml2.path.is_ident(key), + Meta::Path(p) => p.is_ident(key), + }), + Err(_) => false, + } +} diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index ce3f099a..2eea4a53 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -6,68 +6,6 @@ pub mod auto_bind_plugin; pub mod auto_plugin; pub mod rewrite; -pub fn attrs_inject_plugin_param(attrs: &mut Vec, plugin: &syn::Path) { - use syn::Meta; - - for attr in attrs { - let last = attr.path().segments.last().map(|s| s.ident.to_string()).unwrap_or_default(); - - if !last.starts_with("auto_") { - continue; - } - - let already_has_plugin = match &attr.meta { - Meta::List(ml) => list_has_key(ml, "plugin"), - Meta::Path(_) => false, - Meta::NameValue(_) => true, - }; - - if already_has_plugin { - continue; - } - - attr_inject_plugin_param(attr, plugin); - } -} - -fn attr_inject_plugin_param(attr: &mut syn::Attribute, plugin: &syn::Path) { - use syn::{ - Meta, - parse_quote, - }; - match &attr.meta { - Meta::Path(path) => *attr = parse_quote!( #[#path(plugin = #plugin)] ), - Meta::List(ml) => { - let path = &ml.path; - let inner = &ml.tokens; - if inner.is_empty() { - *attr = parse_quote!( #[#path(plugin = #plugin)] ) - } else { - *attr = parse_quote!( #[#path(plugin = #plugin, #inner)] ) - } - } - _ => {} - } -} - -fn list_has_key(ml: &syn::MetaList, key: &str) -> bool { - use syn::{ - Meta, - Token, - parse::Parser, - punctuated::Punctuated, - }; - let parser = Punctuated::::parse_terminated; - match parser.parse2(ml.tokens.clone()) { - Ok(list) => list.iter().any(|m| match m { - Meta::NameValue(nv) => nv.path.is_ident(key), - Meta::List(ml2) => ml2.path.is_ident(key), - Meta::Path(p) => p.is_ident(key), - }), - Err(_) => false, - } -} - macro_rules! gen_action_outers { ( $( $fn:ident => $args:ty ),+ $(,)? ) => { $( From cb8b8cfb90473839c1e71eeddff32eef7ddd1088 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 18:03:30 -0400 Subject: [PATCH 129/162] chore(docs): add `ARCHITECTURE.md` detailing flow --- ARCHITECTURE.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 ARCHITECTURE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000..a84b1bb6 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,27 @@ +# Architecture + +## Flow +- each `bevy_auto_plugin_proc_macros` re-exported by `bevy_auto_plugin` crate in `src/lib` `prelude` +- `#[derive(AutoPlugin)]` + - calls into `crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs` +- `#[auto_plugin]` + - calls into `crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs` +- `#[auto_*(...)]` + - calls into `crates/bevy_auto_plugin_shared/src/__private/expand/attr` + - actions are items that change the input token stream or append tokens to register the static slices during initialization + - rewrites are attributes that expand into several other attributes. only modifies input item attrs. + - params defined in `crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions` + - `ItemAttribute, R>` + - `T` = [darling](https://crates.io/crates/darling) param struct + - `P` = plugin params: `WithPlugin` + - `G` = generics: `WithZeroGenerics | WithZeroOrSingleGenerics | WithZeroOrManyGenerics` + - `R` = resolver: `AllowAny | AllowFn | AllowStructOrEnum` + - Each action attribute may impl traits for `AppMutationEmitter` or `AttrEmitter`. + - `AppMutationEmitter` is responsible for the tokens generated for each respective static slice being constructed + - bonus: it can also override the implementation to mutate the input tokens. for example, allowing helper attributes to exist on an enum variant. + - see `crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs` for the only current use case. + - `AttrEmitter` is responsible for serializing a param sctruct back to tokens + - there's several custom parsing types in `crates/bevy_auto_plugin_shared/src/syntax/ast` + - all hygenic bevy paths are in `crates/bevy_auto_plugin_shared/src/codegen/tokens.rs` + - crate aliases are resolved using `proc-macro-crate` + - input tokens are expected to be preserved during errors. without this, IDEs can struggle when editing macros. \ No newline at end of file From e6c4a532416c492ae3628a6de20fdbad624334f2 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 18:10:15 -0400 Subject: [PATCH 130/162] chore(docs): expand `ARCHITECTURE.md` --- ARCHITECTURE.md | 104 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 25 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index a84b1bb6..2bb70476 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,27 +1,81 @@ # Architecture -## Flow -- each `bevy_auto_plugin_proc_macros` re-exported by `bevy_auto_plugin` crate in `src/lib` `prelude` -- `#[derive(AutoPlugin)]` - - calls into `crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs` -- `#[auto_plugin]` - - calls into `crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs` -- `#[auto_*(...)]` - - calls into `crates/bevy_auto_plugin_shared/src/__private/expand/attr` - - actions are items that change the input token stream or append tokens to register the static slices during initialization - - rewrites are attributes that expand into several other attributes. only modifies input item attrs. - - params defined in `crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions` - - `ItemAttribute, R>` - - `T` = [darling](https://crates.io/crates/darling) param struct - - `P` = plugin params: `WithPlugin` - - `G` = generics: `WithZeroGenerics | WithZeroOrSingleGenerics | WithZeroOrManyGenerics` - - `R` = resolver: `AllowAny | AllowFn | AllowStructOrEnum` - - Each action attribute may impl traits for `AppMutationEmitter` or `AttrEmitter`. - - `AppMutationEmitter` is responsible for the tokens generated for each respective static slice being constructed - - bonus: it can also override the implementation to mutate the input tokens. for example, allowing helper attributes to exist on an enum variant. - - see `crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs` for the only current use case. - - `AttrEmitter` is responsible for serializing a param sctruct back to tokens - - there's several custom parsing types in `crates/bevy_auto_plugin_shared/src/syntax/ast` - - all hygenic bevy paths are in `crates/bevy_auto_plugin_shared/src/codegen/tokens.rs` - - crate aliases are resolved using `proc-macro-crate` - - input tokens are expected to be preserved during errors. without this, IDEs can struggle when editing macros. \ No newline at end of file +This document explains how the `bevy_auto_plugin` ecosystem is structured and how macro expansion flows through the crates. + +## High-Level Flow + +1. **User-facing macros** are re-exported from `bevy_auto_plugin` (in [`src/lib.rs`](src/lib.rs) under the `prelude`). +2. When a user applies: + - `#[derive(AutoPlugin)]` → expansion handled by + [`bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs`](crates/bevy_auto_plugin_shared/src/__private/expand/derive/auto_plugin.rs) + - `#[auto_plugin]` (attribute form) → expansion handled by + [`bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs`](crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs) + - `#[auto_*( ... )]` attributes → routed to + [`bevy_auto_plugin_shared/src/__private/expand/attr/`](crates/bevy_auto_plugin_shared/src/__private/expand/attr/) + +--- + +## Attribute Types + +`auto_*` attributes fall into two categories: + +### Actions + +- Mutate the input token stream **and/or** append code that registers static slices used during plugin initialization. +- Parsing types are defined in: + [`bevy_auto_plugin_shared/src/macro_api/attributes/actions`](crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions) + +Each action attribute is modeled as: `ItemAttribute, R>` + +Where: + +| Generic | Meaning | +|---------|----------| +| `T` | The [`darling`](https://crates.io/crates/darling) parameter struct for the attribute | +| `P` | Plugin context: `WithPlugin` | +| `G` | Generics handling: `WithZeroGenerics`, `WithZeroOrSingleGenerics`, or `WithZeroOrManyGenerics` | +| `R` | Resolver restricting usage: `AllowAny`, `AllowFn`, or `AllowStructOrEnum` | + +Actions can implement traits for one or both of the following wrapper types: + +#### [`AppMutationEmitter`](crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs) + +- Generates tokens for static slice registration and plugin mutation. +- **May also mutate the input tokens** (rare). + Example use case: allowing helper attributes on enum variants. + See: + [`bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs`](crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs) + +#### [`AttrEmitter`](crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr.rs) + +- Responsible for serializing a parsed parameter struct back into attribute tokens (useful for rewrite expansions). + +--- + +### Rewrites + +- Expand into one or more other attributes. +- Only modify the **item’s attributes**, not the item body. +- Uses wrapper type [`AttrExpansionEmitter`](crates/bevy_auto_plugin_shared/src/macro_api/emitters/attr_expansion.rs) + +--- + +## Supporting Infrastructure + +### Custom Parsing + +Located in: +[`bevy_auto_plugin_shared/src/syntax/ast`](crates/bevy_auto_plugin_shared/src/syntax/ast) +Includes custom AST fragments, parsing helpers, and type definitions used across attributes. + +### Codegen Tokens + +All hygienic Bevy paths are centralized in: +[`bevy_auto_plugin_shared/src/codegen/tokens.rs`](crates/bevy_auto_plugin_shared/src/codegen/tokens.rs) + +- Crate alias resolution is handled via [`proc-macro-crate`](https://crates.io/crates/proc-macro-crate). + +### Token Preservation + +Macro expansions are designed to **preserve input tokens on errors**. +This ensures IDEs (like rust-analyzer) maintain valid syntax trees and prevent code “going red” on partially-written macro usage. From 6688fd51282dd8ed235c76c4a592eb7b966319f7 Mon Sep 17 00:00:00 2001 From: bstriker Date: Mon, 27 Oct 2025 18:14:11 -0400 Subject: [PATCH 131/162] chore(docs): update `ARCHITECTURE.md` with notes on `Composed` and potential merging with `ItemAttribute` --- ARCHITECTURE.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 2bb70476..47fa835f 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -36,6 +36,9 @@ Where: | `G` | Generics handling: `WithZeroGenerics`, `WithZeroOrSingleGenerics`, or `WithZeroOrManyGenerics` | | `R` | Resolver restricting usage: `AllowAny`, `AllowFn`, or `AllowStructOrEnum` | +notes: +- `Composed` can probably be merged into `ItemAttribute` but it's currently left open if we decide to add macros that aren't attached to the usual items (unlikely). + Actions can implement traits for one or both of the following wrapper types: #### [`AppMutationEmitter`](crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs) From 259a269d8896dec9d0e48aa0cf89f7b6830a8ba2 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 28 Oct 2025 12:35:13 -0400 Subject: [PATCH 132/162] chore(docs): add TODO comment in `Context` for alias resolution in proc macros --- crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs index 431d62e6..49da3a8a 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/context/mod.rs @@ -2,6 +2,7 @@ use macro_paths::MacroPaths; mod macro_paths; +// TODO: pass from proc macros and resolve any aliases - instead of defaulting #[derive(Debug, Clone, Default, PartialEq, Hash)] pub struct Context { pub macros: MacroPaths, From 3e3c327a3594cc160b152a6072790c48a70fa2ae Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 28 Oct 2025 12:42:32 -0400 Subject: [PATCH 133/162] refactor(auto_plugin): simplify `resolve_app_param_name` by removing unused `app_param` argument and updating related tests --- .../src/__private/expand/attr/auto_plugin.rs | 4 +- .../src/macro_api/attributes/auto_plugin.rs | 60 +++---------------- 2 files changed, 9 insertions(+), 55 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs index c6c1f66c..2a0b85af 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/auto_plugin.rs @@ -37,9 +37,7 @@ pub fn expand_auto_plugin(attr: MacroStream, input: MacroStream) -> MacroStream .collect::>(); let self_arg = self_args.first(); - // TODO: use helper - let app_param_ident = - ok_or_emit_with!(resolve_app_param_name(&item, params.app_param.as_ref()), og_input); + let app_param_ident = ok_or_emit_with!(resolve_app_param_name(&item), og_input); if let Err(err) = require_fn_param_mutable_reference(&item, app_param_ident, "bevy app") { return compile_error_with!(err, og_input); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs index e2220fb5..f587461c 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/auto_plugin.rs @@ -55,13 +55,7 @@ fn app_param_check(app_param: Option) -> darling::Result> { } } -pub fn resolve_app_param_name<'a>( - input: &'a ItemFn, - app_param_name: Option<&'a Ident>, -) -> syn::Result<&'a Ident> { - // Helper: pick a useful Span for errors - let err_span = || app_param_name.map(Ident::span).unwrap_or_else(|| input.sig.span()); - +pub fn resolve_app_param_name(input: &ItemFn) -> syn::Result<&Ident> { // Helper: try to get &Ident from a typed arg fn ident_from_typed_arg(arg: &FnArg) -> Option<&Ident> { match arg { @@ -78,30 +72,17 @@ pub fn resolve_app_param_name<'a>( // collect all named params let named = input.sig.inputs.iter().filter_map(ident_from_typed_arg).collect::>(); - // If user explicitly provided a name, validate it exists and return it - if let Some(given) = app_param_name.as_ref() { - if let Some(found) = named.iter().copied().find(|id| id == given) { - return Ok(found); - } - return Err(syn::Error::new( - err_span(), - format!( - "auto_plugin provided app_param: `{given}` but it was not found in the function signature" - ), - )); - } - // Otherwise infer. We need exactly one named param after any receiver(s). match named.as_slice() { [] => { if has_self { Err(syn::Error::new( - err_span(), + input.sig.inputs.span(), "auto_plugin requires a method taking at least one parameter in addition to `&self`", )) } else { Err(syn::Error::new( - err_span(), + input.sig.inputs.span(), "auto_plugin requires a function taking at least one named parameter", )) } @@ -112,7 +93,7 @@ pub fn resolve_app_param_name<'a>( Ok(*only) } _more => Err(syn::Error::new( - err_span(), + input.sig.inputs.span(), "auto_plugin requires specifying the name of the `&mut bevy::app::App` parameter \ when there’s more than one parameter, e.g.: #[auto_plugin(app_param=my_app)] @@ -125,38 +106,13 @@ pub fn resolve_app_param_name<'a>( mod tests { use crate::macro_api::attributes::auto_plugin::resolve_app_param_name; use internal_test_proc_macro::xtest; - use proc_macro2::{ - Ident, - Span, - }; - - #[xtest] - #[should_panic = "auto_plugin provided app_param: `bar` but it was not found in the function signature"] - fn test_resolve_app_param_name_wrong_specified() { - let item = syn::parse_quote! { - fn foo(&mut self, foo: &mut App) {} - }; - let target_ident = Ident::new("bar", Span::call_site()); - let ident = resolve_app_param_name(&item, Some(&target_ident)).unwrap(); - assert_eq!(ident, "foo"); - } - - #[xtest] - fn test_resolve_app_param_name_specified() { - let item = syn::parse_quote! { - fn foo(&mut self, foo1: &mut App, foo2: &mut App, foo3: &mut App) {} - }; - let target_ident = Ident::new("foo2", Span::call_site()); - let ident = resolve_app_param_name(&item, Some(&target_ident)).unwrap(); - assert_eq!(ident, "foo2"); - } #[xtest] fn test_resolve_app_param_name_default() { let item = syn::parse_quote! { fn foo(&mut self, foo: &mut App) {} }; - let ident = resolve_app_param_name(&item, None).unwrap(); + let ident = resolve_app_param_name(&item).unwrap(); assert_eq!(ident, "foo"); } @@ -166,7 +122,7 @@ mod tests { let item = syn::parse_quote! { fn foo() {} }; - match resolve_app_param_name(&item, None) { + match resolve_app_param_name(&item) { Ok(_) => {} Err(err) => panic!("{err:?}"), } @@ -178,7 +134,7 @@ mod tests { let item = syn::parse_quote! { fn foo(&mut self) {} }; - match resolve_app_param_name(&item, None) { + match resolve_app_param_name(&item) { Ok(_) => {} Err(err) => panic!("{err:?}"), } @@ -190,7 +146,7 @@ mod tests { let item = syn::parse_quote! { fn foo(&mut self, foo: &Bar) {} }; - match resolve_app_param_name(&item, None) { + match resolve_app_param_name(&item) { Ok(_) => {} Err(err) => panic!("{err:?}"), } From 868f6529f11c8247fb33b72cfeb1d95c53faaefd Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 28 Oct 2025 12:43:13 -0400 Subject: [PATCH 134/162] chore(docs): remove obsolete TODO comment in `tokens.rs` --- crates/bevy_auto_plugin_shared/src/codegen/tokens.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs index 017f21eb..555f61f6 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs @@ -21,9 +21,6 @@ pub fn reflect<'a>(idents: impl IntoIterator) -> ExpandAttrs { .filter_map(|ident| { Some(match ident.to_string().as_str() { // Make the helper available for #[reflect(Component)] - // TODO: we could eliminate the need for globs if we pass the ident in - // then we can do `ReflectComponent as ReflectComponent$ident` - // #[reflect(Component$ident)] "Component" => crate::__private::paths::reflect::reflect_component_use_tokens(), // Make the helper available for #[reflect(Resource)] "Resource" => crate::__private::paths::reflect::reflect_resource_use_tokens(), From 48deba917e497afae47e80610c8b4b250c3846e4 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 28 Oct 2025 13:41:42 -0400 Subject: [PATCH 135/162] refactor(scrub_helpers): replace `write_*` methods with `replace_*` and `prepend_errors`, add docs --- .../actions/auto_configure_system_set.rs | 4 +- .../src/syntax/parse/scrub_helpers.rs | 82 +++++++++++++------ 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index f8fc6f2b..2dee71a5 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -278,11 +278,11 @@ pub fn inflate_args_from_input( // 3) if args._strip_helpers { // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with - scrub.write_back(&mut scrubbed_tokens)?; + scrub.replace_token_stream(&mut scrubbed_tokens)?; } else { // Check if we have errors to print and if so, strip helpers from the item // Otherwise, maintain helpers for the next attribute to process - scrub.write_if_errors_with_scrubbed_item(&mut scrubbed_tokens)?; + scrub.prepend_errors(&mut scrubbed_tokens)?; } // 4) If it's a struct, there are no entries to compute diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index 749c5410..04ab46c6 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -140,6 +140,7 @@ pub struct ScrubOutcome { } impl ScrubOutcome { + /// Returns all observed attrs and call sites regardless if they were removed or not pub fn all_with_removed_attrs(&self) -> Vec { let mut out = Vec::with_capacity(self.observed.len()); for group in self.observed.iter() { @@ -154,40 +155,46 @@ impl ScrubOutcome { } out } - // TODO: Better name? - /// If there are errors, it will write them above the scrubbed item. - /// Otherwise, will NOT write the scrubbed item back into the TokenStream - pub fn write_if_errors_with_scrubbed_item( - &self, - token_stream: &mut TokenStream, - ) -> syn::Result<()> { - write_back(token_stream, self.item.span(), self.errors.clone(), "failed to scrub helpers") + /// It will only mutate the TokenStream if there are errors by prepending them + pub fn prepend_errors(&self, token_stream: &mut TokenStream) -> syn::Result<()> { + ts_prepend_errors( + token_stream, + self.item.span(), + self.errors.clone(), + "failed to scrub helpers", + ) } - pub fn write_back(&self, token_stream: &mut TokenStream) -> syn::Result<()> { - write_back_item(token_stream, &self.item, self.errors.clone(), "failed to scrub helpers") + /// Replaces the token stream with the scrubbed item. + /// If there are errors, it will write them above the scrubbed item. + pub fn replace_token_stream(&self, token_stream: &mut TokenStream) -> syn::Result<()> { + replace_ts_with_item_and_errors( + token_stream, + &self.item, + self.errors.clone(), + "failed to scrub helpers", + ) } } -pub fn write_back_item( - token_stream: &mut TokenStream, - item: &Item, - errors: Vec, - message: &str, -) -> syn::Result<()> { - *token_stream = quote! { - #item - }; - - write_back(token_stream, item.span(), errors, message) -} - -pub fn write_back( +/// Writes errors to the token stream if they exist, otherwise doesn't modify the token stream. +/// +/// # Arguments +/// +/// * `token_stream` - The token stream to potentially write errors into +/// * `span` - The span location for error reporting +/// * `errors` - Collection of errors to potentially write +/// * `message` - Error message to include +/// +/// # Returns +/// +/// A Result indicating success or failure of the operation +pub fn ts_prepend_errors( token_stream: &mut TokenStream, span: proc_macro2::Span, errors: Vec, message: &str, ) -> syn::Result<()> { - // inject any errors as compile_error! right here. + // inject any errors as compile_error right here. if !errors.is_empty() { let err_ts = errors.iter().map(syn::Error::to_compile_error); *token_stream = quote! { @@ -202,6 +209,31 @@ pub fn write_back( Ok(()) } +/// Replaces the `TokenStream` in place with the item tokens and prepends any errors. +/// +/// # Arguments +/// +/// * `token_stream` - The token stream to output to +/// * `item` - The item to render +/// * `errors` - Collection of errors to potentially write +/// * `message` - Error message to include +/// +/// # Returns +/// +/// A Result indicating success or failure of the operation +pub fn replace_ts_with_item_and_errors( + token_stream: &mut TokenStream, + item: &Item, + errors: Vec, + message: &str, +) -> syn::Result<()> { + *token_stream = quote! { + #item + }; + + ts_prepend_errors(token_stream, item.span(), errors, message) +} + #[derive(Debug, Default)] struct KeepSplit { keep: Vec, From 479ddf2f4af149ff32a5be36989fdf8ce59a6ac6 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 28 Oct 2025 18:54:02 -0400 Subject: [PATCH 136/162] feat(internal_test_util): add `token_stream` module with `Ts` wrapper, utilities, and `assert_ts_eq!` macro --- crates/internal_test_util/Cargo.toml | 2 ++ crates/internal_test_util/src/lib.rs | 1 + crates/internal_test_util/src/token_stream.rs | 33 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 crates/internal_test_util/src/token_stream.rs diff --git a/crates/internal_test_util/Cargo.toml b/crates/internal_test_util/Cargo.toml index 238580f9..492c35e4 100644 --- a/crates/internal_test_util/Cargo.toml +++ b/crates/internal_test_util/Cargo.toml @@ -20,6 +20,8 @@ internal_test_proc_macro = { workspace = true } trybuild = { workspace = true } darling = { workspace = true } syn = { workspace = true } +proc-macro2 = { workspace = true } +quote = { workspace = true } [dev-dependencies] wasm-bindgen-test = { workspace = true } \ No newline at end of file diff --git a/crates/internal_test_util/src/lib.rs b/crates/internal_test_util/src/lib.rs index fba57338..a4d347b7 100644 --- a/crates/internal_test_util/src/lib.rs +++ b/crates/internal_test_util/src/lib.rs @@ -1,3 +1,4 @@ +pub mod token_stream; pub mod ui_util; use bevy_app::App; diff --git a/crates/internal_test_util/src/token_stream.rs b/crates/internal_test_util/src/token_stream.rs new file mode 100644 index 00000000..fc4e3bc5 --- /dev/null +++ b/crates/internal_test_util/src/token_stream.rs @@ -0,0 +1,33 @@ +#![allow(unused)] + +use proc_macro2::TokenStream; +use quote::ToTokens; + +#[derive(Debug)] +pub struct Ts(TokenStream); + +impl PartialEq for Ts { + fn eq(&self, other: &Self) -> bool { + self.0.to_string() == other.0.to_string() + } +} + +pub fn ts(token_stream: impl ToTokens) -> Ts { + Ts(token_stream.to_token_stream()) +} + +impl From for Ts +where + T: ToTokens, +{ + fn from(value: T) -> Self { + Self(value.into_token_stream()) + } +} + +#[macro_export] +macro_rules! assert_ts_eq { + ($left:expr, $right:expr $(, $msg:expr)?) => { + assert_eq!($crate::token_stream::ts($left), $crate::token_stream::ts($right), $($msg)?); + }; +} From d44efd89f42e041f4e2f905da11b76b1a13a57de Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 28 Oct 2025 18:55:29 -0400 Subject: [PATCH 137/162] feat(codegen): add `emit.rs` for managing token streams with checkpointing, error handling, and related utilities --- .../src/codegen/emit.rs | 420 ++++++++++++++++++ .../src/codegen/mod.rs | 1 + 2 files changed, 421 insertions(+) create mode 100644 crates/bevy_auto_plugin_shared/src/codegen/emit.rs diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs new file mode 100644 index 00000000..89f312d5 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -0,0 +1,420 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; + +#[derive(Debug, Default, Clone)] +pub(crate) struct EmitBuilder { + tokens: TokenStream, + // LIFO stack of checkpoints for nested phases + checkpoints: Vec, +} + +impl EmitBuilder { + pub(crate) fn new() -> Self { + Self::default() + } + + pub(crate) fn from_checkpoint(cp: TokenStream) -> Self { + Self { tokens: cp.clone(), checkpoints: vec![cp] } + } + + #[inline] + pub(crate) fn extend(&mut self, ts: impl ToTokens) -> &mut Self { + self.tokens.extend(ts.into_token_stream()); + self + } + + #[inline] + pub(crate) fn replace(&mut self, ts: impl ToTokens) -> &mut Self { + self.tokens = ts.into_token_stream(); + self + } + + /// Push the current tokens as a checkpoint. + #[must_use] + pub(crate) fn push_checkpoint(&mut self) -> &mut Self { + self.checkpoints.push(self.tokens.clone()); + self + } + + /// Restore to the last checkpoint. No-op if empty. + #[must_use] + pub(crate) fn restore(&mut self) -> &mut Self { + if let Some(cp) = self.checkpoints.last() { + self.tokens = cp.clone(); + } + self + } + + /// Restore to the last checkpoint and **pop** it. No-op if empty. + #[must_use] + pub(crate) fn pop_restore(&mut self) -> &mut Self { + if let Some(cp) = self.checkpoints.pop() { + self.tokens = cp; + } + self + } + + /// Discard the last checkpoint (keep current tokens). No-op if empty. + #[must_use] + pub(crate) fn discard_checkpoint(&mut self) -> &mut Self { + self.checkpoints.pop(); + self + } + + /// Finish successfully. + pub(crate) fn into_ok(self, value: T) -> EmitResult { + EmitResult::Ok { tokens: self.tokens, value } + } + + /// Finish with an error; emits the **last checkpoint** if any, else current tokens. + pub(crate) fn into_err(self, err: E) -> EmitResult + where + EmitError: From, + { + let fallback = + if let Some(cp) = self.checkpoints.last() { cp.clone() } else { self.tokens.clone() }; + EmitResult::Err { tokens: fallback, error: err.into() } + } + + /// Try a phase with automatic checkpointing. + #[must_use] + pub(crate) fn try_phase(&mut self, f: impl FnOnce(&mut Self) -> Result<(), E>) -> &mut Self + where + EmitError: From, + { + match f(self.push_checkpoint()) { + Ok(()) => self.discard_checkpoint(), + Err(_e) => self.pop_restore(), + } + } + + pub(crate) fn take_tokens(&mut self) -> TokenStream { + std::mem::take(&mut self.tokens) + } + + pub(crate) fn tokens(&self) -> &TokenStream { + &self.tokens + } +} + +impl std::ops::Deref for EmitBuilder { + type Target = TokenStream; + fn deref(&self) -> &Self::Target { + &self.tokens + } +} +impl std::ops::DerefMut for EmitBuilder { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.tokens + } +} + +impl ToTokens for EmitBuilder { + fn to_tokens(&self, out: &mut TokenStream) { + out.extend(self.tokens.to_token_stream()); + } +} + +#[derive(Debug, Clone, thiserror::Error)] +pub(crate) enum EmitError { + #[error("{0}")] + Syn(#[from] syn::Error), + #[error("{0}")] + Darling(#[from] darling::Error), +} + +impl From for syn::Error { + fn from(e: EmitError) -> Self { + match e { + EmitError::Syn(s) => s, + EmitError::Darling(d) => d.into(), + } + } +} +impl From for darling::Error { + fn from(e: EmitError) -> Self { + match e { + EmitError::Syn(s) => s.into(), + EmitError::Darling(d) => d, + } + } +} + +#[derive(Debug, Clone)] +pub(crate) enum EmitResult { + Ok { tokens: TokenStream, value: T }, + Err { tokens: TokenStream, error: EmitError }, +} + +impl EmitResult { + pub fn ok(tokens: TokenStream, value: T) -> Self { + Self::Ok { tokens, value } + } + pub fn err(tokens: TokenStream, error: impl Into) -> Self { + Self::Err { tokens, error: error.into() } + } + + pub fn is_ok(&self) -> bool { + matches!(self, Self::Ok { .. }) + } + pub fn is_err(&self) -> bool { + !self.is_ok() + } + + pub fn map(self, f: impl FnOnce(T) -> U) -> EmitResult { + match self { + Self::Ok { tokens, value } => EmitResult::Ok { tokens, value: f(value) }, + Self::Err { tokens, error } => EmitResult::Err { tokens, error }, + } + } + pub fn map_err(self, f: impl FnOnce(EmitError) -> EmitError) -> Self { + match self { + Self::Err { tokens, error } => Self::Err { tokens, error: f(error) }, + ok => ok, + } + } + + /// Split into tokens and a plain `Result`. + pub fn split(self) -> (TokenStream, Result) { + match self { + Self::Ok { tokens, value } => (tokens, Ok(value)), + Self::Err { tokens, error } => (tokens, Err(error)), + } + } +} + +impl From> for syn::Result { + fn from(v: EmitResult) -> Self { + match v { + EmitResult::Ok { value, .. } => Ok(value), + EmitResult::Err { error, .. } => Err(error.into()), + } + } +} +impl From> for darling::Result { + fn from(v: EmitResult) -> Self { + match v { + EmitResult::Ok { value, .. } => Ok(value), + EmitResult::Err { error, .. } => Err(error.into()), + } + } +} +impl ToTokens for EmitResult { + fn to_tokens(&self, out: &mut TokenStream) { + let ts = match self { + EmitResult::Ok { tokens, .. } | EmitResult::Err { tokens, .. } => tokens, + }; + out.extend(ts.clone()); + } +} + +#[derive(Debug)] +pub(crate) struct FatalEmit { + pub tokens: TokenStream, + pub error: EmitError, +} +impl From> for Result { + fn from(v: EmitResult) -> Self { + match v { + EmitResult::Ok { value, .. } => Ok(value), + EmitResult::Err { tokens, error } => Err(FatalEmit { tokens, error }), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use internal_test_proc_macro::xtest; + use internal_test_util::assert_ts_eq; + use quote::quote; + + #[xtest] + fn builder_extend_and_replace() { + let mut b = EmitBuilder::new(); + b.extend(quote! { a }); + assert_ts_eq!(&b, quote! { a }); + + b.replace(quote! { b }); + assert_ts_eq!(&b, quote! { b }); + + b.extend(quote! { c d }); + assert_ts_eq!(&b, quote! { b c d }); + } + + #[xtest] + fn builder_checkpoint_restore_and_pop() { + // start with some base + let mut b = EmitBuilder::from_checkpoint(quote! { base }); + assert_ts_eq!(&b, quote! { base }); + + // push + modify + restore (non-pop) should revert to base but leave checkpoint on stack + let _ = b.push_checkpoint().extend(quote! { X }).restore(); + assert_ts_eq!(&b, quote! { base }); + + // modify again then pop_restore should also revert to base *and* pop the checkpoint + let _ = b.extend(quote! { TEMP }).pop_restore(); + assert_ts_eq!(&b, quote! { base }); + + // push + modify + discard should keep the modified result + let _ = b.push_checkpoint().extend(quote! { KEEP }).discard_checkpoint(); + assert_ts_eq!(&b, quote! { base KEEP }); + } + + #[xtest] + fn try_phase_ok_keeps_changes() { + let mut b = EmitBuilder::from_checkpoint(quote! { init }); + let _ = b.try_phase(|b| { + // phase mutates tokens + b.extend(quote! { ok1 ok2 }); + Ok::<_, syn::Error>(()) + }); + assert_ts_eq!(&b, quote! { init ok1 ok2 }); + } + + #[xtest] + fn try_phase_err_restores_checkpoint() { + let mut b = EmitBuilder::from_checkpoint(quote! { start }); + let _ = b.try_phase(|b| { + // mutate then fail; should revert to checkpoint + b.extend(quote! { broken }); + Err::<(), _>(syn::Error::new(proc_macro2::Span::call_site(), "boom")) + }); + assert_ts_eq!(&b, quote! { start }); + } + + #[xtest] + fn into_ok_and_into_err_fallback_rules() { + // into_ok uses current tokens + let b1 = { + let mut b = EmitBuilder::from_checkpoint(quote! { cp }); + b.extend(quote! { work }); + b + }; + let ok: EmitResult = b1.into_ok(42); + match ok { + EmitResult::Ok { tokens, value } => { + assert_eq!(value, 42); + assert_ts_eq!(&tokens, quote! { cp work }); + } + _ => panic!("expected Ok"), + } + + // into_err uses last checkpoint (cp), not the mutated tokens + let b2 = { + let mut b = EmitBuilder::from_checkpoint(quote! { cp }); + b.extend(quote! { work }); + b + }; + let err: EmitResult<()> = + b2.into_err(syn::Error::new(proc_macro2::Span::call_site(), "nope")); + match err { + EmitResult::Err { tokens, error } => { + let _: syn::Error = error.clone().into(); // convertible + assert_ts_eq!(&tokens, quote! { cp }); + } + _ => panic!("expected Err"), + } + } + + #[xtest] + fn result_conversions_to_syn_and_darling() { + // Ok path -> Ok(_) + let ok: EmitResult<&'static str> = EmitResult::ok(quote! { t }, "v"); + let syn_ok: syn::Result<_> = ok.clone().into(); + let dar_ok: darling::Result<_> = ok.into(); + assert!(syn_ok.is_ok()); + assert!(dar_ok.is_ok()); + + // Err path -> Err(_) + let e = syn::Error::new(proc_macro2::Span::call_site(), "bad"); + let err: EmitResult<()> = EmitResult::err(quote! { t }, e); + let syn_err: syn::Result<()> = err.clone().into(); + let dar_err: darling::Result<()> = err.into(); + assert!(syn_err.is_err()); + assert!(dar_err.is_err()); + } + + #[xtest] + fn result_split_and_map() { + // split ok + { + let ok: EmitResult = EmitResult::ok(quote! { T }, 5); + let (ts, res) = ok.split(); + assert_ts_eq!(&ts, quote! { T }); + assert_eq!(res.unwrap(), 5); + } + + // map + { + let ok: EmitResult<&'static str> = EmitResult::ok(quote! { U }, "abc"); + let mapped = ok.map(|s| s.len()); + let (ts, res) = mapped.split(); + assert_ts_eq!(ts, quote! { U }); + assert_eq!(res.unwrap(), 3); + } + + // split err + { + let err: EmitResult<()> = EmitResult::err( + quote! { E }, + syn::Error::new(proc_macro2::Span::call_site(), "nope"), + ); + let (ts, res) = err.split(); + assert_ts_eq!(&ts, quote! { E }); + assert!(res.is_err()); + } + } + + #[xtest] + fn to_tokens_impls_emit_builder_and_emit_result() { + // EmitBuilder → ToTokens + let mut b = EmitBuilder::new(); + b.extend(quote! { a b c }); + let mut out = TokenStream::new(); + b.to_tokens(&mut out); + assert_ts_eq!(&out, quote! { a b c }); + + // EmitResult Ok → ToTokens + let ok: EmitResult<()> = EmitResult::ok(quote! { OKTOK }, ()); + let mut out_ok = TokenStream::new(); + ok.to_tokens(&mut out_ok); + assert_ts_eq!(&out_ok, quote! { OKTOK }); + + // EmitResult Err → ToTokens + let err: EmitResult<()> = EmitResult::err( + quote! { ERRTOK }, + syn::Error::new(proc_macro2::Span::call_site(), "x"), + ); + let mut out_err = TokenStream::new(); + err.to_tokens(&mut out_err); + assert_ts_eq!(&out_err, quote! { ERRTOK }); + } + + #[xtest] + fn fatal_emit_conversion() { + // Ok path -> Ok + let ok: EmitResult = EmitResult::ok(quote! { TT }, 9); + let ok_conv: Result = ok.into(); + assert_eq!(ok_conv.unwrap(), 9); + + // Err path -> Err(FatalEmit) + let err: EmitResult<()> = + EmitResult::err(quote! { FOO }, darling::Error::unknown_field("bar")); + let err_conv: Result<(), FatalEmit> = err.into(); + let fe = err_conv.expect_err("should be error"); + assert_ts_eq!(&fe.tokens, quote! { FOO }); + // also check error converts both ways + let _syn_err: syn::Error = fe.error.clone().into(); + let _dar_err: darling::Error = fe.error.clone().into(); + } + + #[xtest] + fn restore_noop_when_empty() { + // If no checkpoints exist, restore/discard/pop_restore are no-ops + let mut b = EmitBuilder::new(); + b.extend(quote! { X }); + let _ = b.restore().discard_checkpoint().pop_restore(); + assert_ts_eq!(b, quote! { X }); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs index 8661f225..55fa70e7 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/mod.rs @@ -1,3 +1,4 @@ +pub mod emit; pub mod tokens; use proc_macro2::TokenStream as MacroStream; From 6f2e5fbade64db837dad9f4ab6d9885d3b685e5f Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 28 Oct 2025 19:21:13 -0400 Subject: [PATCH 138/162] refactor(codegen): remove `#[must_use]` on several methods --- .../src/codegen/emit.rs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs index 89f312d5..816f74bc 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -30,14 +30,12 @@ impl EmitBuilder { } /// Push the current tokens as a checkpoint. - #[must_use] pub(crate) fn push_checkpoint(&mut self) -> &mut Self { self.checkpoints.push(self.tokens.clone()); self } /// Restore to the last checkpoint. No-op if empty. - #[must_use] pub(crate) fn restore(&mut self) -> &mut Self { if let Some(cp) = self.checkpoints.last() { self.tokens = cp.clone(); @@ -46,7 +44,6 @@ impl EmitBuilder { } /// Restore to the last checkpoint and **pop** it. No-op if empty. - #[must_use] pub(crate) fn pop_restore(&mut self) -> &mut Self { if let Some(cp) = self.checkpoints.pop() { self.tokens = cp; @@ -55,7 +52,6 @@ impl EmitBuilder { } /// Discard the last checkpoint (keep current tokens). No-op if empty. - #[must_use] pub(crate) fn discard_checkpoint(&mut self) -> &mut Self { self.checkpoints.pop(); self @@ -77,7 +73,6 @@ impl EmitBuilder { } /// Try a phase with automatic checkpointing. - #[must_use] pub(crate) fn try_phase(&mut self, f: impl FnOnce(&mut Self) -> Result<(), E>) -> &mut Self where EmitError: From, @@ -88,6 +83,7 @@ impl EmitBuilder { } } + #[must_use] pub(crate) fn take_tokens(&mut self) -> TokenStream { std::mem::take(&mut self.tokens) } @@ -95,6 +91,10 @@ impl EmitBuilder { pub(crate) fn tokens(&self) -> &TokenStream { &self.tokens } + + pub(crate) fn tokens_mut(&mut self) -> &mut TokenStream { + &mut self.tokens + } } impl std::ops::Deref for EmitBuilder { @@ -249,22 +249,22 @@ mod tests { assert_ts_eq!(&b, quote! { base }); // push + modify + restore (non-pop) should revert to base but leave checkpoint on stack - let _ = b.push_checkpoint().extend(quote! { X }).restore(); + b.push_checkpoint().extend(quote! { X }).restore(); assert_ts_eq!(&b, quote! { base }); // modify again then pop_restore should also revert to base *and* pop the checkpoint - let _ = b.extend(quote! { TEMP }).pop_restore(); + b.extend(quote! { TEMP }).pop_restore(); assert_ts_eq!(&b, quote! { base }); // push + modify + discard should keep the modified result - let _ = b.push_checkpoint().extend(quote! { KEEP }).discard_checkpoint(); + b.push_checkpoint().extend(quote! { KEEP }).discard_checkpoint(); assert_ts_eq!(&b, quote! { base KEEP }); } #[xtest] fn try_phase_ok_keeps_changes() { let mut b = EmitBuilder::from_checkpoint(quote! { init }); - let _ = b.try_phase(|b| { + b.try_phase(|b| { // phase mutates tokens b.extend(quote! { ok1 ok2 }); Ok::<_, syn::Error>(()) @@ -275,7 +275,7 @@ mod tests { #[xtest] fn try_phase_err_restores_checkpoint() { let mut b = EmitBuilder::from_checkpoint(quote! { start }); - let _ = b.try_phase(|b| { + b.try_phase(|b| { // mutate then fail; should revert to checkpoint b.extend(quote! { broken }); Err::<(), _>(syn::Error::new(proc_macro2::Span::call_site(), "boom")) @@ -414,7 +414,7 @@ mod tests { // If no checkpoints exist, restore/discard/pop_restore are no-ops let mut b = EmitBuilder::new(); b.extend(quote! { X }); - let _ = b.restore().discard_checkpoint().pop_restore(); + b.restore().discard_checkpoint().pop_restore(); assert_ts_eq!(b, quote! { X }); } } From 0e5cfb2622b096b354add5c74ea7e3dfdda991c7 Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 28 Oct 2025 19:29:18 -0400 Subject: [PATCH 139/162] refactor(auto_plugin): simplify `auto_configure_system_set` by removing redundant closure and streamlining entry selection logic --- .../actions/auto_configure_system_set.rs | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 2dee71a5..15c3aafe 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -376,35 +376,34 @@ pub fn inflate_args_from_input( let observed = *observed_order_by_variant.entry(v_ident.clone()).or_insert_with(|| prev_observed_len); - let chosen_entry = (|| { + let chosen_entry = { let bucket = variants_cfg.get(&v_ident); // prefer explicit group match if let (Some(g), Some(b)) = (&outer_group, bucket) && let Some(found) = b.per_group.get(g) { - return Some(found.clone()); + found.clone() } - // else use the default helper but override its group to the outer group - if let Some(b) = bucket + else if let Some(b) = bucket && let Some(mut def) = b.default.clone() { def.group = outer_group.clone(); if def.order.is_none() { def.order = Some(observed); } - return Some(def); + def } - // else synthesize a default entry - Some(ConfigureSystemSetArgsInnerEntry { - group: outer_group.clone(), - order: Some(observed), - ..Default::default() - }) - })() - .expect("infallible"); + else { + ConfigureSystemSetArgsInnerEntry { + group: outer_group.clone(), + order: Some(observed), + ..Default::default() + } + } + }; entries.push((v_ident, chosen_entry)); } From 105b76fa4d2e0cb61eb740dded58f76a65464a52 Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 12:45:27 -0400 Subject: [PATCH 140/162] refactor(codegen): rework `EmitResult` and `Ctx` API --- .../src/codegen/emit.rs | 258 ++++++++---------- 1 file changed, 112 insertions(+), 146 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs index 816f74bc..d714f6ba 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + use proc_macro2::TokenStream; use quote::ToTokens; @@ -58,31 +60,29 @@ impl EmitBuilder { } /// Finish successfully. - pub(crate) fn into_ok(self, value: T) -> EmitResult { - EmitResult::Ok { tokens: self.tokens, value } + pub(crate) fn into_ok(self, value: T) -> EmitResult { + Ok((self.tokens, value)) } /// Finish with an error; emits the **last checkpoint** if any, else current tokens. - pub(crate) fn into_err(self, err: E) -> EmitResult - where - EmitError: From, - { + pub(crate) fn into_err(self, err: E) -> EmitResult { let fallback = if let Some(cp) = self.checkpoints.last() { cp.clone() } else { self.tokens.clone() }; - EmitResult::Err { tokens: fallback, error: err.into() } + Err((fallback, err)) } /// Try a phase with automatic checkpointing. - pub(crate) fn try_phase(&mut self, f: impl FnOnce(&mut Self) -> Result<(), E>) -> &mut Self - where - EmitError: From, - { + pub(crate) fn try_phase(&mut self, f: impl FnOnce(&mut Self) -> Result<(), E>) -> &mut Self { match f(self.push_checkpoint()) { Ok(()) => self.discard_checkpoint(), - Err(_e) => self.pop_restore(), + Err(_) => self.pop_restore(), } } + pub(crate) fn into_tokens(self) -> TokenStream { + self.tokens + } + #[must_use] pub(crate) fn take_tokens(&mut self) -> TokenStream { std::mem::take(&mut self.tokens) @@ -115,109 +115,120 @@ impl ToTokens for EmitBuilder { } } -#[derive(Debug, Clone, thiserror::Error)] -pub(crate) enum EmitError { - #[error("{0}")] - Syn(#[from] syn::Error), - #[error("{0}")] - Darling(#[from] darling::Error), -} +pub type EmitResult = Result<(TokenStream, T), (TokenStream, E)>; + +pub struct Ctx(pub TokenStream, pub T); -impl From for syn::Error { - fn from(e: EmitError) -> Self { - match e { - EmitError::Syn(s) => s, - EmitError::Darling(d) => d.into(), +impl Ctx { + pub fn and_then( + self, + f: impl FnOnce(&TokenStream, T) -> Result, + ) -> EmitResult { + let Ctx(ts, v) = self; + match f(&ts, v) { + Ok(u) => Ok((ts, u)), + Err(e) => Err((ts, e)), } } } -impl From for darling::Error { - fn from(e: EmitError) -> Self { - match e { - EmitError::Syn(s) => s.into(), - EmitError::Darling(d) => d, - } + +impl Ctx<()> { + pub fn start(ts: TokenStream) -> Ctx<()> { + Ctx(ts, ()) } } -#[derive(Debug, Clone)] -pub(crate) enum EmitResult { - Ok { tokens: TokenStream, value: T }, - Err { tokens: TokenStream, error: EmitError }, +pub trait WithTs { + type Output; + fn with_ts(self, ts: TokenStream) -> Self::Output; } -impl EmitResult { - pub fn ok(tokens: TokenStream, value: T) -> Self { - Self::Ok { tokens, value } - } - pub fn err(tokens: TokenStream, error: impl Into) -> Self { - Self::Err { tokens, error: error.into() } +impl WithTs for Result { + type Output = EmitResult; + #[inline] + fn with_ts(self, ts: TokenStream) -> Self::Output { + self.map(|v| (ts.clone(), v)).map_err(|e| (ts.clone(), e)) } +} - pub fn is_ok(&self) -> bool { - matches!(self, Self::Ok { .. }) - } - pub fn is_err(&self) -> bool { - !self.is_ok() +pub trait WithTsError { + type Output; + fn with_ts_on_err(self, ts: TokenStream) -> Self::Output; +} + +impl WithTsError for Result { + type Output = Result; + #[inline] + fn with_ts_on_err(self, ts: TokenStream) -> Self::Output { + self.map_err(|e| (ts.clone(), e)) } +} + +pub trait EmitResultExt { + fn split(self) -> (TokenStream, Result); + fn join((ts, res): (TokenStream, Result)) -> EmitResult { + res.with_ts(ts) + } + fn into_tokens(self) -> TokenStream; + fn tokens(&self) -> &TokenStream; + fn map_inner(self, f: impl FnOnce(T) -> U) -> EmitResult; + fn map_inner_err(self, f: impl FnOnce(E) -> U) -> EmitResult; + fn strip_err_tokens(self) -> Result<(TokenStream, T), E>; + fn strip_ok_tokens(self) -> Result; +} - pub fn map(self, f: impl FnOnce(T) -> U) -> EmitResult { +impl EmitResultExt for EmitResult { + #[inline] + fn split(self) -> (TokenStream, Result) { match self { - Self::Ok { tokens, value } => EmitResult::Ok { tokens, value: f(value) }, - Self::Err { tokens, error } => EmitResult::Err { tokens, error }, + Ok((ts, v)) => (ts, Ok(v)), + Err((ts, e)) => (ts, Err(e)), } } - pub fn map_err(self, f: impl FnOnce(EmitError) -> EmitError) -> Self { + + #[inline] + fn into_tokens(self) -> TokenStream { match self { - Self::Err { tokens, error } => Self::Err { tokens, error: f(error) }, - ok => ok, + Ok((ts, _)) => ts, + Err((ts, _)) => ts, } } - /// Split into tokens and a plain `Result`. - pub fn split(self) -> (TokenStream, Result) { + #[inline] + fn tokens(&self) -> &TokenStream { match self { - Self::Ok { tokens, value } => (tokens, Ok(value)), - Self::Err { tokens, error } => (tokens, Err(error)), + Ok((ts, _)) => ts, + Err((ts, _)) => ts, } } -} -impl From> for syn::Result { - fn from(v: EmitResult) -> Self { - match v { - EmitResult::Ok { value, .. } => Ok(value), - EmitResult::Err { error, .. } => Err(error.into()), - } + #[inline] + fn map_inner(self, f: impl FnOnce(T) -> U) -> EmitResult { + self.and_then(|(ts, v)| Ok(f(v)).with_ts(ts)) } -} -impl From> for darling::Result { - fn from(v: EmitResult) -> Self { - match v { - EmitResult::Ok { value, .. } => Ok(value), - EmitResult::Err { error, .. } => Err(error.into()), - } + + #[inline] + fn map_inner_err(self, f: impl FnOnce(E) -> U) -> EmitResult { + self.or_else(|(ts, e)| Err(f(e)).with_ts(ts)) } -} -impl ToTokens for EmitResult { - fn to_tokens(&self, out: &mut TokenStream) { - let ts = match self { - EmitResult::Ok { tokens, .. } | EmitResult::Err { tokens, .. } => tokens, - }; - out.extend(ts.clone()); + + #[inline] + fn strip_err_tokens(self) -> Result<(TokenStream, T), E> { + self.map_err(|(_, e)| e) } -} -#[derive(Debug)] -pub(crate) struct FatalEmit { - pub tokens: TokenStream, - pub error: EmitError, + #[inline] + fn strip_ok_tokens(self) -> Result { + self.map(|(_, v)| v) + } } -impl From> for Result { - fn from(v: EmitResult) -> Self { - match v { - EmitResult::Ok { value, .. } => Ok(value), - EmitResult::Err { tokens, error } => Err(FatalEmit { tokens, error }), + +pub type CtxOnly = Ctx<()>; +impl From> for CtxOnly { + fn from(value: EmitResult) -> Self { + match value { + Ok((ts, _)) => Ctx(ts, ()), + Err((ts, _)) => Ctx(ts, ()), } } } @@ -291,9 +302,9 @@ mod tests { b.extend(quote! { work }); b }; - let ok: EmitResult = b1.into_ok(42); + let ok: EmitResult = b1.into_ok(42); match ok { - EmitResult::Ok { tokens, value } => { + Ok((tokens, value)) => { assert_eq!(value, 42); assert_ts_eq!(&tokens, quote! { cp work }); } @@ -306,40 +317,22 @@ mod tests { b.extend(quote! { work }); b }; - let err: EmitResult<()> = + let err: EmitResult<(), _> = b2.into_err(syn::Error::new(proc_macro2::Span::call_site(), "nope")); match err { - EmitResult::Err { tokens, error } => { - let _: syn::Error = error.clone().into(); // convertible + Err((tokens, error)) => { + let _: syn::Error = error.clone().into(); assert_ts_eq!(&tokens, quote! { cp }); } _ => panic!("expected Err"), } } - #[xtest] - fn result_conversions_to_syn_and_darling() { - // Ok path -> Ok(_) - let ok: EmitResult<&'static str> = EmitResult::ok(quote! { t }, "v"); - let syn_ok: syn::Result<_> = ok.clone().into(); - let dar_ok: darling::Result<_> = ok.into(); - assert!(syn_ok.is_ok()); - assert!(dar_ok.is_ok()); - - // Err path -> Err(_) - let e = syn::Error::new(proc_macro2::Span::call_site(), "bad"); - let err: EmitResult<()> = EmitResult::err(quote! { t }, e); - let syn_err: syn::Result<()> = err.clone().into(); - let dar_err: darling::Result<()> = err.into(); - assert!(syn_err.is_err()); - assert!(dar_err.is_err()); - } - #[xtest] fn result_split_and_map() { // split ok { - let ok: EmitResult = EmitResult::ok(quote! { T }, 5); + let ok: EmitResult = Ok((quote! { T }, 5)); let (ts, res) = ok.split(); assert_ts_eq!(&ts, quote! { T }); assert_eq!(res.unwrap(), 5); @@ -347,8 +340,8 @@ mod tests { // map { - let ok: EmitResult<&'static str> = EmitResult::ok(quote! { U }, "abc"); - let mapped = ok.map(|s| s.len()); + let ok: EmitResult<&'static str, ()> = Ok((quote! { U }, "abc")); + let mapped = ok.map(|(ts, s)| (ts, s.len())); let (ts, res) = mapped.split(); assert_ts_eq!(ts, quote! { U }); assert_eq!(res.unwrap(), 3); @@ -356,10 +349,8 @@ mod tests { // split err { - let err: EmitResult<()> = EmitResult::err( - quote! { E }, - syn::Error::new(proc_macro2::Span::call_site(), "nope"), - ); + let err: EmitResult<(), _> = + Err((quote! { E }, syn::Error::new(proc_macro2::Span::call_site(), "nope"))); let (ts, res) = err.split(); assert_ts_eq!(&ts, quote! { E }); assert!(res.is_err()); @@ -376,39 +367,14 @@ mod tests { assert_ts_eq!(&out, quote! { a b c }); // EmitResult Ok → ToTokens - let ok: EmitResult<()> = EmitResult::ok(quote! { OKTOK }, ()); - let mut out_ok = TokenStream::new(); - ok.to_tokens(&mut out_ok); - assert_ts_eq!(&out_ok, quote! { OKTOK }); + let ok: EmitResult<(), ()> = Ok((quote! { OKTOK }, ())); + assert_ts_eq!(ok.tokens(), quote! { OKTOK }); // EmitResult Err → ToTokens - let err: EmitResult<()> = EmitResult::err( - quote! { ERRTOK }, - syn::Error::new(proc_macro2::Span::call_site(), "x"), - ); - let mut out_err = TokenStream::new(); - err.to_tokens(&mut out_err); - assert_ts_eq!(&out_err, quote! { ERRTOK }); + let err: EmitResult<(), _> = + Err((quote! { ERRTOK }, syn::Error::new(proc_macro2::Span::call_site(), "x"))); + assert_ts_eq!(err.into_tokens(), quote! { ERRTOK }); } - - #[xtest] - fn fatal_emit_conversion() { - // Ok path -> Ok - let ok: EmitResult = EmitResult::ok(quote! { TT }, 9); - let ok_conv: Result = ok.into(); - assert_eq!(ok_conv.unwrap(), 9); - - // Err path -> Err(FatalEmit) - let err: EmitResult<()> = - EmitResult::err(quote! { FOO }, darling::Error::unknown_field("bar")); - let err_conv: Result<(), FatalEmit> = err.into(); - let fe = err_conv.expect_err("should be error"); - assert_ts_eq!(&fe.tokens, quote! { FOO }); - // also check error converts both ways - let _syn_err: syn::Error = fe.error.clone().into(); - let _dar_err: darling::Error = fe.error.clone().into(); - } - #[xtest] fn restore_noop_when_empty() { // If no checkpoints exist, restore/discard/pop_restore are no-ops From d42d8275dd347bc6bbe2bb05f1e7647f08092b62 Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 12:45:45 -0400 Subject: [PATCH 141/162] refactor(macro_api): enhance error handling in `item_post_process` and related APIs with `EmitResult` integration --- .../src/__private/expand/attr/action.rs | 8 +- .../actions/auto_configure_system_set.rs | 74 ++++++++++--------- .../src/macro_api/emitters/app_mutation.rs | 2 +- .../src/syntax/parse/scrub_helpers.rs | 63 ++++++++++++---- 4 files changed, 98 insertions(+), 49 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs index 3eefcb37..2c382762 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs @@ -25,7 +25,13 @@ where ); let mut app_mut_emitter = AppMutationEmitter::from_args(args); let processed_item = { - ok_or_emit_with!(app_mut_emitter.item_post_process(), app_mut_emitter.args.input_item()); + if let Err((tokens, err)) = app_mut_emitter.item_post_process() { + let err = err.to_compile_error(); + return quote! { + #err + #tokens + }; + } app_mut_emitter.args.input_item().to_token_stream() }; let after_item_tokens = diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 15c3aafe..3f9026fe 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,4 +1,9 @@ use crate::{ + codegen::emit::{ + EmitResult, + EmitResultExt, + WithTs, + }, macro_api::{ prelude::*, schedule_config::{ @@ -34,6 +39,7 @@ use syn::{ parse_quote, spanned::Spanned, }; + const CONFIG_ATTR_NAME: &str = "auto_configure_system_set_config"; const CHAIN_CONFLICT_ERR: &str = "`chain` and `chain_ignore_deferred` are mutually exclusive"; @@ -178,16 +184,16 @@ fn output( } impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { - fn item_post_process(&mut self) -> syn::Result<()> { + fn item_post_process(&mut self) -> Result<(), (TokenStream, syn::Error)> { let input_item = &mut self.args.input_item; let args = &mut self.args.args.base; - let item = input_item.ensure_ast()?; - check_strip_helpers(item, args)?; + let input = input_item.to_token_stream(); + let (input, item) = input_item.ensure_ast().with_ts(input)?; + check_strip_helpers(item, args).with_ts(input.clone())?; if args.inner.is_none() { - let input = input_item.to_token_stream(); - let res = inflate_args_from_input(args.clone(), input)?; - *args = res.inflated_args; - *input_item = InputItem::Tokens(res.scrubbed_tokens); + let (input, inflated_args) = inflate_args_from_input(args.clone(), input)?; + *args = inflated_args; + *input_item = InputItem::Tokens(input); } Ok(()) } @@ -198,8 +204,8 @@ impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { let args = args.clone(); let input = self.args.input_item.to_token_stream(); match inflate_args_from_input(args, input) { - Ok(res) => res.inflated_args, - Err(err) => { + Ok((_, args)) => args, + Err((_, err)) => { tokens.extend(err.to_compile_error()); return; } @@ -239,23 +245,18 @@ fn check_strip_helpers(item: &Item, args: &mut ConfigureSystemSetArgs) -> syn::R pub fn args_from_attr_input( attr: TokenStream, input: TokenStream, -) -> syn::Result { - let mut args = syn::parse2::(attr)?; - let mut input_item = InputItem::Tokens(input); - check_strip_helpers(input_item.ensure_ast()?, &mut args)?; +) -> EmitResult { + let (input, mut args) = syn::parse2::(attr).with_ts(input.clone())?; + let mut input_item = InputItem::Tokens(input.clone()); + let (input, item) = input_item.ensure_ast().with_ts(input)?; + check_strip_helpers(item, &mut args).with_ts(input)?; inflate_args_from_input(args, input_item.to_token_stream()) } -#[derive(Debug)] -pub struct InflateArgsOutput { - scrubbed_tokens: TokenStream, - inflated_args: ConfigureSystemSetArgs, -} - pub fn inflate_args_from_input( mut args: ConfigureSystemSetArgs, input: TokenStream, -) -> syn::Result { +) -> EmitResult { fn resolve_ident(item: &Item) -> syn::Result<&Ident> { // TODO: remove and use ident from higher level? item.ident() @@ -268,7 +269,7 @@ pub fn inflate_args_from_input( let mut scrubbed_tokens = input.clone(); // 2) Scrub helpers from the item and resolve ident - let scrub = scrub_helpers_and_ident_with_filter( + let (input, scrub) = scrub_helpers_and_ident_with_filter( input, is_allowed_helper, is_config_helper, @@ -278,17 +279,17 @@ pub fn inflate_args_from_input( // 3) if args._strip_helpers { // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with - scrub.replace_token_stream(&mut scrubbed_tokens)?; + scrub.replace_token_stream(&mut scrubbed_tokens).with_ts(input.clone())?; } else { // Check if we have errors to print and if so, strip helpers from the item // Otherwise, maintain helpers for the next attribute to process - scrub.prepend_errors(&mut scrubbed_tokens)?; + scrub.prepend_errors(&mut scrubbed_tokens).with_ts(input.clone())?; } // 4) If it's a struct, there are no entries to compute let data_enum = match scrub.item { Item::Struct(_) => { - return Ok(InflateArgsOutput { inflated_args: args, scrubbed_tokens }); + return Ok(args).with_ts(scrubbed_tokens); } Item::Enum(ref en) => en, _ => unreachable!("resolve_ident_from_struct_or_enum guarantees struct|enum"), @@ -325,7 +326,10 @@ pub fn inflate_args_from_input( continue; } - let mut entry = ConfigureSystemSetArgsInnerEntry::from_meta(&attr.meta)?; + let mut entry = ConfigureSystemSetArgsInnerEntry::from_meta(&attr.meta) + .map_err(syn::Error::from) + .with_ts(scrubbed_tokens.clone()) + .strip_ok_tokens()?; // If order wasn't provided on the helper, set it to the first observed index for this variant if entry.order.is_none() { @@ -340,7 +344,7 @@ pub fn inflate_args_from_input( return Err(syn::Error::new( attr.span(), format!("duplicate helper for variant `{variant}` and group `{g}`",), - )); + )).with_ts(scrubbed_tokens.clone()); } bucket.per_group.insert(g.clone(), entry); } @@ -351,7 +355,8 @@ pub fn inflate_args_from_input( format!( "duplicate default (no-group) helper for variant `{variant}`", ), - )); + )) + .with_ts(scrubbed_tokens.clone()); } bucket.default = Some(entry); } @@ -421,12 +426,13 @@ pub fn inflate_args_from_input( // 8) Store into args and return args.inner = Some(ConfigureSystemSetArgsInner { entries }); - Ok(InflateArgsOutput { inflated_args: args, scrubbed_tokens }) + Ok(args).with_ts(scrubbed_tokens) } #[cfg(test)] mod tests { use super::*; + use crate::codegen::emit::EmitResultExt; use internal_test_proc_macro::xtest; use syn::{ Path, @@ -438,9 +444,9 @@ mod tests { attr: TokenStream, input: TokenStream, ) -> Result<(Ident, ConfigureSystemSetArgs), syn::Error> { - let mut input_item = InputItem::Tokens(input); + let mut input_item = InputItem::Tokens(input.clone()); let ident = input_item.ident()?.clone(); - let inflated_args = args_from_attr_input(attr, input_item.to_token_stream())?.inflated_args; + let (_, inflated_args) = args_from_attr_input(attr, input.clone()).strip_err_tokens()?; Ok((ident, inflated_args)) } @@ -581,7 +587,7 @@ mod tests { #[xtest] fn test_helper() -> syn::Result<()> { - let inflated_args = args_from_attr_input( + let (_, inflated_args) = args_from_attr_input( quote! { group = A, schedule = Update, @@ -594,8 +600,8 @@ mod tests { B, } }, - )? - .inflated_args; + ) + .strip_err_tokens()?; assert_eq!( inflated_args, ConfigureSystemSetArgs { @@ -646,7 +652,7 @@ mod tests { B, } }; - let scrubbed_input = args_from_attr_input(attr, input)?.scrubbed_tokens; + let (scrubbed_input, _) = args_from_attr_input(attr, input).strip_err_tokens()?; assert_eq!( scrubbed_input.to_string(), quote! { diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs index 29741b73..790c7041 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs @@ -52,7 +52,7 @@ impl AppMutationEmitter { pub trait EmitAppMutationTokens { // TODO: this should be its own thing but it might overcomplicate things - fn item_post_process(&mut self) -> syn::Result<()> { + fn item_post_process(&mut self) -> Result<(), (TokenStream, syn::Error)> { Ok(()) } fn to_app_mutation_token_stream(&self, app_param: &syn::Ident) -> TokenStream { diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index 04ab46c6..622622b6 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -1,5 +1,11 @@ #![allow(dead_code)] -use crate::syntax::extensions::item::ItemAttrsExt; +use crate::{ + codegen::emit::{ + EmitResult, + WithTsError, + }, + syntax::extensions::item::ItemAttrsExt, +}; use darling::FromMeta; use proc_macro2::TokenStream; use quote::{ @@ -176,6 +182,19 @@ impl ScrubOutcome { } } +impl ToTokens for ScrubOutcome { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.item.to_tokens(tokens); + } +} + +impl From for EmitResult { + fn from(value: ScrubOutcome) -> Self { + // TODO: do we return Err if errors are present? + Ok((value.item.to_token_stream(), value)) + } +} + /// Writes errors to the token stream if they exist, otherwise doesn't modify the token stream. /// /// # Arguments @@ -394,18 +413,18 @@ pub fn scrub_helpers_and_ident( input: proc_macro2::TokenStream, is_helper: fn(&Attribute) -> bool, resolve_ident: fn(&Item) -> syn::Result<&Ident>, -) -> syn::Result { +) -> EmitResult { scrub_helpers_and_ident_with_filter(input, |_, _| true, is_helper, resolve_ident) } pub fn scrub_helpers_and_ident_with_filter( - input: proc_macro2::TokenStream, + input: TokenStream, is_site_allowed: fn(&AttrSite, &Attribute) -> bool, is_helper: fn(&Attribute) -> bool, resolve_ident: fn(&Item) -> syn::Result<&Ident>, -) -> syn::Result { - let mut item: Item = syn::parse2(input)?; - let ident = resolve_ident(&item)?.clone(); +) -> EmitResult { + let mut item = syn::parse2::(input.clone()).with_ts_on_err(input.clone())?; + let ident = resolve_ident(&item).cloned().with_ts_on_err(input.clone())?; let mut scrubber = Scrubber { is_helper, out: ScrubberOut::default(), errors: vec![] }; scrubber.visit_item_mut(&mut item); @@ -429,13 +448,25 @@ pub fn scrub_helpers_and_ident_with_filter( } } - Ok(ScrubOutcome { + // TODO: check for errors? + // check for errors + // if let Some(err) = scrubber.errors.pop() { + // let err = scrubber.errors.into_iter().fold(err, |mut acc, err| { + // acc.combine(err); + // acc + // }); + // return Err((item.to_token_stream(), err)); + // } + + let scrub = ScrubOutcome { item, ident, observed: scrubber.out.observed, removed: scrubber.out.removed, errors: scrubber.errors, - }) + }; + + scrub.into() } // Parse removed helpers into `T` @@ -511,6 +542,7 @@ mod tests { mod scrub_helpers_and_ident { use super::*; + use crate::codegen::emit::EmitResultExt; #[inline] fn assert_no_errors(scrub_outcome: &ScrubOutcome) { assert_eq!( @@ -551,7 +583,8 @@ mod tests { z: i32, } }; - let scrub_outcome = scrub_helpers_and_ident(input, is_helper, resolve_ident)?; + let (_input, scrub_outcome) = + scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; assert_no_errors(&scrub_outcome); assert_ident(&scrub_outcome, "Foo"); assert_no_helpers_remain_on_item(&scrub_outcome); @@ -593,7 +626,8 @@ mod tests { C, } }; - let scrub_outcome = scrub_helpers_and_ident(input, is_helper, resolve_ident)?; + let (_input, scrub_outcome) = + scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; assert_no_errors(&scrub_outcome); assert_ident(&scrub_outcome, "Foo"); assert_no_helpers_remain_on_item(&scrub_outcome); @@ -642,7 +676,8 @@ mod tests { Y, } }; - let scrub_outcome = scrub_helpers_and_ident(input, is_helper, resolve_ident)?; + let (_input, scrub_outcome) = + scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; assert_no_errors(&scrub_outcome); assert_ident(&scrub_outcome, "Foo"); assert_no_helpers_remain_on_item(&scrub_outcome); @@ -684,7 +719,8 @@ mod tests { C, } }; - let scrub_outcome = scrub_helpers_and_ident(input, is_helper, resolve_ident)?; + let (_input, scrub_outcome) = + scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; assert_no_errors(&scrub_outcome); assert_ident(&scrub_outcome, "Foo"); assert_no_helpers_remain_on_item(&scrub_outcome); @@ -732,7 +768,8 @@ mod tests { } }; - let scrub_outcome = scrub_helpers_and_ident(input, is_helper, resolve_ident)?; + let (_input, scrub_outcome) = + scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; let got = SiteAttrsVec::from_vec(scrub_outcome.all_with_removed_attrs()); let expected = SiteAttrsVec::from_vec(vec![ From 1ff49623072c707c582160f1a4e45d0bb359d425 Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 14:39:37 -0400 Subject: [PATCH 142/162] feat(internal_test_util): implement custom `Debug` trait for `Ts` --- crates/internal_test_util/src/token_stream.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/internal_test_util/src/token_stream.rs b/crates/internal_test_util/src/token_stream.rs index fc4e3bc5..597fad55 100644 --- a/crates/internal_test_util/src/token_stream.rs +++ b/crates/internal_test_util/src/token_stream.rs @@ -2,10 +2,19 @@ use proc_macro2::TokenStream; use quote::ToTokens; +use std::fmt::{ + Debug, + Formatter, +}; -#[derive(Debug)] pub struct Ts(TokenStream); +impl Debug for Ts { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(&self.0.to_string()) + } +} + impl PartialEq for Ts { fn eq(&self, other: &Self) -> bool { self.0.to_string() == other.0.to_string() From 187157787d9bc9c24b353949dfbdab107dd1f3d1 Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 15:36:37 -0400 Subject: [PATCH 143/162] feat(internal_test_util): add `token_string` utility function to `token_stream.rs` --- crates/internal_test_util/src/token_stream.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/internal_test_util/src/token_stream.rs b/crates/internal_test_util/src/token_stream.rs index 597fad55..daefb686 100644 --- a/crates/internal_test_util/src/token_stream.rs +++ b/crates/internal_test_util/src/token_stream.rs @@ -7,6 +7,11 @@ use std::fmt::{ Formatter, }; +#[inline] +pub fn token_string(ts: impl ToTokens) -> String { + ts.to_token_stream().to_string() +} + pub struct Ts(TokenStream); impl Debug for Ts { From 4d93e2e63d771a70800a5a682c330858d49a57ec Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 15:36:44 -0400 Subject: [PATCH 144/162] feat(internal_test_util): mark `Ts` struct with `#[repr(transparent)]` --- crates/internal_test_util/src/token_stream.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/internal_test_util/src/token_stream.rs b/crates/internal_test_util/src/token_stream.rs index daefb686..4d4af448 100644 --- a/crates/internal_test_util/src/token_stream.rs +++ b/crates/internal_test_util/src/token_stream.rs @@ -12,6 +12,7 @@ pub fn token_string(ts: impl ToTokens) -> String { ts.to_token_stream().to_string() } +#[repr(transparent)] pub struct Ts(TokenStream); impl Debug for Ts { From 2a371cbba3f68e84621aba468cc54dac860a857c Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 15:37:03 -0400 Subject: [PATCH 145/162] feat(codegen): add utility methods `ok`, `err`, `try_do`, and `try_unit` to `emit.rs` for streamlined error handling and checkpoint management --- .../src/codegen/emit.rs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs index d714f6ba..dfbfb8b8 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -79,6 +79,40 @@ impl EmitBuilder { } } + #[inline] + pub fn ok(&self, v: T) -> EmitResult { + Ok((self.tokens.clone(), v)) + } + #[inline] + pub fn err(&self, e: E) -> EmitResult { + Err((self.tokens.clone(), e)) + } + + /// Same as `try_phase` but returns `EmitResult` for easy `?` usage + pub(crate) fn try_do( + &mut self, + f: impl FnOnce(&mut Self) -> Result, + ) -> EmitResult { + self.push_checkpoint(); + match f(self) { + Ok(v) => { + self.discard_checkpoint(); + self.ok(v) + } + Err(e) => { + self.pop_restore(); + self.err(e) + } + } + } + + pub(crate) fn try_unit( + &mut self, + f: impl FnOnce(&mut Self) -> Result<(), E>, + ) -> Result<(), (TokenStream, E)> { + self.try_do(f).strip_ok_tokens() + } + pub(crate) fn into_tokens(self) -> TokenStream { self.tokens } From 9811c177a87b80766be50742f0937d159a8d8410 Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 15:37:21 -0400 Subject: [PATCH 146/162] feat(codegen): add `map_err_tokens` method to `EmitResult` --- crates/bevy_auto_plugin_shared/src/codegen/emit.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs index dfbfb8b8..18e75f66 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -207,6 +207,10 @@ pub trait EmitResultExt { fn tokens(&self) -> &TokenStream; fn map_inner(self, f: impl FnOnce(T) -> U) -> EmitResult; fn map_inner_err(self, f: impl FnOnce(E) -> U) -> EmitResult; + fn map_err_tokens( + self, + f: impl FnOnce(TokenStream) -> U, + ) -> Result<(TokenStream, T), (U, E)>; fn strip_err_tokens(self) -> Result<(TokenStream, T), E>; fn strip_ok_tokens(self) -> Result; } @@ -246,6 +250,14 @@ impl EmitResultExt for EmitResult { self.or_else(|(ts, e)| Err(f(e)).with_ts(ts)) } + #[inline] + fn map_err_tokens( + self, + f: impl FnOnce(TokenStream) -> U, + ) -> Result<(TokenStream, T), (U, E)> { + self.map_err(|(ts, e)| (f(ts), e)) + } + #[inline] fn strip_err_tokens(self) -> Result<(TokenStream, T), E> { self.map_err(|(_, e)| e) From a3794c9012475fbb212795e543ea0254af730076 Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 15:37:31 -0400 Subject: [PATCH 147/162] chore(parse): add TODO for refactoring `ScrubOutcome` and `EmitResult` structure --- .../bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index 622622b6..1811bb1c 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -133,6 +133,8 @@ impl SiteAttrsVec { } pub struct ScrubOutcome { + // TODO: probably should be inside the EmitResult instead of here. + // But EmitResult should allow for `syn::Item` or `InputItem` as well as `TokenStream` to make sense /// scrubbed item (no helpers remain) pub item: Item, /// struct/enum ident From 348ea6681f6d04c3711b4ac0a17b73f3c5123c8b Mon Sep 17 00:00:00 2001 From: bstriker Date: Wed, 29 Oct 2025 15:37:42 -0400 Subject: [PATCH 148/162] refactor(macro_api): integrate `EmitBuilder` into `auto_configure_system_set` for improved token management and error handling --- .../actions/auto_configure_system_set.rs | 144 +++++++++++------- 1 file changed, 88 insertions(+), 56 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 3f9026fe..ffb8dba8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,5 +1,6 @@ use crate::{ codegen::emit::{ + EmitBuilder, EmitResult, EmitResultExt, WithTs, @@ -266,33 +267,41 @@ pub fn inflate_args_from_input( is_config_helper(attr) && matches!(site, AttrSite::Variant { .. }) } - let mut scrubbed_tokens = input.clone(); + let mut b = EmitBuilder::from_checkpoint(input); + // TODO: maybe we need a code path that doesn't strip - only analyze? // 2) Scrub helpers from the item and resolve ident - let (input, scrub) = scrub_helpers_and_ident_with_filter( - input, + let scrub = scrub_helpers_and_ident_with_filter( + b.to_token_stream(), is_allowed_helper, is_config_helper, resolve_ident, - )?; + ) + // TODO: this feels bad - see `ScrubOutcome#ident` todo + .strip_ok_tokens()?; // 3) - if args._strip_helpers { - // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with - scrub.replace_token_stream(&mut scrubbed_tokens).with_ts(input.clone())?; - } else { - // Check if we have errors to print and if so, strip helpers from the item - // Otherwise, maintain helpers for the next attribute to process - scrub.prepend_errors(&mut scrubbed_tokens).with_ts(input.clone())?; - } + b.try_unit(|b| { + if args._strip_helpers { + // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with + scrub.replace_token_stream(b) + } else { + // Check if we have errors to print and if so, strip helpers from the item + // Otherwise, maintain helpers for the next attribute to process + scrub.prepend_errors(b) + } + })?; // 4) If it's a struct, there are no entries to compute let data_enum = match scrub.item { Item::Struct(_) => { - return Ok(args).with_ts(scrubbed_tokens); + return b.into_ok(args); } Item::Enum(ref en) => en, - _ => unreachable!("resolve_ident_from_struct_or_enum guarantees struct|enum"), + _ => { + let err = syn::Error::new(scrub.item.span(), "Only struct or enum supported"); + return b.into_err(err); + } }; // 5) Collect per-variant configs: @@ -314,56 +323,55 @@ pub fn inflate_args_from_input( // Track the FIRST observed index we see for that variant. let mut observed_order_by_variant: HashMap = HashMap::new(); - // Parse all removed helper attrs (last-one-wins per key), but error on duplicates for the SAME key. - // Treat a second helper on the same (variant, group or None) as a hard error. - for (observed_index, site) in scrub.all_with_removed_attrs().into_iter().enumerate() { - if let AttrSite::Variant { variant } = &site.site { - observed_order_by_variant.entry(variant.clone()).or_insert(observed_index); - - for attr in &site.attrs { - // Only care about our helper - if !is_config_helper(attr) { - continue; - } + b.try_unit(|_| { + // Parse all removed helper attrs (last-one-wins per key), but error on duplicates for the SAME key. + // Treat a second helper on the same (variant, group or None) as a hard error. + for (observed_index, site) in scrub.all_with_removed_attrs().into_iter().enumerate() { + if let AttrSite::Variant { variant } = &site.site { + observed_order_by_variant.entry(variant.clone()).or_insert(observed_index); + + for attr in &site.attrs { + // Only care about our helper + if !is_config_helper(attr) { + continue; + } - let mut entry = ConfigureSystemSetArgsInnerEntry::from_meta(&attr.meta) - .map_err(syn::Error::from) - .with_ts(scrubbed_tokens.clone()) - .strip_ok_tokens()?; + let mut entry = ConfigureSystemSetArgsInnerEntry::from_meta(&attr.meta)?; - // If order wasn't provided on the helper, set it to the first observed index for this variant - if entry.order.is_none() { - entry.order = - Some(*observed_order_by_variant.get(variant).unwrap_or(&observed_index)); - } + // If order wasn't provided on the helper, set it to the first observed index for this variant + if entry.order.is_none() { + entry.order = + Some(*observed_order_by_variant.get(variant).unwrap_or(&observed_index)); + } - let bucket = variants_cfg.entry(variant.clone()).or_default(); - match &entry.group { - Some(g) => { - if bucket.per_group.contains_key(g) { - return Err(syn::Error::new( - attr.span(), - format!("duplicate helper for variant `{variant}` and group `{g}`",), - )).with_ts(scrubbed_tokens.clone()); + let bucket = variants_cfg.entry(variant.clone()).or_default(); + match &entry.group { + Some(g) => { + if bucket.per_group.contains_key(g) { + return Err(syn::Error::new( + attr.span(), + format!("duplicate helper for variant `{variant}` and group `{g}`", ), + )); + } + bucket.per_group.insert(g.clone(), entry); } - bucket.per_group.insert(g.clone(), entry); - } - None => { - if bucket.default.is_some() { - return Err(syn::Error::new( - attr.span(), - format!( - "duplicate default (no-group) helper for variant `{variant}`", - ), - )) - .with_ts(scrubbed_tokens.clone()); + None => { + if bucket.default.is_some() { + return Err(syn::Error::new( + attr.span(), + format!( + "duplicate default (no-group) helper for variant `{variant}`", + ), + )); + } + bucket.default = Some(entry); } - bucket.default = Some(entry); } } } } - } + Ok(()) + })?; // 6) Walk the enum variants and assemble entries using fallback rules: // chosen = per_group[outer_group] @@ -426,7 +434,7 @@ pub fn inflate_args_from_input( // 8) Store into args and return args.inner = Some(ConfigureSystemSetArgsInner { entries }); - Ok(args).with_ts(scrubbed_tokens) + Ok(args).with_ts(b.into_tokens()) } #[cfg(test)] @@ -510,6 +518,10 @@ mod tests { mod test_enum { use super::*; + use internal_test_util::{ + assert_ts_eq, + token_stream::token_string, + }; use quote::quote; #[xtest] @@ -701,5 +713,25 @@ mod tests { assert_eq!(res, Err(CHAIN_CONFLICT_ERR.into())); } + + #[xtest] + fn test_dont_strip_helpers_early() -> Result<(), (String, syn::Error)> { + let attr = quote! { group = A, schedule = Update }; + let input = quote! { + #[auto_configure_system_set(group = B, schedule = FixedUpdate)] + enum Foo { + #[auto_configure_system_set_config(group = A, config(run_if = always))] + #[auto_configure_system_set_config(group = B, config(run_if = never))] + A, + } + }; + let (tokens, args) = + args_from_attr_input(attr, input.clone()).map_err_tokens(token_string)?; + + assert!(!args._strip_helpers); + assert_ts_eq!(tokens, input); + + Ok(()) + } } } From b7f7a31131b445c6a1a213116a3508cc150ca04f Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 30 Oct 2025 16:06:06 -0400 Subject: [PATCH 149/162] refactor(codegen): update `try_phase` and related functions to improve error handling and include token context in error propagation --- .../src/codegen/emit.rs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs index 18e75f66..0eb874ef 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -72,10 +72,16 @@ impl EmitBuilder { } /// Try a phase with automatic checkpointing. - pub(crate) fn try_phase(&mut self, f: impl FnOnce(&mut Self) -> Result<(), E>) -> &mut Self { + pub(crate) fn try_phase( + &mut self, + f: impl FnOnce(&mut Self) -> Result<(), E>, + ) -> Result<&mut Self, (TokenStream, E)> { match f(self.push_checkpoint()) { - Ok(()) => self.discard_checkpoint(), - Err(_) => self.pop_restore(), + Ok(()) => Ok(self.discard_checkpoint()), + Err(e) => { + self.pop_restore(); + Err((self.to_token_stream(), e)) + } } } @@ -91,7 +97,7 @@ impl EmitBuilder { /// Same as `try_phase` but returns `EmitResult` for easy `?` usage pub(crate) fn try_do( &mut self, - f: impl FnOnce(&mut Self) -> Result, + f: impl FnOnce(&mut Self) -> Result, ) -> EmitResult { self.push_checkpoint(); match f(self) { @@ -99,7 +105,7 @@ impl EmitBuilder { self.discard_checkpoint(); self.ok(v) } - Err(e) => { + Err((_, e)) => { self.pop_restore(); self.err(e) } @@ -110,7 +116,7 @@ impl EmitBuilder { &mut self, f: impl FnOnce(&mut Self) -> Result<(), E>, ) -> Result<(), (TokenStream, E)> { - self.try_do(f).strip_ok_tokens() + self.try_do(|b| f(b).map_err(|e| (b.to_token_stream(), e))).strip_ok_tokens() } pub(crate) fn into_tokens(self) -> TokenStream { @@ -321,7 +327,7 @@ mod tests { #[xtest] fn try_phase_ok_keeps_changes() { let mut b = EmitBuilder::from_checkpoint(quote! { init }); - b.try_phase(|b| { + let _ = b.try_phase(|b| { // phase mutates tokens b.extend(quote! { ok1 ok2 }); Ok::<_, syn::Error>(()) @@ -332,7 +338,7 @@ mod tests { #[xtest] fn try_phase_err_restores_checkpoint() { let mut b = EmitBuilder::from_checkpoint(quote! { start }); - b.try_phase(|b| { + let _ = b.try_phase(|b| { // mutate then fail; should revert to checkpoint b.extend(quote! { broken }); Err::<(), _>(syn::Error::new(proc_macro2::Span::call_site(), "boom")) From 230b4cfe49413821be9311bf2f11fb485c15ac2b Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 30 Oct 2025 16:06:42 -0400 Subject: [PATCH 150/162] refactor(macro_api): encapsulate scrubbing --- .../actions/auto_configure_system_set.rs | 49 +++++++++++-------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index ffb8dba8..f3ab1775 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -19,6 +19,7 @@ use crate::{ item::item_has_attr, scrub_helpers::{ AttrSite, + ScrubOutcome, scrub_helpers_and_ident_with_filter, }, }, @@ -269,28 +270,34 @@ pub fn inflate_args_from_input( let mut b = EmitBuilder::from_checkpoint(input); - // TODO: maybe we need a code path that doesn't strip - only analyze? // 2) Scrub helpers from the item and resolve ident - let scrub = scrub_helpers_and_ident_with_filter( - b.to_token_stream(), - is_allowed_helper, - is_config_helper, - resolve_ident, - ) - // TODO: this feels bad - see `ScrubOutcome#ident` todo - .strip_ok_tokens()?; - - // 3) - b.try_unit(|b| { - if args._strip_helpers { - // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with - scrub.replace_token_stream(b) - } else { - // Check if we have errors to print and if so, strip helpers from the item - // Otherwise, maintain helpers for the next attribute to process - scrub.prepend_errors(b) - } - })?; + let scrub = b + .try_do(|b| { + // TODO: maybe we need a code path that doesn't strip - only analyze? + let scrub = scrub_helpers_and_ident_with_filter( + b.to_token_stream(), + is_allowed_helper, + is_config_helper, + resolve_ident, + ) + // TODO: this feels bad - see `ScrubOutcome#ident` todo + .strip_ok_tokens()?; + + // 3) Determine if we are writing the scrubbed item back to *input* or just errors (if any) + b.try_unit(|b| { + if args._strip_helpers { + // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with + scrub.replace_token_stream(b) + } else { + // Check if we have errors to print and if so, strip helpers from the item + // Otherwise, maintain helpers for the next attribute to process + scrub.prepend_errors(b) + } + })?; + + Ok(scrub) + }) + .strip_ok_tokens()?; // 4) If it's a struct, there are no entries to compute let data_enum = match scrub.item { From d009b720cc27de89d67a7fea322f9f76c3bd2102 Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 30 Oct 2025 16:27:36 -0400 Subject: [PATCH 151/162] refactor(macro_api): breakup `auto_configure_system_set` `inflate_args_from_input` --- .../src/codegen/emit.rs | 1 + .../actions/auto_configure_system_set.rs | 369 +++++++++++------- 2 files changed, 222 insertions(+), 148 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs index 0eb874ef..3a1c794f 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -156,6 +156,7 @@ impl ToTokens for EmitBuilder { } pub type EmitResult = Result<(TokenStream, T), (TokenStream, E)>; +pub type EmitErrOnlyResult = Result; pub struct Ctx(pub TokenStream, pub T); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index f3ab1775..ca8ec6f8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,6 +1,7 @@ use crate::{ codegen::emit::{ EmitBuilder, + EmitErrOnlyResult, EmitResult, EmitResultExt, WithTs, @@ -34,6 +35,7 @@ use quote::{ ToTokens, quote, }; +use std::collections::HashMap; use syn::{ Attribute, Item, @@ -255,10 +257,54 @@ pub fn args_from_attr_input( inflate_args_from_input(args, input_item.to_token_stream()) } +/// Type alias for the per-variant configuration data structure +type VariantConfigMap = HashMap; + +/// Type alias for tracking observed order of variants +type ObservedOrderMap = HashMap; + +/// Holds configuration data for a specific enum variant +#[derive(Default)] +struct PerVariant { + /// Default configuration (when group == None) + default: Option, + /// Group-specific configurations (when group == Some(g)) + per_group: HashMap, +} + +/// Processes an input TokenStream and constructs ConfigureSystemSetArgs pub fn inflate_args_from_input( mut args: ConfigureSystemSetArgs, input: TokenStream, ) -> EmitResult { + let mut builder = EmitBuilder::from_checkpoint(input); + + // Process the input and scrub helper attributes + let scrubbed_item = process_helper_attributes(&mut builder, args._strip_helpers)?; + + // Handle based on item type + match &scrubbed_item.item { + Item::Struct(_) => { + return builder.into_ok(args); + } + Item::Enum(item_enum) => { + // Process enum variants to populate args + process_enum_variants(&mut builder, &mut args, item_enum, &scrubbed_item)?; + } + _ => { + let err = syn::Error::new(scrubbed_item.item.span(), "Only struct or enum supported"); + return builder.into_err(err); + } + } + + Ok(args).with_ts(builder.into_tokens()) +} + +/// Scrubs helper attributes from input and prepares for processing +fn process_helper_attributes( + builder: &mut EmitBuilder, + strip_helpers: bool, +) -> Result { fn resolve_ident(item: &Item) -> syn::Result<&Ident> { // TODO: remove and use ident from higher level? item.ident() @@ -268,180 +314,207 @@ pub fn inflate_args_from_input( is_config_helper(attr) && matches!(site, AttrSite::Variant { .. }) } - let mut b = EmitBuilder::from_checkpoint(input); - - // 2) Scrub helpers from the item and resolve ident - let scrub = b - .try_do(|b| { - // TODO: maybe we need a code path that doesn't strip - only analyze? - let scrub = scrub_helpers_and_ident_with_filter( - b.to_token_stream(), - is_allowed_helper, - is_config_helper, - resolve_ident, - ) - // TODO: this feels bad - see `ScrubOutcome#ident` todo - .strip_ok_tokens()?; - - // 3) Determine if we are writing the scrubbed item back to *input* or just errors (if any) - b.try_unit(|b| { - if args._strip_helpers { - // Always write back the scrubbed item to *input* so helpers never re-trigger and IDE has something to work with - scrub.replace_token_stream(b) - } else { - // Check if we have errors to print and if so, strip helpers from the item - // Otherwise, maintain helpers for the next attribute to process - scrub.prepend_errors(b) - } - })?; - - Ok(scrub) - }) - .strip_ok_tokens()?; - - // 4) If it's a struct, there are no entries to compute - let data_enum = match scrub.item { - Item::Struct(_) => { - return b.into_ok(args); - } - Item::Enum(ref en) => en, - _ => { - let err = syn::Error::new(scrub.item.span(), "Only struct or enum supported"); - return b.into_err(err); + // TODO: maybe we need a code path that doesn't strip - only analyze? + let scrub = scrub_helpers_and_ident_with_filter( + builder.to_token_stream(), + is_allowed_helper, + is_config_helper, + resolve_ident, + ) + // TODO: this feels bad - see `ScrubOutcome#ident` todo + .strip_ok_tokens()?; + + builder.try_unit(|b| { + if strip_helpers { + // Always write back scrubbed item to prevent helpers from re-triggering + scrub.replace_token_stream(b) + } else { + // Only prepend errors if any, otherwise keep helpers for next attribute + scrub.prepend_errors(b) } - }; + })?; - // 5) Collect per-variant configs: - // - per-group configs: HashMap - // - default (no-group) config: Option - use std::collections::HashMap; - - #[derive(Default)] - struct PerVariant { - /// group == None - default: Option, - /// group == Some(g) - per_group: HashMap, - } + Ok(scrub) +} + +/// Processes enum variants to extract and organize configuration entries +fn process_enum_variants( + builder: &mut EmitBuilder, + args: &mut ConfigureSystemSetArgs, + item_enum: &syn::ItemEnum, + scrubbed_item: &ScrubOutcome, +) -> EmitErrOnlyResult<(), syn::Error> { + // Parse and collect configuration data from variant attributes + let (variant_configs, observed_order) = collect_variant_configs(builder, scrubbed_item)?; - let mut variants_cfg: HashMap = HashMap::new(); + // Create entries based on variant configs and apply fallback rules + let entries = create_variant_entries(item_enum, &variant_configs, &observed_order, &args.group); - // Require an observed order per variant, based on site enumeration position. - // Track the FIRST observed index we see for that variant. - let mut observed_order_by_variant: HashMap = HashMap::new(); + // Store processed entries in args + args.inner = Some(ConfigureSystemSetArgsInner { entries }); + Ok(()) +} - b.try_unit(|_| { - // Parse all removed helper attrs (last-one-wins per key), but error on duplicates for the SAME key. - // Treat a second helper on the same (variant, group or None) as a hard error. - for (observed_index, site) in scrub.all_with_removed_attrs().into_iter().enumerate() { +/// Collects configuration data from variant attributes +fn collect_variant_configs( + builder: &mut EmitBuilder, + scrubbed_item: &ScrubOutcome, +) -> EmitErrOnlyResult<(VariantConfigMap, ObservedOrderMap), syn::Error> { + let mut variants_cfg: VariantConfigMap = HashMap::new(); + let mut observed_order_by_variant: ObservedOrderMap = HashMap::new(); + + builder.try_unit(|_| { + for (observed_index, site) in scrubbed_item.all_with_removed_attrs().into_iter().enumerate() + { if let AttrSite::Variant { variant } = &site.site { observed_order_by_variant.entry(variant.clone()).or_insert(observed_index); + process_variant_attributes( + variant, + &site.attrs, + observed_index, + &mut variants_cfg, + )?; + } + } + Ok(()) + })?; - for attr in &site.attrs { - // Only care about our helper - if !is_config_helper(attr) { - continue; - } + Ok((variants_cfg, observed_order_by_variant)) +} - let mut entry = ConfigureSystemSetArgsInnerEntry::from_meta(&attr.meta)?; +/// Processes attributes for a specific variant +fn process_variant_attributes( + variant: &Ident, + attrs: &[Attribute], + observed_index: usize, + variants_cfg: &mut VariantConfigMap, +) -> syn::Result<()> { + for attr in attrs { + // Skip non-config helpers + if !is_config_helper(attr) { + continue; + } - // If order wasn't provided on the helper, set it to the first observed index for this variant - if entry.order.is_none() { - entry.order = - Some(*observed_order_by_variant.get(variant).unwrap_or(&observed_index)); - } + // Parse entry from attribute metadata + let mut entry = ConfigureSystemSetArgsInnerEntry::from_meta(&attr.meta)?; - let bucket = variants_cfg.entry(variant.clone()).or_default(); - match &entry.group { - Some(g) => { - if bucket.per_group.contains_key(g) { - return Err(syn::Error::new( - attr.span(), - format!("duplicate helper for variant `{variant}` and group `{g}`", ), - )); - } - bucket.per_group.insert(g.clone(), entry); - } - None => { - if bucket.default.is_some() { - return Err(syn::Error::new( - attr.span(), - format!( - "duplicate default (no-group) helper for variant `{variant}`", - ), - )); - } - bucket.default = Some(entry); - } - } - } - } + // Set default order if not specified + if entry.order.is_none() { + entry.order = Some(observed_index); } - Ok(()) - })?; - // 6) Walk the enum variants and assemble entries using fallback rules: - // chosen = per_group[outer_group] - // || (default with group overwritten to outer_group) - // || synthesized default (group = outer_group, order = observed) - let outer_group = args.group.clone(); - let mut entries: ConfigureSystemSetArgsInnerEntries = - Vec::with_capacity(data_enum.variants.len()); - - for v in &data_enum.variants { - let v_ident = v.ident.clone(); - - let prev_observed_len = observed_order_by_variant.len(); - // Find observed order for this variant (if we never saw the site, use sequential fallback) - let observed = - *observed_order_by_variant.entry(v_ident.clone()).or_insert_with(|| prev_observed_len); - - let chosen_entry = { - let bucket = variants_cfg.get(&v_ident); - - // prefer explicit group match - if let (Some(g), Some(b)) = (&outer_group, bucket) - && let Some(found) = b.per_group.get(g) - { - found.clone() - } - // else use the default helper but override its group to the outer group - else if let Some(b) = bucket - && let Some(mut def) = b.default.clone() - { - def.group = outer_group.clone(); - if def.order.is_none() { - def.order = Some(observed); + let bucket = variants_cfg.entry(variant.clone()).or_default(); + + // Store entry based on group + match &entry.group { + Some(g) => { + if bucket.per_group.contains_key(g) { + return Err(syn::Error::new( + attr.span(), + format!("duplicate helper for variant `{variant}` and group `{g}`"), + )); } - def + bucket.per_group.insert(g.clone(), entry); } - // else synthesize a default entry - else { - ConfigureSystemSetArgsInnerEntry { - group: outer_group.clone(), - order: Some(observed), - ..Default::default() + None => { + if bucket.default.is_some() { + return Err(syn::Error::new( + attr.span(), + format!("duplicate default (no-group) helper for variant `{variant}`"), + )); } + bucket.default = Some(entry); } - }; + } + } + + Ok(()) +} + +/// Creates entries for each variant based on configs and fallback rules +fn create_variant_entries( + item_enum: &syn::ItemEnum, + variants_cfg: &VariantConfigMap, + observed_order: &ObservedOrderMap, + outer_group: &Option, +) -> ConfigureSystemSetArgsInnerEntries { + let mut entries = Vec::with_capacity(item_enum.variants.len()); + let mut next_fallback_index = observed_order.len(); + + for variant in &item_enum.variants { + let variant_ident = variant.ident.clone(); + + // Find or create observed order for this variant + let observed_index = observed_order.get(&variant_ident).copied().unwrap_or_else(|| { + let idx = next_fallback_index; + next_fallback_index += 1; + idx + }); - entries.push((v_ident, chosen_entry)); + // Apply fallback rules to select entry + let entry = + select_entry_with_fallback(&variant_ident, variants_cfg, observed_index, outer_group); + + entries.push((variant_ident, entry)); + } + + // Sort by order and filter by group + sort_and_filter_entries(entries, outer_group) +} + +/// Selects the appropriate entry for a variant based on fallback rules +fn select_entry_with_fallback( + variant_ident: &Ident, + variants_cfg: &VariantConfigMap, + observed_index: usize, + outer_group: &Option, +) -> ConfigureSystemSetArgsInnerEntry { + let bucket = variants_cfg.get(variant_ident); + + // First try: explicit group match + if let (Some(g), Some(b)) = (outer_group, bucket) { + if let Some(found) = b.per_group.get(g) { + return found.clone(); + } } - // 7) Sort & filter - entries.sort_by_key(|(_, e)| e.order.unwrap_or_default()); - entries.retain(|(_, e)| { - // same group as outer group - match (&e.group, &outer_group) { + // Second try: default entry with group override + if let Some(b) = bucket { + if let Some(mut default_entry) = b.default.clone() { + default_entry.group = outer_group.clone(); + if default_entry.order.is_none() { + default_entry.order = Some(observed_index); + } + return default_entry; + } + } + + // Fallback: synthesize default entry + ConfigureSystemSetArgsInnerEntry { + group: outer_group.clone(), + order: Some(observed_index), + ..Default::default() + } +} + +/// Sorts entries by order and filters by group +fn sort_and_filter_entries( + mut entries: ConfigureSystemSetArgsInnerEntries, + outer_group: &Option, +) -> ConfigureSystemSetArgsInnerEntries { + // Sort by order + entries.sort_by_key(|(_, entry)| entry.order.unwrap_or_default()); + + // Filter by group + entries.retain(|(_, entry)| { + match (&entry.group, outer_group) { (Some(g), Some(og)) => g == og, // If either side is None, keep it (acts as "applies to any") _ => true, } }); - // 8) Store into args and return - args.inner = Some(ConfigureSystemSetArgsInner { entries }); - Ok(args).with_ts(b.into_tokens()) + entries } #[cfg(test)] From 527041b0478cb18a6bb011bd3f92b4e3bd7f2de5 Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 30 Oct 2025 16:32:12 -0400 Subject: [PATCH 152/162] refactor(codegen): add more type aliases for `EmitResult` --- .../src/codegen/emit.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs index 3a1c794f..d3088b0a 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -155,8 +155,10 @@ impl ToTokens for EmitBuilder { } } -pub type EmitResult = Result<(TokenStream, T), (TokenStream, E)>; -pub type EmitErrOnlyResult = Result; +pub type WithTokens = (TokenStream, T); +pub type EmitResult = Result, WithTokens>; +pub type EmitOkOnlyResult = Result, E>; +pub type EmitErrOnlyResult = Result>; pub struct Ctx(pub TokenStream, pub T); @@ -214,12 +216,9 @@ pub trait EmitResultExt { fn tokens(&self) -> &TokenStream; fn map_inner(self, f: impl FnOnce(T) -> U) -> EmitResult; fn map_inner_err(self, f: impl FnOnce(E) -> U) -> EmitResult; - fn map_err_tokens( - self, - f: impl FnOnce(TokenStream) -> U, - ) -> Result<(TokenStream, T), (U, E)>; - fn strip_err_tokens(self) -> Result<(TokenStream, T), E>; - fn strip_ok_tokens(self) -> Result; + fn map_err_tokens(self, f: impl FnOnce(TokenStream) -> U) -> Result, (U, E)>; + fn strip_err_tokens(self) -> EmitOkOnlyResult; + fn strip_ok_tokens(self) -> EmitErrOnlyResult; } impl EmitResultExt for EmitResult { @@ -266,12 +265,12 @@ impl EmitResultExt for EmitResult { } #[inline] - fn strip_err_tokens(self) -> Result<(TokenStream, T), E> { + fn strip_err_tokens(self) -> EmitOkOnlyResult { self.map_err(|(_, e)| e) } #[inline] - fn strip_ok_tokens(self) -> Result { + fn strip_ok_tokens(self) -> EmitErrOnlyResult { self.map(|(_, v)| v) } } From f2d195d1baaa63d331baff45f45ba7e3fe3bb54d Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 30 Oct 2025 19:54:01 -0400 Subject: [PATCH 153/162] refactor(syntax): move `item` from `parse` module to `analysis` module and update references --- .../src/syntax/analysis/item.rs | 58 ++++++ .../src/syntax/analysis/mod.rs | 1 + .../src/syntax/parse/item.rs | 57 ------ .../src/syntax/parse/scrub_helpers.rs | 189 +++++++----------- 4 files changed, 131 insertions(+), 174 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs new file mode 100644 index 00000000..ca2dd688 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs @@ -0,0 +1,58 @@ +use crate::syntax::extensions::{ + item::ItemAttrsExt, + path::PathExt, +}; +use syn::{ + Attribute, + Item, +}; + +pub fn item_has_attr(item: &Item, path: &syn::Path) -> syn::Result { + Ok(has_attr(item.attrs().unwrap_or_default(), path)) +} + +pub fn has_attr(attrs: &[Attribute], path: &syn::Path) -> bool { + attrs.iter().any(|attr| attr.path().is_similar_path_or_ident(path)) +} + +#[cfg(test)] +mod tests { + use crate::syntax::analysis::item::has_attr; + use internal_test_proc_macro::xtest; + use syn::parse_quote; + + #[xtest] + fn test_negative_has_attr_empty() { + let target_path = parse_quote!(a); + assert!(!has_attr(&[], &target_path)); + } + + #[xtest] + fn test_negative_has_attr() { + let target_path = parse_quote!(a); + let input: Vec<_> = parse_quote! { + #[foo] + }; + assert!(!has_attr(&input, &target_path)); + } + + #[xtest] + fn test_positive_has_attr_single() { + let target_path = parse_quote!(a); + let input: Vec<_> = parse_quote! { + #[#target_path] + }; + assert!(has_attr(&input, &target_path)); + } + + #[xtest] + fn test_positive_has_attr_multiple() { + let target_path = parse_quote!(a); + let input: Vec<_> = parse_quote! { + #[A] + #[#target_path] + #[B] + }; + assert!(has_attr(&input, &target_path)); + } +} diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs index be9d8276..2294853b 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/mod.rs @@ -1,3 +1,4 @@ pub mod fn_param; +pub mod item; pub mod path; pub mod ty_classify; diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs index ac9c4b05..8b137891 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs @@ -1,58 +1 @@ -use crate::syntax::extensions::{ - item::ItemAttrsExt, - path::PathExt, -}; -use syn::{ - Attribute, - Item, -}; -pub fn item_has_attr(item: &Item, path: &syn::Path) -> syn::Result { - Ok(has_attr(item.attrs().unwrap_or_default(), path)) -} - -pub fn has_attr(attrs: &[Attribute], path: &syn::Path) -> bool { - attrs.iter().any(|attr| attr.path().is_similar_path_or_ident(path)) -} - -#[cfg(test)] -mod tests { - use super::*; - use internal_test_proc_macro::xtest; - use syn::parse_quote; - - #[xtest] - fn test_negative_has_attr_empty() { - let target_path = parse_quote!(a); - assert!(!has_attr(&[], &target_path)); - } - - #[xtest] - fn test_negative_has_attr() { - let target_path = parse_quote!(a); - let input: Vec<_> = parse_quote! { - #[foo] - }; - assert!(!has_attr(&input, &target_path)); - } - - #[xtest] - fn test_positive_has_attr_single() { - let target_path = parse_quote!(a); - let input: Vec<_> = parse_quote! { - #[#target_path] - }; - assert!(has_attr(&input, &target_path)); - } - - #[xtest] - fn test_positive_has_attr_multiple() { - let target_path = parse_quote!(a); - let input: Vec<_> = parse_quote! { - #[A] - #[#target_path] - #[B] - }; - assert!(has_attr(&input, &target_path)); - } -} diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index 1811bb1c..0d007d56 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -1,9 +1,11 @@ #![allow(dead_code)] use crate::{ codegen::emit::{ + EmitErrOnlyResult, EmitResult, WithTsError, }, + macro_api::prelude::InputItem, syntax::extensions::item::ItemAttrsExt, }; use darling::FromMeta; @@ -133,10 +135,10 @@ impl SiteAttrsVec { } pub struct ScrubOutcome { - // TODO: probably should be inside the EmitResult instead of here. - // But EmitResult should allow for `syn::Item` or `InputItem` as well as `TokenStream` to make sense + /// original item (with helpers intact) + pub original_item: Item, /// scrubbed item (no helpers remain) - pub item: Item, + pub scrubbed_item: Item, /// struct/enum ident pub ident: Ident, /// attrs kept per site (non-helpers or empty) @@ -163,96 +165,58 @@ impl ScrubOutcome { } out } - /// It will only mutate the TokenStream if there are errors by prepending them - pub fn prepend_errors(&self, token_stream: &mut TokenStream) -> syn::Result<()> { - ts_prepend_errors( - token_stream, - self.item.span(), - self.errors.clone(), - "failed to scrub helpers", - ) + pub fn to_original_item_tokens(&self) -> TokenStream { + ts_item_errors(&self.original_item, self.errors.clone()) } - /// Replaces the token stream with the scrubbed item. - /// If there are errors, it will write them above the scrubbed item. - pub fn replace_token_stream(&self, token_stream: &mut TokenStream) -> syn::Result<()> { - replace_ts_with_item_and_errors( - token_stream, - &self.item, - self.errors.clone(), - "failed to scrub helpers", - ) + pub fn to_scrubbed_item_tokens(&self) -> TokenStream { + ts_item_errors(&self.scrubbed_item, self.errors.clone()) } } impl ToTokens for ScrubOutcome { fn to_tokens(&self, tokens: &mut TokenStream) { - self.item.to_tokens(tokens); + self.scrubbed_item.to_tokens(tokens); } } -impl From for EmitResult { +impl From for EmitErrOnlyResult { fn from(value: ScrubOutcome) -> Self { - // TODO: do we return Err if errors are present? - Ok((value.item.to_token_stream(), value)) + if value.errors.is_empty() { + Ok(value) + } else { + Err(( + value.original_item.to_token_stream(), + value.errors.into_iter().fold( + syn::Error::new(value.original_item.span(), "Failed to scrub helpers"), + |mut acc, err| { + acc.combine(err); + acc + }, + ), + )) + } } } -/// Writes errors to the token stream if they exist, otherwise doesn't modify the token stream. -/// -/// # Arguments -/// -/// * `token_stream` - The token stream to potentially write errors into -/// * `span` - The span location for error reporting -/// * `errors` - Collection of errors to potentially write -/// * `message` - Error message to include -/// -/// # Returns -/// -/// A Result indicating success or failure of the operation -pub fn ts_prepend_errors( - token_stream: &mut TokenStream, - span: proc_macro2::Span, - errors: Vec, - message: &str, -) -> syn::Result<()> { - // inject any errors as compile_error right here. - if !errors.is_empty() { +/// Returns `TokenStream` with errors (if any) +pub fn ts_errors(errors: Vec) -> TokenStream { + if errors.is_empty() { + TokenStream::new() + } else { let err_ts = errors.iter().map(syn::Error::to_compile_error); - *token_stream = quote! { + quote! { #( #err_ts )* - #token_stream - }; - let mut err = syn::Error::new(span, message); - err.extend(errors.clone()); - return Err(err); + } } - - Ok(()) } -/// Replaces the `TokenStream` in place with the item tokens and prepends any errors. -/// -/// # Arguments -/// -/// * `token_stream` - The token stream to output to -/// * `item` - The item to render -/// * `errors` - Collection of errors to potentially write -/// * `message` - Error message to include -/// -/// # Returns -/// -/// A Result indicating success or failure of the operation -pub fn replace_ts_with_item_and_errors( - token_stream: &mut TokenStream, - item: &Item, - errors: Vec, - message: &str, -) -> syn::Result<()> { - *token_stream = quote! { +/// Returns `TokenStream` with errors (if any) and the given `item` +pub fn ts_item_errors(item: &Item, errors: Vec) -> TokenStream { + let errors = ts_errors(errors); + quote! { + #errors #item - }; - - ts_prepend_errors(token_stream, item.span(), errors, message) + } } #[derive(Debug, Default)] @@ -411,25 +375,27 @@ impl VisitMut for Scrubber { } } -pub fn scrub_helpers_and_ident( - input: proc_macro2::TokenStream, +pub fn scrub_helpers( + input_item: impl AsRef, is_helper: fn(&Attribute) -> bool, - resolve_ident: fn(&Item) -> syn::Result<&Ident>, -) -> EmitResult { - scrub_helpers_and_ident_with_filter(input, |_, _| true, is_helper, resolve_ident) +) -> Result { + scrub_helpers_with_filter(input_item, |_, _| true, is_helper) } -pub fn scrub_helpers_and_ident_with_filter( - input: TokenStream, +pub fn scrub_helpers_with_filter( + input_item: impl AsRef, is_site_allowed: fn(&AttrSite, &Attribute) -> bool, is_helper: fn(&Attribute) -> bool, - resolve_ident: fn(&Item) -> syn::Result<&Ident>, -) -> EmitResult { - let mut item = syn::parse2::(input.clone()).with_ts_on_err(input.clone())?; - let ident = resolve_ident(&item).cloned().with_ts_on_err(input.clone())?; +) -> Result { + let mut input_item = input_item.as_ref().clone(); + let ident = input_item.ident()?.clone(); + let original_item = input_item.ensure_ast()?.clone(); + let mut scrubbed_item = original_item.clone(); + + // Must be infallible beyond this point to ensure `ScrubOutcome` is valid let mut scrubber = Scrubber { is_helper, out: ScrubberOut::default(), errors: vec![] }; - scrubber.visit_item_mut(&mut item); + scrubber.visit_item_mut(&mut scrubbed_item); // validate “removed” helpers against the site filter for group in &scrubber.out.removed.0 { @@ -450,25 +416,14 @@ pub fn scrub_helpers_and_ident_with_filter( } } - // TODO: check for errors? - // check for errors - // if let Some(err) = scrubber.errors.pop() { - // let err = scrubber.errors.into_iter().fold(err, |mut acc, err| { - // acc.combine(err); - // acc - // }); - // return Err((item.to_token_stream(), err)); - // } - - let scrub = ScrubOutcome { - item, + Ok(ScrubOutcome { + original_item, + scrubbed_item, ident, observed: scrubber.out.observed, removed: scrubber.out.removed, errors: scrubber.errors, - }; - - scrub.into() + }) } // Parse removed helpers into `T` @@ -545,6 +500,7 @@ mod tests { mod scrub_helpers_and_ident { use super::*; use crate::codegen::emit::EmitResultExt; + use internal_test_util::assert_ts_eq; #[inline] fn assert_no_errors(scrub_outcome: &ScrubOutcome) { assert_eq!( @@ -560,7 +516,7 @@ mod tests { #[inline] fn assert_no_helpers_remain_on_item(scrub_outcome: &ScrubOutcome) { - let ts = scrub_outcome.item.to_token_stream().to_string(); + let ts = scrub_outcome.scrubbed_item.to_token_stream().to_string(); assert!(!ts.contains("::helper"), "item still has helper attributes: {}", ts); } @@ -585,8 +541,8 @@ mod tests { z: i32, } }; - let (_input, scrub_outcome) = - scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; + let input_item = InputItem::from_ts_validated(input).expect("should be valid item"); + let scrub_outcome = scrub_helpers(input_item, is_helper)?; assert_no_errors(&scrub_outcome); assert_ident(&scrub_outcome, "Foo"); assert_no_helpers_remain_on_item(&scrub_outcome); @@ -628,8 +584,8 @@ mod tests { C, } }; - let (_input, scrub_outcome) = - scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; + let input_item = InputItem::from_ts_validated(input).expect("should be valid item"); + let scrub_outcome = scrub_helpers(input_item, is_helper)?; assert_no_errors(&scrub_outcome); assert_ident(&scrub_outcome, "Foo"); assert_no_helpers_remain_on_item(&scrub_outcome); @@ -678,14 +634,14 @@ mod tests { Y, } }; - let (_input, scrub_outcome) = - scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; + let input_item = InputItem::from_ts_validated(input).expect("should be valid item"); + let scrub_outcome = scrub_helpers(input_item, is_helper)?; assert_no_errors(&scrub_outcome); assert_ident(&scrub_outcome, "Foo"); assert_no_helpers_remain_on_item(&scrub_outcome); - let item = scrub_outcome.item; - assert_eq!( - item.to_token_stream().to_string(), + let item = scrub_outcome.scrubbed_item; + assert_ts_eq!( + item.to_token_stream(), quote! { #[non_helper] enum Foo { @@ -698,8 +654,7 @@ mod tests { X, Y, } - } - .to_string(), + }, ); Ok(()) } @@ -721,8 +676,8 @@ mod tests { C, } }; - let (_input, scrub_outcome) = - scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; + let input_item = InputItem::from_ts_validated(input).expect("should be valid item"); + let scrub_outcome = scrub_helpers(input_item, is_helper)?; assert_no_errors(&scrub_outcome); assert_ident(&scrub_outcome, "Foo"); assert_no_helpers_remain_on_item(&scrub_outcome); @@ -770,8 +725,8 @@ mod tests { } }; - let (_input, scrub_outcome) = - scrub_helpers_and_ident(input, is_helper, resolve_ident).strip_err_tokens()?; + let input_item = InputItem::from_ts_validated(input).expect("should be valid item"); + let scrub_outcome = scrub_helpers(input_item, is_helper)?; let got = SiteAttrsVec::from_vec(scrub_outcome.all_with_removed_attrs()); let expected = SiteAttrsVec::from_vec(vec![ From b3c618328bfe44092a24e9bae6651ffdfdfabb56 Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 30 Oct 2025 20:48:39 -0400 Subject: [PATCH 154/162] feat(syntax): add `expect_single_item_any_compile_errors` for parsing single items with compile error handling --- .../src/syntax/parse/item.rs | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs index 8b137891..d00565c2 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/item.rs @@ -1 +1,65 @@ +use proc_macro2::TokenStream; +use syn::{ + File, + Item, + ItemMacro, + Macro, +}; +use thiserror::Error; +#[derive(Debug, Error)] +pub enum SingleItemWithErrorsCheckError { + #[error("failed to parse token stream as a single item: {0}")] + ParseFailed(#[from] syn::Error), + #[error("token stream did not contain an item")] + NoRealItem, + #[error("token stream contained more than one item")] + MultipleRealItems, +} + +/// Returns the single Item (struct/enum/etc) if the token stream is: +/// `Item` [+ zero or more `compile_error!` items] +/// Fails otherwise. +pub fn expect_single_item_any_compile_errors( + ts: TokenStream, +) -> Result<(Item, Vec), SingleItemWithErrorsCheckError> { + let file: File = syn::parse2(ts).map_err(SingleItemWithErrorsCheckError::ParseFailed)?; + + let mut compile_errors = vec![]; + let mut found_item: Option = None; + + for item in file.items.into_iter() { + if let Some(compiler_error) = as_compile_error_item(&item) { + compile_errors.push(compiler_error.clone()); + continue; + } + + // It's a "real" item + match &found_item { + None => { + // first real item we've seen — keep it + found_item = Some(item); + } + Some(_) => { + // second real item → reject + return Err(SingleItemWithErrorsCheckError::MultipleRealItems); + } + } + } + + match found_item { + Some(item) => Ok((item, compile_errors)), + None => Err(SingleItemWithErrorsCheckError::NoRealItem), + } +} + +/// returns `Some(ItemMacro)` if `compile_error!(...)` ? +fn as_compile_error_item(item: &Item) -> Option<&ItemMacro> { + match item { + Item::Macro(item_macro) => { + let ItemMacro { mac: Macro { path, .. }, .. } = item_macro; + if path.is_ident("compile_error") { Some(item_macro) } else { None } + } + _ => None, + } +} From 0942281cfecdae341aae839b40e448e75bc35ee2 Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 30 Oct 2025 20:50:29 -0400 Subject: [PATCH 155/162] refactor(macro_api): enhance `InputItem` with new conversion traits and validation methods --- .../src/macro_api/input_item.rs | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs index 780ac2cb..fe420e54 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/input_item.rs @@ -1,4 +1,10 @@ -use crate::syntax::extensions::item::ItemAttrsExt; +use crate::syntax::{ + extensions::item::ItemAttrsExt, + parse::item::{ + SingleItemWithErrorsCheckError, + expect_single_item_any_compile_errors, + }, +}; use proc_macro2::TokenStream; use quote::{ ToTokens, @@ -15,6 +21,44 @@ pub enum InputItem { Item(Box), } +impl AsRef for InputItem { + fn as_ref(&self) -> &Self { + self + } +} + +impl From> for InputItem { + fn from(boxed_item: Box) -> Self { + Self::Item(boxed_item) + } +} + +impl From<&syn::Item> for InputItem { + fn from(item: &syn::Item) -> Self { + Self::Item(Box::new(item.clone())) + } +} + +impl From for InputItem { + fn from(item: syn::Item) -> Self { + Self::Item(Box::new(item)) + } +} + +impl TryFrom for InputItem { + type Error = syn::Error; + fn try_from(tokens: TokenStream) -> Result { + Self::from_ts_validated(tokens) + } +} + +impl TryFrom<&TokenStream> for InputItem { + type Error = syn::Error; + fn try_from(tokens: &TokenStream) -> Result { + Self::from_ts_validated(tokens.clone()) + } +} + impl PartialEq for InputItem { fn eq(&self, other: &Self) -> bool { let self_tokens = self.to_token_stream(); @@ -24,12 +68,28 @@ impl PartialEq for InputItem { } impl InputItem { + pub fn from_ts_validated(tokens: TokenStream) -> syn::Result { + let mut input_item = Self::Tokens(tokens); + input_item.ensure_ast()?; + Ok(input_item) + } fn _upgrade(&mut self) -> syn::Result<()> { if let Self::Tokens(tokens) = self { *self = Self::Item(parse2(tokens.clone())?); } Ok(()) } + pub fn has_compiler_errors(&self) -> Result { + match self { + InputItem::Tokens(tokens) => { + match expect_single_item_any_compile_errors(tokens.clone()) { + Ok((_, compiler_errors)) => Ok(!compiler_errors.is_empty()), + Err(e) => Err(e), + } + } + InputItem::Item(_) => Ok(false), + } + } pub fn ensure_ast(&mut self) -> syn::Result<&syn::Item> { self._upgrade()?; Ok(match &*self { From ccb2831d6ef9856a297b8a48c814c14eefa07b79 Mon Sep 17 00:00:00 2001 From: bstriker Date: Thu, 30 Oct 2025 20:51:30 -0400 Subject: [PATCH 156/162] refactor(codegen, macro_api): replace `EmitBuilder` with new context logic, and overhaul related paths --- .../src/__private/expand/attr/action.rs | 2 +- .../src/codegen/emit.rs | 402 ++++-------------- .../actions/auto_configure_system_set.rs | 239 +++++------ .../src/macro_api/emitters/app_mutation.rs | 2 +- .../src/syntax/analysis/item.rs | 4 +- .../src/syntax/parse/scrub_helpers.rs | 9 +- 6 files changed, 204 insertions(+), 454 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs index 2c382762..01b48fe5 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/action.rs @@ -25,7 +25,7 @@ where ); let mut app_mut_emitter = AppMutationEmitter::from_args(args); let processed_item = { - if let Err((tokens, err)) = app_mut_emitter.item_post_process() { + if let Err((tokens, err)) = app_mut_emitter.post_process_inner_item() { let err = err.to_compile_error(); return quote! { #err diff --git a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs index d3088b0a..d7167210 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/emit.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/emit.rs @@ -3,194 +3,51 @@ use proc_macro2::TokenStream; use quote::ToTokens; -#[derive(Debug, Default, Clone)] -pub(crate) struct EmitBuilder { - tokens: TokenStream, - // LIFO stack of checkpoints for nested phases - checkpoints: Vec, -} - -impl EmitBuilder { - pub(crate) fn new() -> Self { - Self::default() - } - - pub(crate) fn from_checkpoint(cp: TokenStream) -> Self { - Self { tokens: cp.clone(), checkpoints: vec![cp] } - } - - #[inline] - pub(crate) fn extend(&mut self, ts: impl ToTokens) -> &mut Self { - self.tokens.extend(ts.into_token_stream()); - self - } - - #[inline] - pub(crate) fn replace(&mut self, ts: impl ToTokens) -> &mut Self { - self.tokens = ts.into_token_stream(); - self - } - - /// Push the current tokens as a checkpoint. - pub(crate) fn push_checkpoint(&mut self) -> &mut Self { - self.checkpoints.push(self.tokens.clone()); - self - } - - /// Restore to the last checkpoint. No-op if empty. - pub(crate) fn restore(&mut self) -> &mut Self { - if let Some(cp) = self.checkpoints.last() { - self.tokens = cp.clone(); - } - self - } - - /// Restore to the last checkpoint and **pop** it. No-op if empty. - pub(crate) fn pop_restore(&mut self) -> &mut Self { - if let Some(cp) = self.checkpoints.pop() { - self.tokens = cp; - } - self - } - - /// Discard the last checkpoint (keep current tokens). No-op if empty. - pub(crate) fn discard_checkpoint(&mut self) -> &mut Self { - self.checkpoints.pop(); - self - } - - /// Finish successfully. - pub(crate) fn into_ok(self, value: T) -> EmitResult { - Ok((self.tokens, value)) - } - - /// Finish with an error; emits the **last checkpoint** if any, else current tokens. - pub(crate) fn into_err(self, err: E) -> EmitResult { - let fallback = - if let Some(cp) = self.checkpoints.last() { cp.clone() } else { self.tokens.clone() }; - Err((fallback, err)) - } - - /// Try a phase with automatic checkpointing. - pub(crate) fn try_phase( - &mut self, - f: impl FnOnce(&mut Self) -> Result<(), E>, - ) -> Result<&mut Self, (TokenStream, E)> { - match f(self.push_checkpoint()) { - Ok(()) => Ok(self.discard_checkpoint()), - Err(e) => { - self.pop_restore(); - Err((self.to_token_stream(), e)) - } - } - } +pub type EmitResult = Result<(T, V), (T, E)>; +pub type EmitOkOnlyResult = Result<(T, V), E>; +pub type EmitErrOnlyResult = Result; - #[inline] - pub fn ok(&self, v: T) -> EmitResult { - Ok((self.tokens.clone(), v)) - } - #[inline] - pub fn err(&self, e: E) -> EmitResult { - Err((self.tokens.clone(), e)) - } +pub struct Ctx(pub T, pub V); - /// Same as `try_phase` but returns `EmitResult` for easy `?` usage - pub(crate) fn try_do( - &mut self, - f: impl FnOnce(&mut Self) -> Result, - ) -> EmitResult { - self.push_checkpoint(); - match f(self) { - Ok(v) => { - self.discard_checkpoint(); - self.ok(v) - } - Err((_, e)) => { - self.pop_restore(); - self.err(e) - } +impl Ctx { + pub fn and_then(self, f: impl FnOnce(&T, V) -> Result) -> EmitResult { + let Ctx(ts, v) = self; + match f(&ts, v) { + Ok(u) => Ok((ts, u)), + Err(e) => Err((ts, e)), } } - - pub(crate) fn try_unit( - &mut self, - f: impl FnOnce(&mut Self) -> Result<(), E>, - ) -> Result<(), (TokenStream, E)> { - self.try_do(|b| f(b).map_err(|e| (b.to_token_stream(), e))).strip_ok_tokens() - } - - pub(crate) fn into_tokens(self) -> TokenStream { - self.tokens - } - - #[must_use] - pub(crate) fn take_tokens(&mut self) -> TokenStream { - std::mem::take(&mut self.tokens) - } - - pub(crate) fn tokens(&self) -> &TokenStream { - &self.tokens - } - - pub(crate) fn tokens_mut(&mut self) -> &mut TokenStream { - &mut self.tokens - } -} - -impl std::ops::Deref for EmitBuilder { - type Target = TokenStream; - fn deref(&self) -> &Self::Target { - &self.tokens - } -} -impl std::ops::DerefMut for EmitBuilder { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.tokens - } -} - -impl ToTokens for EmitBuilder { - fn to_tokens(&self, out: &mut TokenStream) { - out.extend(self.tokens.to_token_stream()); - } -} - -pub type WithTokens = (TokenStream, T); -pub type EmitResult = Result, WithTokens>; -pub type EmitOkOnlyResult = Result, E>; -pub type EmitErrOnlyResult = Result>; - -pub struct Ctx(pub TokenStream, pub T); - -impl Ctx { - pub fn and_then( + pub fn and_then_mut( self, - f: impl FnOnce(&TokenStream, T) -> Result, - ) -> EmitResult { - let Ctx(ts, v) = self; - match f(&ts, v) { + f: impl FnOnce(&mut T, V) -> Result, + ) -> EmitResult { + let Ctx(mut ts, v) = self; + match f(&mut ts, v) { Ok(u) => Ok((ts, u)), Err(e) => Err((ts, e)), } } } -impl Ctx<()> { - pub fn start(ts: TokenStream) -> Ctx<()> { +impl Ctx { + pub fn start(ts: T) -> Ctx { Ctx(ts, ()) } } -pub trait WithTs { +pub trait WithTs { type Output; - fn with_ts(self, ts: TokenStream) -> Self::Output; + fn with_ts(self, ts: T) -> Self::Output; } -impl WithTs for Result { - type Output = EmitResult; +impl WithTs for Result { + type Output = EmitResult; #[inline] - fn with_ts(self, ts: TokenStream) -> Self::Output { - self.map(|v| (ts.clone(), v)).map_err(|e| (ts.clone(), e)) + fn with_ts(self, ts: T) -> Self::Output { + match self { + Ok(v) => Ok((ts, v)), + Err(e) => Err((ts, e)), + } } } @@ -207,23 +64,29 @@ impl WithTsError for Result { } } -pub trait EmitResultExt { - fn split(self) -> (TokenStream, Result); - fn join((ts, res): (TokenStream, Result)) -> EmitResult { +pub trait EmitResultExt { + fn split(self) -> (T, Result); + fn join((ts, res): (T, Result)) -> EmitResult { res.with_ts(ts) } - fn into_tokens(self) -> TokenStream; - fn tokens(&self) -> &TokenStream; - fn map_inner(self, f: impl FnOnce(T) -> U) -> EmitResult; - fn map_inner_err(self, f: impl FnOnce(E) -> U) -> EmitResult; - fn map_err_tokens(self, f: impl FnOnce(TokenStream) -> U) -> Result, (U, E)>; - fn strip_err_tokens(self) -> EmitOkOnlyResult; - fn strip_ok_tokens(self) -> EmitErrOnlyResult; + fn into_tokens(self) -> TokenStream + where + T: ToTokens; + fn to_tokens(&self) -> TokenStream + where + T: ToTokens; + fn map_inner(self, f: impl FnOnce(V) -> U) -> EmitResult; + fn map_inner_err(self, f: impl FnOnce(E) -> U) -> EmitResult; + fn map_err_context(self, f: impl FnOnce(T) -> U) -> Result<(T, V), (U, E)>; + fn strip_err_context(self) -> EmitOkOnlyResult; + fn strip_ok_context(self) -> EmitErrOnlyResult; + fn and_then_ctx(self, f: impl FnOnce(&T, V) -> Result) -> EmitResult; + fn and_then_ctx_mut(self, f: impl FnOnce(&mut T, V) -> Result) -> EmitResult; } -impl EmitResultExt for EmitResult { +impl EmitResultExt for EmitResult { #[inline] - fn split(self) -> (TokenStream, Result) { + fn split(self) -> (T, Result) { match self { Ok((ts, v)) => (ts, Ok(v)), Err((ts, e)) => (ts, Err(e)), @@ -231,53 +94,75 @@ impl EmitResultExt for EmitResult { } #[inline] - fn into_tokens(self) -> TokenStream { + fn into_tokens(self) -> TokenStream + where + T: ToTokens, + { match self { - Ok((ts, _)) => ts, - Err((ts, _)) => ts, + Ok((ts, _)) => ts.into_token_stream(), + Err((ts, _)) => ts.into_token_stream(), } } #[inline] - fn tokens(&self) -> &TokenStream { + fn to_tokens(&self) -> TokenStream + where + T: ToTokens, + { match self { - Ok((ts, _)) => ts, - Err((ts, _)) => ts, + Ok((ts, _)) => ts.to_token_stream(), + Err((ts, _)) => ts.to_token_stream(), } } #[inline] - fn map_inner(self, f: impl FnOnce(T) -> U) -> EmitResult { + fn map_inner(self, f: impl FnOnce(V) -> U) -> EmitResult { self.and_then(|(ts, v)| Ok(f(v)).with_ts(ts)) } #[inline] - fn map_inner_err(self, f: impl FnOnce(E) -> U) -> EmitResult { + fn map_inner_err(self, f: impl FnOnce(E) -> U) -> EmitResult { self.or_else(|(ts, e)| Err(f(e)).with_ts(ts)) } #[inline] - fn map_err_tokens( - self, - f: impl FnOnce(TokenStream) -> U, - ) -> Result<(TokenStream, T), (U, E)> { + fn map_err_context(self, f: impl FnOnce(T) -> U) -> Result<(T, V), (U, E)> { self.map_err(|(ts, e)| (f(ts), e)) } #[inline] - fn strip_err_tokens(self) -> EmitOkOnlyResult { + fn strip_err_context(self) -> EmitOkOnlyResult { self.map_err(|(_, e)| e) } #[inline] - fn strip_ok_tokens(self) -> EmitErrOnlyResult { + fn strip_ok_context(self) -> EmitErrOnlyResult { self.map(|(_, v)| v) } + + #[inline] + fn and_then_ctx(self, f: impl FnOnce(&T, V) -> Result) -> EmitResult { + match self { + Ok((ts, v)) => Ctx(ts, v).and_then(f), + Err((ts, e)) => Err((ts, e)), + } + } + + #[inline] + fn and_then_ctx_mut(self, f: impl FnOnce(&mut T, V) -> Result) -> EmitResult { + match self { + Ok((ts, v)) => Ctx(ts, v).and_then_mut(f), + Err((ts, e)) => Err((ts, e)), + } + } } -pub type CtxOnly = Ctx<()>; -impl From> for CtxOnly { - fn from(value: EmitResult) -> Self { +pub type CtxOnly = Ctx; +impl From> for CtxOnly +where + T: ToTokens, +{ + fn from(value: Result<(T, V), (T, E)>) -> Self { match value { Ok((ts, _)) => Ctx(ts, ()), Err((ts, _)) => Ctx(ts, ()), @@ -292,99 +177,11 @@ mod tests { use internal_test_util::assert_ts_eq; use quote::quote; - #[xtest] - fn builder_extend_and_replace() { - let mut b = EmitBuilder::new(); - b.extend(quote! { a }); - assert_ts_eq!(&b, quote! { a }); - - b.replace(quote! { b }); - assert_ts_eq!(&b, quote! { b }); - - b.extend(quote! { c d }); - assert_ts_eq!(&b, quote! { b c d }); - } - - #[xtest] - fn builder_checkpoint_restore_and_pop() { - // start with some base - let mut b = EmitBuilder::from_checkpoint(quote! { base }); - assert_ts_eq!(&b, quote! { base }); - - // push + modify + restore (non-pop) should revert to base but leave checkpoint on stack - b.push_checkpoint().extend(quote! { X }).restore(); - assert_ts_eq!(&b, quote! { base }); - - // modify again then pop_restore should also revert to base *and* pop the checkpoint - b.extend(quote! { TEMP }).pop_restore(); - assert_ts_eq!(&b, quote! { base }); - - // push + modify + discard should keep the modified result - b.push_checkpoint().extend(quote! { KEEP }).discard_checkpoint(); - assert_ts_eq!(&b, quote! { base KEEP }); - } - - #[xtest] - fn try_phase_ok_keeps_changes() { - let mut b = EmitBuilder::from_checkpoint(quote! { init }); - let _ = b.try_phase(|b| { - // phase mutates tokens - b.extend(quote! { ok1 ok2 }); - Ok::<_, syn::Error>(()) - }); - assert_ts_eq!(&b, quote! { init ok1 ok2 }); - } - - #[xtest] - fn try_phase_err_restores_checkpoint() { - let mut b = EmitBuilder::from_checkpoint(quote! { start }); - let _ = b.try_phase(|b| { - // mutate then fail; should revert to checkpoint - b.extend(quote! { broken }); - Err::<(), _>(syn::Error::new(proc_macro2::Span::call_site(), "boom")) - }); - assert_ts_eq!(&b, quote! { start }); - } - - #[xtest] - fn into_ok_and_into_err_fallback_rules() { - // into_ok uses current tokens - let b1 = { - let mut b = EmitBuilder::from_checkpoint(quote! { cp }); - b.extend(quote! { work }); - b - }; - let ok: EmitResult = b1.into_ok(42); - match ok { - Ok((tokens, value)) => { - assert_eq!(value, 42); - assert_ts_eq!(&tokens, quote! { cp work }); - } - _ => panic!("expected Ok"), - } - - // into_err uses last checkpoint (cp), not the mutated tokens - let b2 = { - let mut b = EmitBuilder::from_checkpoint(quote! { cp }); - b.extend(quote! { work }); - b - }; - let err: EmitResult<(), _> = - b2.into_err(syn::Error::new(proc_macro2::Span::call_site(), "nope")); - match err { - Err((tokens, error)) => { - let _: syn::Error = error.clone().into(); - assert_ts_eq!(&tokens, quote! { cp }); - } - _ => panic!("expected Err"), - } - } - #[xtest] fn result_split_and_map() { // split ok { - let ok: EmitResult = Ok((quote! { T }, 5)); + let ok: EmitResult = Ok((quote! { T }, 5)); let (ts, res) = ok.split(); assert_ts_eq!(&ts, quote! { T }); assert_eq!(res.unwrap(), 5); @@ -392,7 +189,7 @@ mod tests { // map { - let ok: EmitResult<&'static str, ()> = Ok((quote! { U }, "abc")); + let ok: EmitResult = Ok((quote! { U }, "abc")); let mapped = ok.map(|(ts, s)| (ts, s.len())); let (ts, res) = mapped.split(); assert_ts_eq!(ts, quote! { U }); @@ -401,38 +198,11 @@ mod tests { // split err { - let err: EmitResult<(), _> = + let err: EmitResult = Err((quote! { E }, syn::Error::new(proc_macro2::Span::call_site(), "nope"))); let (ts, res) = err.split(); assert_ts_eq!(&ts, quote! { E }); assert!(res.is_err()); } } - - #[xtest] - fn to_tokens_impls_emit_builder_and_emit_result() { - // EmitBuilder → ToTokens - let mut b = EmitBuilder::new(); - b.extend(quote! { a b c }); - let mut out = TokenStream::new(); - b.to_tokens(&mut out); - assert_ts_eq!(&out, quote! { a b c }); - - // EmitResult Ok → ToTokens - let ok: EmitResult<(), ()> = Ok((quote! { OKTOK }, ())); - assert_ts_eq!(ok.tokens(), quote! { OKTOK }); - - // EmitResult Err → ToTokens - let err: EmitResult<(), _> = - Err((quote! { ERRTOK }, syn::Error::new(proc_macro2::Span::call_site(), "x"))); - assert_ts_eq!(err.into_tokens(), quote! { ERRTOK }); - } - #[xtest] - fn restore_noop_when_empty() { - // If no checkpoints exist, restore/discard/pop_restore are no-ops - let mut b = EmitBuilder::new(); - b.extend(quote! { X }); - b.restore().discard_checkpoint().pop_restore(); - assert_ts_eq!(b, quote! { X }); - } } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index ca8ec6f8..532e92a7 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -1,10 +1,8 @@ use crate::{ codegen::emit::{ - EmitBuilder, - EmitErrOnlyResult, + Ctx, EmitResult, EmitResultExt, - WithTs, }, macro_api::{ prelude::*, @@ -14,21 +12,19 @@ use crate::{ }, }, syntax::{ + analysis::item::item_has_attr, ast::flag::Flag, - extensions::item::ItemAttrsExt, - parse::{ - item::item_has_attr, - scrub_helpers::{ - AttrSite, - ScrubOutcome, - scrub_helpers_and_ident_with_filter, - }, + parse::scrub_helpers::{ + AttrSite, + ScrubOutcome, + scrub_helpers_with_filter, }, }, }; use darling::FromMeta; use proc_macro2::{ Ident, + Span, TokenStream, }; use quote::{ @@ -104,9 +100,6 @@ pub struct ConfigureSystemSetArgs { #[darling(skip)] /// Some when enum, None when struct pub inner: Option, - #[darling(skip, default)] - /// internal - used to track if this is the last attribute in the item to strip helpers - pub _strip_helpers: bool, } impl ConfigureSystemSetArgs { @@ -188,16 +181,14 @@ fn output( } impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { - fn item_post_process(&mut self) -> Result<(), (TokenStream, syn::Error)> { + fn post_process_inner_item(&mut self) -> Result<(), (InputItem, syn::Error)> { let input_item = &mut self.args.input_item; let args = &mut self.args.args.base; - let input = input_item.to_token_stream(); - let (input, item) = input_item.ensure_ast().with_ts(input)?; - check_strip_helpers(item, args).with_ts(input.clone())?; if args.inner.is_none() { - let (input, inflated_args) = inflate_args_from_input(args.clone(), input)?; + let (maybe_scrubbed_input_item, inflated_args) = + inflate_args_from_input_item(args.clone(), input_item)?; *args = inflated_args; - *input_item = InputItem::Tokens(input); + *input_item = maybe_scrubbed_input_item; } Ok(()) } @@ -206,8 +197,8 @@ impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { // checks if we need to inflate args let inflated_args = if args.inner.is_none() { let args = args.clone(); - let input = self.args.input_item.to_token_stream(); - match inflate_args_from_input(args, input) { + let input_item = &self.args.input_item; + match inflate_args_from_input_item(args, input_item) { Ok((_, args)) => args, Err((_, err)) => { tokens.extend(err.to_compile_error()); @@ -237,24 +228,20 @@ impl ToTokens for ConfigureSystemSetAttrEmitter { } } -/// HACK - if the item doesn't have anymore `auto_configure_system_set` - set a flag to strip out the helper attributes -fn check_strip_helpers(item: &Item, args: &mut ConfigureSystemSetArgs) -> syn::Result<()> { - if !item_has_attr(item, &parse_quote!(auto_configure_system_set))? { - args._strip_helpers = true; - } - Ok(()) +fn check_strip_helpers(item: &Item) -> bool { + !item_has_attr(item, &parse_quote!(auto_configure_system_set)) } #[cfg(test)] pub fn args_from_attr_input( attr: TokenStream, input: TokenStream, -) -> EmitResult { - let (input, mut args) = syn::parse2::(attr).with_ts(input.clone())?; - let mut input_item = InputItem::Tokens(input.clone()); - let (input, item) = input_item.ensure_ast().with_ts(input)?; - check_strip_helpers(item, &mut args).with_ts(input)?; - inflate_args_from_input(args, input_item.to_token_stream()) +) -> EmitResult { + let input_item = + InputItem::from_ts_validated(input.clone()).map_err(|e| (InputItem::Tokens(input), e))?; + let (input_item, args) = + Ctx::start(input_item).and_then(|_, _| syn::parse2::(attr))?; + inflate_args_from_input_item(args, &input_item) } /// Type alias for the per-variant configuration data structure @@ -273,111 +260,108 @@ struct PerVariant { } /// Processes an input TokenStream and constructs ConfigureSystemSetArgs -pub fn inflate_args_from_input( +pub fn inflate_args_from_input_item( mut args: ConfigureSystemSetArgs, - input: TokenStream, -) -> EmitResult { - let mut builder = EmitBuilder::from_checkpoint(input); - - // Process the input and scrub helper attributes - let scrubbed_item = process_helper_attributes(&mut builder, args._strip_helpers)?; - - // Handle based on item type - match &scrubbed_item.item { - Item::Struct(_) => { - return builder.into_ok(args); - } - Item::Enum(item_enum) => { - // Process enum variants to populate args - process_enum_variants(&mut builder, &mut args, item_enum, &scrubbed_item)?; - } - _ => { - let err = syn::Error::new(scrubbed_item.item.span(), "Only struct or enum supported"); - return builder.into_err(err); - } - } - - Ok(args).with_ts(builder.into_tokens()) + input_item: &InputItem, +) -> EmitResult { + Ctx::start(input_item.clone()) + .and_then(|input_item, _| { + // Process the input helper attributes + process_helper_attributes(input_item) + }) + .and_then_ctx_mut(|input_item, scrubbed_outcome| { + let should_strip_helpers = check_strip_helpers(&scrubbed_outcome.original_item); + let maybe_scrubbed_input_item_tokens = if should_strip_helpers { + scrubbed_outcome.to_scrubbed_item_tokens() + } else { + scrubbed_outcome.to_original_item_tokens() + }; + *input_item = InputItem::Tokens(maybe_scrubbed_input_item_tokens); + // TODO: so this is kind of ugly. we check if we need to re-emit the scrubbed item. + // but in doing so we are required to include any errors which breaks syn parsing. + // and our context required `InputItem` instead of just a `TokenStream`. + // so we check if the scrubbed item has errors and if so break out early. + match input_item.has_compiler_errors() { + Ok(has_compiler_errors) => { + if has_compiler_errors { + return Err( + // TODO: we need a ui test to make sure the other errors are still emitted with their spans + syn::Error::new(Span::call_site(), format!("invalid {CONFIG_ATTR_NAME}s:")), + ); + } + } + Err(err) => { + return Err( + syn::Error::new( + Span::call_site(), + format!("bevy_auto_plugin bug - please open an issue with a reproduction case: {err:?}"), + ), + ); + } + } + Ok(scrubbed_outcome) + }) + .and_then_ctx(|_maybe_scrubbed_input_item, scrub_outcome| { + // Handle based on item type + match &scrub_outcome.original_item { + Item::Enum(item_enum) => { + // Process enum variants for the specified group to populate args + let inner = process_enum_variants_for_group( + args.group.as_ref(), + item_enum, + &scrub_outcome, + )?; + args.inner = inner; + Ok(args) + } + Item::Struct(_) => Ok(args), + _ => { + let err = syn::Error::new(Span::call_site(), "Only struct or enum supported"); + Err(err) + } + } + }) } /// Scrubs helper attributes from input and prepares for processing fn process_helper_attributes( - builder: &mut EmitBuilder, - strip_helpers: bool, -) -> Result { - fn resolve_ident(item: &Item) -> syn::Result<&Ident> { - // TODO: remove and use ident from higher level? - item.ident() - } - + input_item: impl AsRef, +) -> Result { fn is_allowed_helper(site: &AttrSite, attr: &Attribute) -> bool { is_config_helper(attr) && matches!(site, AttrSite::Variant { .. }) } - // TODO: maybe we need a code path that doesn't strip - only analyze? - let scrub = scrub_helpers_and_ident_with_filter( - builder.to_token_stream(), - is_allowed_helper, - is_config_helper, - resolve_ident, - ) - // TODO: this feels bad - see `ScrubOutcome#ident` todo - .strip_ok_tokens()?; - - builder.try_unit(|b| { - if strip_helpers { - // Always write back scrubbed item to prevent helpers from re-triggering - scrub.replace_token_stream(b) - } else { - // Only prepend errors if any, otherwise keep helpers for next attribute - scrub.prepend_errors(b) - } - })?; - - Ok(scrub) + scrub_helpers_with_filter(input_item, is_allowed_helper, is_config_helper) } /// Processes enum variants to extract and organize configuration entries -fn process_enum_variants( - builder: &mut EmitBuilder, - args: &mut ConfigureSystemSetArgs, +fn process_enum_variants_for_group( + group: Option<&Ident>, item_enum: &syn::ItemEnum, scrubbed_item: &ScrubOutcome, -) -> EmitErrOnlyResult<(), syn::Error> { +) -> Result, syn::Error> { // Parse and collect configuration data from variant attributes - let (variant_configs, observed_order) = collect_variant_configs(builder, scrubbed_item)?; + let (variant_configs, observed_order) = collect_variant_configs(scrubbed_item)?; // Create entries based on variant configs and apply fallback rules - let entries = create_variant_entries(item_enum, &variant_configs, &observed_order, &args.group); + let entries = create_variant_entries(item_enum, &variant_configs, &observed_order, group); - // Store processed entries in args - args.inner = Some(ConfigureSystemSetArgsInner { entries }); - Ok(()) + Ok(Some(ConfigureSystemSetArgsInner { entries })) } /// Collects configuration data from variant attributes fn collect_variant_configs( - builder: &mut EmitBuilder, scrubbed_item: &ScrubOutcome, -) -> EmitErrOnlyResult<(VariantConfigMap, ObservedOrderMap), syn::Error> { +) -> Result<(VariantConfigMap, ObservedOrderMap), syn::Error> { let mut variants_cfg: VariantConfigMap = HashMap::new(); let mut observed_order_by_variant: ObservedOrderMap = HashMap::new(); - builder.try_unit(|_| { - for (observed_index, site) in scrubbed_item.all_with_removed_attrs().into_iter().enumerate() - { - if let AttrSite::Variant { variant } = &site.site { - observed_order_by_variant.entry(variant.clone()).or_insert(observed_index); - process_variant_attributes( - variant, - &site.attrs, - observed_index, - &mut variants_cfg, - )?; - } + for (observed_index, site) in scrubbed_item.all_with_removed_attrs().into_iter().enumerate() { + if let AttrSite::Variant { variant } = &site.site { + observed_order_by_variant.entry(variant.clone()).or_insert(observed_index); + process_variant_attributes(variant, &site.attrs, observed_index, &mut variants_cfg)?; } - Ok(()) - })?; + } Ok((variants_cfg, observed_order_by_variant)) } @@ -436,7 +420,7 @@ fn create_variant_entries( item_enum: &syn::ItemEnum, variants_cfg: &VariantConfigMap, observed_order: &ObservedOrderMap, - outer_group: &Option, + outer_group: Option<&Ident>, ) -> ConfigureSystemSetArgsInnerEntries { let mut entries = Vec::with_capacity(item_enum.variants.len()); let mut next_fallback_index = observed_order.len(); @@ -467,7 +451,7 @@ fn select_entry_with_fallback( variant_ident: &Ident, variants_cfg: &VariantConfigMap, observed_index: usize, - outer_group: &Option, + outer_group: Option<&Ident>, ) -> ConfigureSystemSetArgsInnerEntry { let bucket = variants_cfg.get(variant_ident); @@ -481,7 +465,7 @@ fn select_entry_with_fallback( // Second try: default entry with group override if let Some(b) = bucket { if let Some(mut default_entry) = b.default.clone() { - default_entry.group = outer_group.clone(); + default_entry.group = outer_group.cloned(); if default_entry.order.is_none() { default_entry.order = Some(observed_index); } @@ -491,7 +475,7 @@ fn select_entry_with_fallback( // Fallback: synthesize default entry ConfigureSystemSetArgsInnerEntry { - group: outer_group.clone(), + group: outer_group.cloned(), order: Some(observed_index), ..Default::default() } @@ -500,7 +484,7 @@ fn select_entry_with_fallback( /// Sorts entries by order and filters by group fn sort_and_filter_entries( mut entries: ConfigureSystemSetArgsInnerEntries, - outer_group: &Option, + outer_group: Option<&Ident>, ) -> ConfigureSystemSetArgsInnerEntries { // Sort by order entries.sort_by_key(|(_, entry)| entry.order.unwrap_or_default()); @@ -534,7 +518,7 @@ mod tests { ) -> Result<(Ident, ConfigureSystemSetArgs), syn::Error> { let mut input_item = InputItem::Tokens(input.clone()); let ident = input_item.ident()?.clone(); - let (_, inflated_args) = args_from_attr_input(attr, input.clone()).strip_err_tokens()?; + let (_, inflated_args) = args_from_attr_input(attr, input.clone()).strip_err_context()?; Ok((ident, inflated_args)) } @@ -693,7 +677,7 @@ mod tests { } }, ) - .strip_err_tokens()?; + .strip_err_context()?; assert_eq!( inflated_args, ConfigureSystemSetArgs { @@ -724,7 +708,6 @@ mod tests { group: Some(parse_quote!(A)), chain: Flag::from(false), chain_ignore_deferred: Flag::from(false), - _strip_helpers: true, } ); Ok(()) @@ -744,16 +727,15 @@ mod tests { B, } }; - let (scrubbed_input, _) = args_from_attr_input(attr, input).strip_err_tokens()?; - assert_eq!( - scrubbed_input.to_string(), + let (scrubbed_input, _) = args_from_attr_input(attr, input).strip_err_context()?; + assert_ts_eq!( + scrubbed_input, quote! { enum Foo { A, B, } } - .to_string() ); Ok(()) } @@ -805,10 +787,13 @@ mod tests { A, } }; - let (tokens, args) = - args_from_attr_input(attr, input.clone()).map_err_tokens(token_string)?; + let mut input_item = + InputItem::from_ts_validated(input.clone()).expect("should be valid item"); + let item = input_item.ensure_ast().expect("should be valid item ast"); + assert!(!check_strip_helpers(item)); + let (tokens, _) = + args_from_attr_input(attr, input.clone()).map_err_context(token_string)?; - assert!(!args._strip_helpers); assert_ts_eq!(tokens, input); Ok(()) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs index 790c7041..cdfb7b06 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/emitters/app_mutation.rs @@ -52,7 +52,7 @@ impl AppMutationEmitter { pub trait EmitAppMutationTokens { // TODO: this should be its own thing but it might overcomplicate things - fn item_post_process(&mut self) -> Result<(), (TokenStream, syn::Error)> { + fn post_process_inner_item(&mut self) -> Result<(), (InputItem, syn::Error)> { Ok(()) } fn to_app_mutation_token_stream(&self, app_param: &syn::Ident) -> TokenStream { diff --git a/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs b/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs index ca2dd688..f6bccd56 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/analysis/item.rs @@ -7,8 +7,8 @@ use syn::{ Item, }; -pub fn item_has_attr(item: &Item, path: &syn::Path) -> syn::Result { - Ok(has_attr(item.attrs().unwrap_or_default(), path)) +pub fn item_has_attr(item: &Item, path: &syn::Path) -> bool { + has_attr(item.attrs().unwrap_or_default(), path) } pub fn has_attr(attrs: &[Attribute], path: &syn::Path) -> bool { diff --git a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs index 0d007d56..b2d8a56b 100644 --- a/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs +++ b/crates/bevy_auto_plugin_shared/src/syntax/parse/scrub_helpers.rs @@ -1,10 +1,6 @@ #![allow(dead_code)] use crate::{ - codegen::emit::{ - EmitErrOnlyResult, - EmitResult, - WithTsError, - }, + codegen::emit::EmitErrOnlyResult, macro_api::prelude::InputItem, syntax::extensions::item::ItemAttrsExt, }; @@ -499,7 +495,6 @@ mod tests { mod scrub_helpers_and_ident { use super::*; - use crate::codegen::emit::EmitResultExt; use internal_test_util::assert_ts_eq; #[inline] fn assert_no_errors(scrub_outcome: &ScrubOutcome) { @@ -654,7 +649,7 @@ mod tests { X, Y, } - }, + } ); Ok(()) } From d6fb2bbc9c358a5687e947ed5e10cfaade8373ab Mon Sep 17 00:00:00 2001 From: bstriker Date: Fri, 31 Oct 2025 00:03:12 -0400 Subject: [PATCH 157/162] refactor(macro_api): simplify pattern matching in `auto_configure_system_set` responses --- .../actions/auto_configure_system_set.rs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs index 532e92a7..483c3de3 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs @@ -456,21 +456,21 @@ fn select_entry_with_fallback( let bucket = variants_cfg.get(variant_ident); // First try: explicit group match - if let (Some(g), Some(b)) = (outer_group, bucket) { - if let Some(found) = b.per_group.get(g) { - return found.clone(); - } + if let (Some(g), Some(b)) = (outer_group, bucket) + && let Some(found) = b.per_group.get(g) + { + return found.clone(); } // Second try: default entry with group override - if let Some(b) = bucket { - if let Some(mut default_entry) = b.default.clone() { - default_entry.group = outer_group.cloned(); - if default_entry.order.is_none() { - default_entry.order = Some(observed_index); - } - return default_entry; + if let Some(b) = bucket + && let Some(mut default_entry) = b.default.clone() + { + default_entry.group = outer_group.cloned(); + if default_entry.order.is_none() { + default_entry.order = Some(observed_index); } + return default_entry; } // Fallback: synthesize default entry From 304f2df6ff1cf29bfd7094806cb66544e222a5d9 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 1 Nov 2025 22:09:44 -0400 Subject: [PATCH 158/162] refactor(macro_api): move `auto_configure_system_set` to its own module --- .../mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/{auto_configure_system_set.rs => auto_configure_system_set/mod.rs} (100%) diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/mod.rs similarity index 100% rename from crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set.rs rename to crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/mod.rs From 298fd8966ff7538d248d9b2d3e7d0a718df32024 Mon Sep 17 00:00:00 2001 From: bstriker Date: Sat, 1 Nov 2025 22:14:58 -0400 Subject: [PATCH 159/162] refactor(macro_api): extract `inflate` module from `auto_configure_system_set` --- .../auto_configure_system_set/inflate.rs | 376 +++++++++++++++++ .../actions/auto_configure_system_set/mod.rs | 377 +----------------- 2 files changed, 398 insertions(+), 355 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/inflate.rs diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/inflate.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/inflate.rs new file mode 100644 index 00000000..e38937a8 --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/inflate.rs @@ -0,0 +1,376 @@ +use super::CONFIG_ATTR_NAME; +use crate::{ + codegen::emit::{ + Ctx, + EmitResult, + EmitResultExt, + }, + macro_api::{ + attributes::actions::auto_configure_system_set, + input_item::InputItem, + prelude::{ + ConfigureSystemSetArgs, + ConfigureSystemSetArgsInner, + ConfigureSystemSetArgsInnerEntries, + ConfigureSystemSetArgsInnerEntry, + }, + }, + syntax::{ + analysis::item::item_has_attr, + parse::scrub_helpers::{ + AttrSite, + ScrubOutcome, + scrub_helpers_with_filter, + }, + }, +}; +use darling::FromMeta; +use proc_macro2::{ + Ident, + Span, + TokenStream, +}; +use quote::{ + ToTokens, + quote, +}; +use std::collections::HashMap; +use syn::{ + Attribute, + Item, + Path, + parse_quote, + spanned::Spanned, +}; + +pub fn output( + args: &ConfigureSystemSetArgs, + app_param: &Ident, + concrete_path: &Path, + has_generics: bool, +) -> TokenStream { + let mut tokens = TokenStream::new(); + let schedule = &args.schedule_config.schedule; + let config_tokens = args.schedule_config.config.to_token_stream(); + if let Some(inner) = &args.inner { + // enum + let chained = if args.chain.is_present() { + quote! { .chain() } + } else if args.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let mut entries = vec![]; + for (ident, entry) in inner.entries.iter() { + let chained = if entry.chain.is_present() { + quote! { .chain() } + } else if entry.chain_ignore_deferred.is_present() { + quote! { .chain_ignore_deferred() } + } else { + quote! {} + }; + let config_tokens = entry.config.to_token_stream(); + entries.push(quote! { + #concrete_path :: #ident #chained #config_tokens + }); + } + if !entries.is_empty() { + tokens.extend(quote! { + #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); + }); + } + } else { + // struct + if has_generics { + // TODO: generics are kind of silly here + // but if someone does use them we'll assume its just a marker type + // that can be initialized via `Default::default()` + tokens.extend(quote! { + #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); + }); + } else { + tokens.extend(quote! { + #app_param.configure_sets(#schedule, #concrete_path #config_tokens); + }); + } + } + tokens +} + +pub fn check_strip_helpers(item: &Item) -> bool { + !item_has_attr(item, &parse_quote!(auto_configure_system_set)) +} + +#[cfg(test)] +pub fn args_from_attr_input( + attr: TokenStream, + input: TokenStream, +) -> EmitResult { + let input_item = + InputItem::from_ts_validated(input.clone()).map_err(|e| (InputItem::Tokens(input), e))?; + let (input_item, args) = + Ctx::start(input_item).and_then(|_, _| syn::parse2::(attr))?; + inflate_args_from_input_item(args, &input_item) +} + +/// Type alias for the per-variant configuration data structure +type VariantConfigMap = HashMap; +/// Type alias for tracking observed order of variants +type ObservedOrderMap = HashMap; + +/// Holds configuration data for a specific enum variant +#[derive(Default)] +struct PerVariant { + /// Default configuration (when group == None) + default: Option, + /// Group-specific configurations (when group == Some(g)) + per_group: HashMap, +} + +/// Processes an input TokenStream and constructs ConfigureSystemSetArgs +pub fn inflate_args_from_input_item( + mut args: ConfigureSystemSetArgs, + input_item: &InputItem, +) -> EmitResult { + Ctx::start(input_item.clone()) + .and_then(|input_item, _| { + // Process the input helper attributes + process_helper_attributes(input_item) + }) + .and_then_ctx_mut(|input_item, scrubbed_outcome| { + let should_strip_helpers = check_strip_helpers(&scrubbed_outcome.original_item); + let maybe_scrubbed_input_item_tokens = if should_strip_helpers { + scrubbed_outcome.to_scrubbed_item_tokens() + } else { + scrubbed_outcome.to_original_item_tokens() + }; + *input_item = InputItem::Tokens(maybe_scrubbed_input_item_tokens); + // TODO: so this is kind of ugly. we check if we need to re-emit the scrubbed item. + // but in doing so we are required to include any errors which breaks syn parsing. + // and our context required `InputItem` instead of just a `TokenStream`. + // so we check if the scrubbed item has errors and if so break out early. + match input_item.has_compiler_errors() { + Ok(has_compiler_errors) => { + if has_compiler_errors { + return Err( + // TODO: we need a ui test to make sure the other errors are still emitted with their spans + syn::Error::new(Span::call_site(), format!("invalid {CONFIG_ATTR_NAME}s:")), + ); + } + } + Err(err) => { + return Err( + syn::Error::new( + Span::call_site(), + format!("bevy_auto_plugin bug - please open an issue with a reproduction case: {err:?}"), + ), + ); + } + } + Ok(scrubbed_outcome) + }) + .and_then_ctx(|_maybe_scrubbed_input_item, scrub_outcome| { + // Handle based on item type + match &scrub_outcome.original_item { + Item::Enum(item_enum) => { + // Process enum variants for the specified group to populate args + let inner = process_enum_variants_for_group( + args.group.as_ref(), + item_enum, + &scrub_outcome, + )?; + args.inner = inner; + Ok(args) + } + Item::Struct(_) => Ok(args), + _ => { + let err = syn::Error::new(Span::call_site(), "Only struct or enum supported"); + Err(err) + } + } + }) +} + +/// Scrubs helper attributes from input and prepares for processing +fn process_helper_attributes( + input_item: impl AsRef, +) -> Result { + fn is_allowed_helper(site: &AttrSite, attr: &Attribute) -> bool { + auto_configure_system_set::is_config_helper(attr) + && matches!(site, AttrSite::Variant { .. }) + } + + scrub_helpers_with_filter( + input_item, + is_allowed_helper, + auto_configure_system_set::is_config_helper, + ) +} + +/// Processes enum variants to extract and organize configuration entries +fn process_enum_variants_for_group( + group: Option<&Ident>, + item_enum: &syn::ItemEnum, + scrubbed_item: &ScrubOutcome, +) -> Result, syn::Error> { + // Parse and collect configuration data from variant attributes + let (variant_configs, observed_order) = collect_variant_configs(scrubbed_item)?; + + // Create entries based on variant configs and apply fallback rules + let entries = create_variant_entries(item_enum, &variant_configs, &observed_order, group); + + Ok(Some(ConfigureSystemSetArgsInner { entries })) +} + +/// Collects configuration data from variant attributes +fn collect_variant_configs( + scrubbed_item: &ScrubOutcome, +) -> Result<(VariantConfigMap, ObservedOrderMap), syn::Error> { + let mut variants_cfg: VariantConfigMap = HashMap::new(); + let mut observed_order_by_variant: ObservedOrderMap = HashMap::new(); + + for (observed_index, site) in scrubbed_item.all_with_removed_attrs().into_iter().enumerate() { + if let AttrSite::Variant { variant } = &site.site { + observed_order_by_variant.entry(variant.clone()).or_insert(observed_index); + process_variant_attributes(variant, &site.attrs, observed_index, &mut variants_cfg)?; + } + } + + Ok((variants_cfg, observed_order_by_variant)) +} + +/// Processes attributes for a specific variant +fn process_variant_attributes( + variant: &Ident, + attrs: &[Attribute], + observed_index: usize, + variants_cfg: &mut VariantConfigMap, +) -> syn::Result<()> { + for attr in attrs { + // Skip non-config helpers + if !auto_configure_system_set::is_config_helper(attr) { + continue; + } + + // Parse entry from attribute metadata + let mut entry = ConfigureSystemSetArgsInnerEntry::from_meta(&attr.meta)?; + + // Set default order if not specified + if entry.order.is_none() { + entry.order = Some(observed_index); + } + + let bucket = variants_cfg.entry(variant.clone()).or_default(); + + // Store entry based on group + match &entry.group { + Some(g) => { + if bucket.per_group.contains_key(g) { + return Err(syn::Error::new( + attr.span(), + format!("duplicate helper for variant `{variant}` and group `{g}`"), + )); + } + bucket.per_group.insert(g.clone(), entry); + } + None => { + if bucket.default.is_some() { + return Err(syn::Error::new( + attr.span(), + format!("duplicate default (no-group) helper for variant `{variant}`"), + )); + } + bucket.default = Some(entry); + } + } + } + + Ok(()) +} + +/// Creates entries for each variant based on configs and fallback rules +fn create_variant_entries( + item_enum: &syn::ItemEnum, + variants_cfg: &VariantConfigMap, + observed_order: &ObservedOrderMap, + outer_group: Option<&Ident>, +) -> ConfigureSystemSetArgsInnerEntries { + let mut entries = Vec::with_capacity(item_enum.variants.len()); + let mut next_fallback_index = observed_order.len(); + + for variant in &item_enum.variants { + let variant_ident = variant.ident.clone(); + + // Find or create observed order for this variant + let observed_index = observed_order.get(&variant_ident).copied().unwrap_or_else(|| { + let idx = next_fallback_index; + next_fallback_index += 1; + idx + }); + + // Apply fallback rules to select entry + let entry = + select_entry_with_fallback(&variant_ident, variants_cfg, observed_index, outer_group); + + entries.push((variant_ident, entry)); + } + + // Sort by order and filter by group + sort_and_filter_entries(entries, outer_group) +} + +/// Selects the appropriate entry for a variant based on fallback rules +fn select_entry_with_fallback( + variant_ident: &Ident, + variants_cfg: &VariantConfigMap, + observed_index: usize, + outer_group: Option<&Ident>, +) -> ConfigureSystemSetArgsInnerEntry { + let bucket = variants_cfg.get(variant_ident); + + // First try: explicit group match + if let (Some(g), Some(b)) = (outer_group, bucket) + && let Some(found) = b.per_group.get(g) + { + return found.clone(); + } + + // Second try: default entry with group override + if let Some(b) = bucket + && let Some(mut default_entry) = b.default.clone() + { + default_entry.group = outer_group.cloned(); + if default_entry.order.is_none() { + default_entry.order = Some(observed_index); + } + return default_entry; + } + + // Fallback: synthesize default entry + ConfigureSystemSetArgsInnerEntry { + group: outer_group.cloned(), + order: Some(observed_index), + ..Default::default() + } +} + +/// Sorts entries by order and filters by group +fn sort_and_filter_entries( + mut entries: ConfigureSystemSetArgsInnerEntries, + outer_group: Option<&Ident>, +) -> ConfigureSystemSetArgsInnerEntries { + // Sort by order + entries.sort_by_key(|(_, entry)| entry.order.unwrap_or_default()); + + // Filter by group + entries.retain(|(_, entry)| { + match (&entry.group, outer_group) { + (Some(g), Some(og)) => g == og, + // If either side is None, keep it (acts as "applies to any") + _ => true, + } + }); + + entries +} diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/mod.rs index 483c3de3..45fc40cd 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/actions/auto_configure_system_set/mod.rs @@ -1,9 +1,6 @@ +mod inflate; + use crate::{ - codegen::emit::{ - Ctx, - EmitResult, - EmitResultExt, - }, macro_api::{ prelude::*, schedule_config::{ @@ -11,34 +8,18 @@ use crate::{ ScheduleWithScheduleConfigArgs, }, }, - syntax::{ - analysis::item::item_has_attr, - ast::flag::Flag, - parse::scrub_helpers::{ - AttrSite, - ScrubOutcome, - scrub_helpers_with_filter, - }, - }, + syntax::ast::flag::Flag, }; use darling::FromMeta; use proc_macro2::{ Ident, - Span, TokenStream, }; use quote::{ ToTokens, quote, }; -use std::collections::HashMap; -use syn::{ - Attribute, - Item, - Path, - parse_quote, - spanned::Spanned, -}; +use syn::Attribute; const CONFIG_ATTR_NAME: &str = "auto_configure_system_set_config"; const CHAIN_CONFLICT_ERR: &str = "`chain` and `chain_ignore_deferred` are mutually exclusive"; @@ -125,68 +106,13 @@ pub type IaConfigureSystemSet = ItemAttribute< pub type ConfigureSystemSetAppMutEmitter = AppMutationEmitter; pub type ConfigureSystemSetAttrEmitter = AttrEmitter; -fn output( - args: &ConfigureSystemSetArgs, - app_param: &Ident, - concrete_path: &Path, - has_generics: bool, -) -> TokenStream { - let mut tokens = TokenStream::new(); - let schedule = &args.schedule_config.schedule; - let config_tokens = args.schedule_config.config.to_token_stream(); - if let Some(inner) = &args.inner { - // enum - let chained = if args.chain.is_present() { - quote! { .chain() } - } else if args.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let mut entries = vec![]; - for (ident, entry) in inner.entries.iter() { - let chained = if entry.chain.is_present() { - quote! { .chain() } - } else if entry.chain_ignore_deferred.is_present() { - quote! { .chain_ignore_deferred() } - } else { - quote! {} - }; - let config_tokens = entry.config.to_token_stream(); - entries.push(quote! { - #concrete_path :: #ident #chained #config_tokens - }); - } - if !entries.is_empty() { - tokens.extend(quote! { - #app_param.configure_sets(#schedule, (#(#entries),*) #chained #config_tokens); - }); - } - } else { - // struct - if has_generics { - // TODO: generics are kind of silly here - // but if someone does use them we'll assume its just a marker type - // that can be initialized via `Default::default()` - tokens.extend(quote! { - #app_param.configure_sets(#schedule, #concrete_path::default() #config_tokens); - }); - } else { - tokens.extend(quote! { - #app_param.configure_sets(#schedule, #concrete_path #config_tokens); - }); - } - } - tokens -} - impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { fn post_process_inner_item(&mut self) -> Result<(), (InputItem, syn::Error)> { let input_item = &mut self.args.input_item; let args = &mut self.args.args.base; if args.inner.is_none() { let (maybe_scrubbed_input_item, inflated_args) = - inflate_args_from_input_item(args.clone(), input_item)?; + inflate::inflate_args_from_input_item(args.clone(), input_item)?; *args = inflated_args; *input_item = maybe_scrubbed_input_item; } @@ -198,7 +124,7 @@ impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { let inflated_args = if args.inner.is_none() { let args = args.clone(); let input_item = &self.args.input_item; - match inflate_args_from_input_item(args, input_item) { + match inflate::inflate_args_from_input_item(args, input_item) { Ok((_, args)) => args, Err((_, err)) => { tokens.extend(err.to_compile_error()); @@ -210,7 +136,12 @@ impl EmitAppMutationTokens for ConfigureSystemSetAppMutEmitter { }; let generics = self.args.args.generics(); for concrete_path in self.args.concrete_paths() { - tokens.extend(output(&inflated_args, app_param, &concrete_path, !generics.is_empty())); + tokens.extend(inflate::output( + &inflated_args, + app_param, + &concrete_path, + !generics.is_empty(), + )); } } } @@ -228,283 +159,13 @@ impl ToTokens for ConfigureSystemSetAttrEmitter { } } -fn check_strip_helpers(item: &Item) -> bool { - !item_has_attr(item, &parse_quote!(auto_configure_system_set)) -} - -#[cfg(test)] -pub fn args_from_attr_input( - attr: TokenStream, - input: TokenStream, -) -> EmitResult { - let input_item = - InputItem::from_ts_validated(input.clone()).map_err(|e| (InputItem::Tokens(input), e))?; - let (input_item, args) = - Ctx::start(input_item).and_then(|_, _| syn::parse2::(attr))?; - inflate_args_from_input_item(args, &input_item) -} - -/// Type alias for the per-variant configuration data structure -type VariantConfigMap = HashMap; - -/// Type alias for tracking observed order of variants -type ObservedOrderMap = HashMap; - -/// Holds configuration data for a specific enum variant -#[derive(Default)] -struct PerVariant { - /// Default configuration (when group == None) - default: Option, - /// Group-specific configurations (when group == Some(g)) - per_group: HashMap, -} - -/// Processes an input TokenStream and constructs ConfigureSystemSetArgs -pub fn inflate_args_from_input_item( - mut args: ConfigureSystemSetArgs, - input_item: &InputItem, -) -> EmitResult { - Ctx::start(input_item.clone()) - .and_then(|input_item, _| { - // Process the input helper attributes - process_helper_attributes(input_item) - }) - .and_then_ctx_mut(|input_item, scrubbed_outcome| { - let should_strip_helpers = check_strip_helpers(&scrubbed_outcome.original_item); - let maybe_scrubbed_input_item_tokens = if should_strip_helpers { - scrubbed_outcome.to_scrubbed_item_tokens() - } else { - scrubbed_outcome.to_original_item_tokens() - }; - *input_item = InputItem::Tokens(maybe_scrubbed_input_item_tokens); - // TODO: so this is kind of ugly. we check if we need to re-emit the scrubbed item. - // but in doing so we are required to include any errors which breaks syn parsing. - // and our context required `InputItem` instead of just a `TokenStream`. - // so we check if the scrubbed item has errors and if so break out early. - match input_item.has_compiler_errors() { - Ok(has_compiler_errors) => { - if has_compiler_errors { - return Err( - // TODO: we need a ui test to make sure the other errors are still emitted with their spans - syn::Error::new(Span::call_site(), format!("invalid {CONFIG_ATTR_NAME}s:")), - ); - } - } - Err(err) => { - return Err( - syn::Error::new( - Span::call_site(), - format!("bevy_auto_plugin bug - please open an issue with a reproduction case: {err:?}"), - ), - ); - } - } - Ok(scrubbed_outcome) - }) - .and_then_ctx(|_maybe_scrubbed_input_item, scrub_outcome| { - // Handle based on item type - match &scrub_outcome.original_item { - Item::Enum(item_enum) => { - // Process enum variants for the specified group to populate args - let inner = process_enum_variants_for_group( - args.group.as_ref(), - item_enum, - &scrub_outcome, - )?; - args.inner = inner; - Ok(args) - } - Item::Struct(_) => Ok(args), - _ => { - let err = syn::Error::new(Span::call_site(), "Only struct or enum supported"); - Err(err) - } - } - }) -} - -/// Scrubs helper attributes from input and prepares for processing -fn process_helper_attributes( - input_item: impl AsRef, -) -> Result { - fn is_allowed_helper(site: &AttrSite, attr: &Attribute) -> bool { - is_config_helper(attr) && matches!(site, AttrSite::Variant { .. }) - } - - scrub_helpers_with_filter(input_item, is_allowed_helper, is_config_helper) -} - -/// Processes enum variants to extract and organize configuration entries -fn process_enum_variants_for_group( - group: Option<&Ident>, - item_enum: &syn::ItemEnum, - scrubbed_item: &ScrubOutcome, -) -> Result, syn::Error> { - // Parse and collect configuration data from variant attributes - let (variant_configs, observed_order) = collect_variant_configs(scrubbed_item)?; - - // Create entries based on variant configs and apply fallback rules - let entries = create_variant_entries(item_enum, &variant_configs, &observed_order, group); - - Ok(Some(ConfigureSystemSetArgsInner { entries })) -} - -/// Collects configuration data from variant attributes -fn collect_variant_configs( - scrubbed_item: &ScrubOutcome, -) -> Result<(VariantConfigMap, ObservedOrderMap), syn::Error> { - let mut variants_cfg: VariantConfigMap = HashMap::new(); - let mut observed_order_by_variant: ObservedOrderMap = HashMap::new(); - - for (observed_index, site) in scrubbed_item.all_with_removed_attrs().into_iter().enumerate() { - if let AttrSite::Variant { variant } = &site.site { - observed_order_by_variant.entry(variant.clone()).or_insert(observed_index); - process_variant_attributes(variant, &site.attrs, observed_index, &mut variants_cfg)?; - } - } - - Ok((variants_cfg, observed_order_by_variant)) -} - -/// Processes attributes for a specific variant -fn process_variant_attributes( - variant: &Ident, - attrs: &[Attribute], - observed_index: usize, - variants_cfg: &mut VariantConfigMap, -) -> syn::Result<()> { - for attr in attrs { - // Skip non-config helpers - if !is_config_helper(attr) { - continue; - } - - // Parse entry from attribute metadata - let mut entry = ConfigureSystemSetArgsInnerEntry::from_meta(&attr.meta)?; - - // Set default order if not specified - if entry.order.is_none() { - entry.order = Some(observed_index); - } - - let bucket = variants_cfg.entry(variant.clone()).or_default(); - - // Store entry based on group - match &entry.group { - Some(g) => { - if bucket.per_group.contains_key(g) { - return Err(syn::Error::new( - attr.span(), - format!("duplicate helper for variant `{variant}` and group `{g}`"), - )); - } - bucket.per_group.insert(g.clone(), entry); - } - None => { - if bucket.default.is_some() { - return Err(syn::Error::new( - attr.span(), - format!("duplicate default (no-group) helper for variant `{variant}`"), - )); - } - bucket.default = Some(entry); - } - } - } - - Ok(()) -} - -/// Creates entries for each variant based on configs and fallback rules -fn create_variant_entries( - item_enum: &syn::ItemEnum, - variants_cfg: &VariantConfigMap, - observed_order: &ObservedOrderMap, - outer_group: Option<&Ident>, -) -> ConfigureSystemSetArgsInnerEntries { - let mut entries = Vec::with_capacity(item_enum.variants.len()); - let mut next_fallback_index = observed_order.len(); - - for variant in &item_enum.variants { - let variant_ident = variant.ident.clone(); - - // Find or create observed order for this variant - let observed_index = observed_order.get(&variant_ident).copied().unwrap_or_else(|| { - let idx = next_fallback_index; - next_fallback_index += 1; - idx - }); - - // Apply fallback rules to select entry - let entry = - select_entry_with_fallback(&variant_ident, variants_cfg, observed_index, outer_group); - - entries.push((variant_ident, entry)); - } - - // Sort by order and filter by group - sort_and_filter_entries(entries, outer_group) -} - -/// Selects the appropriate entry for a variant based on fallback rules -fn select_entry_with_fallback( - variant_ident: &Ident, - variants_cfg: &VariantConfigMap, - observed_index: usize, - outer_group: Option<&Ident>, -) -> ConfigureSystemSetArgsInnerEntry { - let bucket = variants_cfg.get(variant_ident); - - // First try: explicit group match - if let (Some(g), Some(b)) = (outer_group, bucket) - && let Some(found) = b.per_group.get(g) - { - return found.clone(); - } - - // Second try: default entry with group override - if let Some(b) = bucket - && let Some(mut default_entry) = b.default.clone() - { - default_entry.group = outer_group.cloned(); - if default_entry.order.is_none() { - default_entry.order = Some(observed_index); - } - return default_entry; - } - - // Fallback: synthesize default entry - ConfigureSystemSetArgsInnerEntry { - group: outer_group.cloned(), - order: Some(observed_index), - ..Default::default() - } -} - -/// Sorts entries by order and filters by group -fn sort_and_filter_entries( - mut entries: ConfigureSystemSetArgsInnerEntries, - outer_group: Option<&Ident>, -) -> ConfigureSystemSetArgsInnerEntries { - // Sort by order - entries.sort_by_key(|(_, entry)| entry.order.unwrap_or_default()); - - // Filter by group - entries.retain(|(_, entry)| { - match (&entry.group, outer_group) { - (Some(g), Some(og)) => g == og, - // If either side is None, keep it (acts as "applies to any") - _ => true, - } - }); - - entries -} - #[cfg(test)] mod tests { use super::*; - use crate::codegen::emit::EmitResultExt; + use crate::{ + codegen::emit::EmitResultExt, + macro_api::attributes::actions::auto_configure_system_set::inflate::args_from_attr_input, + }; use internal_test_proc_macro::xtest; use syn::{ Path, @@ -524,7 +185,9 @@ mod tests { mod test_struct { use super::*; + use crate::macro_api::attributes::actions::auto_configure_system_set::inflate::output; use quote::quote; + #[xtest] fn test_to_tokens_no_generics() -> syn::Result<()> { let args = parse2::(quote!(schedule = Update))?; @@ -582,6 +245,10 @@ mod tests { mod test_enum { use super::*; + use crate::macro_api::attributes::actions::auto_configure_system_set::inflate::{ + check_strip_helpers, + output, + }; use internal_test_util::{ assert_ts_eq, token_stream::token_string, From 471110626ccf6c997fa6c8a0cdc7a45b95c0e1bb Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 6 Jan 2026 22:01:12 -0500 Subject: [PATCH 160/162] feat: add `auto_sub_states`, and add `auto_register_state_type` to `auto_states` - ported from https://github.com/StrikeForceZero/bevy_auto_plugin/pull/55 Co-authored-by: Jady Wright --- .../bevy_auto_plugin_proc_macros/src/lib.rs | 6 ++ .../src/__private/expand/attr/mod.rs | 1 + .../src/codegen/tokens.rs | 33 +++++++++ .../attributes/rewrites/auto_states.rs | 9 ++- .../attributes/rewrites/auto_sub_states.rs | 73 +++++++++++++++++++ .../src/macro_api/attributes/rewrites/mod.rs | 2 + docs/proc_attributes/rewrites/auto_states.md | 2 +- .../rewrites/auto_sub_states.md | 48 ++++++++++++ src/lib.rs | 3 + tests/e2e/rewrites/auto_states.rs | 45 ++++++++++++ tests/e2e/rewrites/auto_sub_states.rs | 61 ++++++++++++++++ tests/e2e/rewrites/mod.rs | 2 + 12 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_sub_states.rs create mode 100644 docs/proc_attributes/rewrites/auto_sub_states.md create mode 100644 tests/e2e/rewrites/auto_states.rs create mode 100644 tests/e2e/rewrites/auto_sub_states.rs diff --git a/crates/bevy_auto_plugin_proc_macros/src/lib.rs b/crates/bevy_auto_plugin_proc_macros/src/lib.rs index ca1ae1dc..8ee617ca 100644 --- a/crates/bevy_auto_plugin_proc_macros/src/lib.rs +++ b/crates/bevy_auto_plugin_proc_macros/src/lib.rs @@ -126,6 +126,12 @@ pub fn auto_states(attr: CompilerStream, input: CompilerStream) -> CompilerStrea handle_attribute(expand::attr::auto_states, attr, input) } +/// Automatically registers item as `SubStates` for the Bevy `App`. +#[proc_macro_attribute] +pub fn auto_sub_states(attr: CompilerStream, input: CompilerStream) -> CompilerStream { + handle_attribute(expand::attr::auto_sub_states, attr, input) +} + /// Automatically adds the `fn` as a `System` for the Bevy `App`. #[proc_macro_attribute] pub fn auto_system(attr: CompilerStream, input: CompilerStream) -> CompilerStream { diff --git a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs index 2eea4a53..05d79be5 100644 --- a/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/__private/expand/attr/mod.rs @@ -52,4 +52,5 @@ gen_rewrite_outers! { auto_message => IaMessage, auto_observer => IaObserver, auto_states => IaState, + auto_sub_states => IaSubState, } diff --git a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs index 555f61f6..372ce43a 100644 --- a/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs +++ b/crates/bevy_auto_plugin_shared/src/codegen/tokens.rs @@ -82,6 +82,11 @@ pub fn derive_states_path() -> NonEmptyPath { parse_quote!(#states::state::States) } +pub fn derive_sub_states_path() -> NonEmptyPath { + let states = crate::__private::paths::state::root_path(); + parse_quote!(#states::state::SubStates) +} + pub fn derive_component<'a>( extra_items: impl IntoIterator, ) -> TokenStream { @@ -151,6 +156,28 @@ pub fn derive_states<'a>(extra_items: impl IntoIterator )], } } +pub fn derive_sub_states<'a>( + extra_items: impl IntoIterator, +) -> ExpandAttrs { + ExpandAttrs { + use_items: vec![crate::__private::paths::state::derive_use_tokens()], + attrs: vec![derive_from( + [ + vec![ + &derive_sub_states_path(), + &parse_quote!(Debug), + &parse_quote!(Default), + &parse_quote!(Clone), + &parse_quote!(PartialEq), + &parse_quote!(Eq), + &parse_quote!(Hash), + ], + extra_items.into_iter().collect::>(), + ] + .concat(), + )], + } +} pub fn derive_reflect() -> TokenStream { let derive_reflect_path = derive_reflect_path(); quote! { #[derive(#derive_reflect_path)] } @@ -166,6 +193,9 @@ pub fn use_bevy_state_app_ext_states() -> syn::ItemUse { pub fn auto_register_type(args: RegisterTypeAttrEmitter) -> TokenStream { args.to_token_stream() } +pub fn auto_register_state_type(args: RegisterStateTypeAttrEmitter) -> TokenStream { + args.to_token_stream() +} pub fn auto_name(args: NameAttrEmitter) -> TokenStream { args.to_token_stream() } @@ -175,6 +205,9 @@ pub fn auto_init_resource(args: InitResourceAttrEmitter) -> TokenStream { pub fn auto_init_states(args: InitStateAttrEmitter) -> TokenStream { args.to_token_stream() } +pub fn auto_init_sub_states(args: InitSubStateAttrEmitter) -> TokenStream { + args.to_token_stream() +} pub fn auto_add_systems(args: AddSystemAttrEmitter) -> TokenStream { args.to_token_stream() } diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs index 231fffee..0cc673e8 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_states.rs @@ -32,6 +32,12 @@ impl<'a> From<&'a StatesArgs> for RegisterTypeArgs { } } +impl<'a> From<&'a StatesArgs> for RegisterStateTypeArgs { + fn from(_value: &'a StatesArgs) -> Self { + Self::default() + } +} + impl<'a> From<&'a StatesArgs> for InitStateArgs { fn from(_value: &'a StatesArgs) -> Self { Self::default() @@ -53,6 +59,7 @@ impl AttrExpansionEmitterToExpandAttr for StateAttrExpandEmitter { } if self.args.args.base.register { expand_attrs.attrs.push(tokens::auto_register_type(self.into())); + expand_attrs.attrs.push(tokens::auto_register_state_type(self.into())); } if self.args.args.base.init { expand_attrs.attrs.push(tokens::auto_init_states(self.into())); @@ -60,4 +67,4 @@ impl AttrExpansionEmitterToExpandAttr for StateAttrExpandEmitter { } } -impl_from_default!(StatesArgs => (RegisterTypeArgs, InitStateArgs)); +impl_from_default!(StatesArgs => (RegisterTypeArgs, RegisterStateTypeArgs, InitStateArgs)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_sub_states.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_sub_states.rs new file mode 100644 index 00000000..f88a8b0b --- /dev/null +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/auto_sub_states.rs @@ -0,0 +1,73 @@ +use crate::{ + codegen::{ + ExpandAttrs, + tokens, + }, + macro_api::prelude::*, + syntax::{ + ast::flag_or_list::FlagOrList, + validated::non_empty_path::NonEmptyPath, + }, + util::macros::impl_from_default, +}; +use darling::FromMeta; +use proc_macro2::Ident; + +#[derive(FromMeta, Debug, Default, Clone, PartialEq, Hash)] +#[darling(derive_syn_parse, default)] +pub struct SubStatesArgs { + pub derive: FlagOrList, + pub reflect: FlagOrList, + pub register: bool, + pub init: bool, +} + +impl AttributeIdent for SubStatesArgs { + const IDENT: &'static str = "auto_sub_states"; +} + +impl<'a> From<&'a SubStatesArgs> for RegisterTypeArgs { + fn from(_value: &'a SubStatesArgs) -> Self { + Self::default() + } +} + +impl<'a> From<&'a SubStatesArgs> for RegisterStateTypeArgs { + fn from(_value: &'a SubStatesArgs) -> Self { + Self::default() + } +} + +impl<'a> From<&'a SubStatesArgs> for InitSubStateArgs { + fn from(_value: &'a SubStatesArgs) -> Self { + Self::default() + } +} + +pub type IaSubState = + ItemAttribute, AllowStructOrEnum>; + +pub type SubStateAttrExpandEmitter = AttrExpansionEmitter; + +impl AttrExpansionEmitterToExpandAttr for SubStateAttrExpandEmitter { + fn to_expand_attrs(&self, expand_attrs: &mut ExpandAttrs) { + if self.args.args.base.derive.present { + expand_attrs.append(tokens::derive_sub_states(&self.args.args.base.derive.items)); + } + if self.args.args.base.reflect.present { + if self.args.args.base.derive.present { + expand_attrs.attrs.push(tokens::derive_reflect()); + } + expand_attrs.append(tokens::reflect(&self.args.args.base.reflect.items)) + } + if self.args.args.base.register { + expand_attrs.attrs.push(tokens::auto_register_type(self.into())); + expand_attrs.attrs.push(tokens::auto_register_state_type(self.into())); + } + if self.args.args.base.init { + expand_attrs.attrs.push(tokens::auto_init_sub_states(self.into())); + } + } +} + +impl_from_default!(SubStatesArgs => (RegisterTypeArgs, RegisterStateTypeArgs, InitSubStateArgs)); diff --git a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/mod.rs b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/mod.rs index fb09b5cc..ca9210b1 100644 --- a/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/mod.rs +++ b/crates/bevy_auto_plugin_shared/src/macro_api/attributes/rewrites/mod.rs @@ -4,6 +4,7 @@ mod auto_message; mod auto_observer; mod auto_resource; mod auto_states; +mod auto_sub_states; mod auto_system; pub mod prelude { @@ -14,5 +15,6 @@ pub mod prelude { pub use auto_observer::*; pub use auto_resource::*; pub use auto_states::*; + pub use auto_sub_states::*; pub use auto_system::*; } diff --git a/docs/proc_attributes/rewrites/auto_states.md b/docs/proc_attributes/rewrites/auto_states.md index 3499bae6..f740c6d5 100644 --- a/docs/proc_attributes/rewrites/auto_states.md +++ b/docs/proc_attributes/rewrites/auto_states.md @@ -18,7 +18,7 @@ Automatically initializes a state in the app. Passes through any additional reflects listed. If enabled in tandem with `derive` it also includes `#[derive(Reflect)]` - `register` - Enables type registration for the `States` - Same as having `#[auto_register_type]` + Same as having `#[auto_register_type]` and `#[auto_register_state_type]` - `init` - Initializes the `States` with default values Same as having `#[auto_init_state]` diff --git a/docs/proc_attributes/rewrites/auto_sub_states.md b/docs/proc_attributes/rewrites/auto_sub_states.md new file mode 100644 index 00000000..318b1cea --- /dev/null +++ b/docs/proc_attributes/rewrites/auto_sub_states.md @@ -0,0 +1,48 @@ +Automatically initializes a sub-state in the app. + +# Parameters +- `plugin = PluginType` - Required. Specifies which plugin should initialize this state. +- `generics(T1, T2, ...)` - Optional. Specifies concrete types for generic parameters. + When provided, the states will be registered with these specific generic parameters. +- `derive` | `derive(Debug, Default, ..)` - Optional. Specifies that the macro should handle deriving `SubStates`. + Passes through any additional derives listed. + When enabled, `SubStates` include these additional derives: + - `SubStates` + - `Debug` + - `Default` + - `Clone` + - `PartialEq` + - `Eq` + - `Hash` +- `reflect` | `reflect(Debug, Default, ..)` - Optional. Specifies that the macro should handle emitting the single `#[reflect(...)]`. + Passes through any additional reflects listed. + If enabled in tandem with `derive` it also includes `#[derive(Reflect)]` +- `register` - Enables type registration for the `SubStates` + Same as having `#[auto_register_type]` and `#[auto_register_state_type]` +- `init` - Initializes the `SubStates` with default values + Same as having `#[auto_init_sub_state]` + +# Example +```rust +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct MyPlugin; + +#[auto_states(plugin = MyPlugin, derive, init)] +enum MainState { + #[default] + InGame, + Menu, +} + +#[auto_sub_states(plugin = MyPlugin, derive, init)] +#[source(MainState = MainState::InGame)] +enum InGameState { + #[default] + Playing, + Paused, +} +``` diff --git a/src/lib.rs b/src/lib.rs index 92631f2e..0b4c45f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -172,6 +172,9 @@ pub mod prelude { #[doc = include_str!("../docs/proc_attributes/rewrites/auto_states.md")] pub use bevy_auto_plugin_proc_macros::auto_states; + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_sub_states.md")] + pub use bevy_auto_plugin_proc_macros::auto_sub_states; + #[doc = include_str!("../docs/proc_attributes/rewrites/auto_system.md")] pub use bevy_auto_plugin_proc_macros::auto_system; diff --git a/tests/e2e/rewrites/auto_states.rs b/tests/e2e/rewrites/auto_states.rs new file mode 100644 index 00000000..c22782b1 --- /dev/null +++ b/tests/e2e/rewrites/auto_states.rs @@ -0,0 +1,45 @@ +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; +use bevy_state::app::StatesPlugin; +use internal_test_proc_macro::xtest; +use internal_test_util::type_id_of; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct Test; + +#[auto_states(plugin = Test, derive, reflect, register, init)] +enum FooState { + #[default] + Start, + End, +} + +fn app() -> App { + let mut app = App::new(); + app.add_plugins(StatesPlugin); + app.add_plugins(Test); + app +} + +#[xtest] +fn test_auto_init_state() { + let app = app(); + assert_eq!(app.world().resource::>().get(), &FooState::Start); +} + +#[xtest] +fn test_auto_register_types() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!(type_registry.contains(type_id_of::()), "did not auto register type"); + assert!( + type_registry.contains(type_id_of::>()), + "did not auto register State type" + ); + assert!( + type_registry.contains(type_id_of::>()), + "did not auto register NextState type" + ); +} diff --git a/tests/e2e/rewrites/auto_sub_states.rs b/tests/e2e/rewrites/auto_sub_states.rs new file mode 100644 index 00000000..e89630aa --- /dev/null +++ b/tests/e2e/rewrites/auto_sub_states.rs @@ -0,0 +1,61 @@ +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; +use bevy_state::app::StatesPlugin; +use internal_test_proc_macro::xtest; +use internal_test_util::type_id_of; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct Test; + +#[auto_states(plugin = Test, derive, reflect, register, init)] +enum FooState { + #[default] + Start, + End, +} + +#[auto_sub_states(plugin = Test, derive, reflect, register, init)] +#[source(FooState = FooState::End)] +enum BarState { + #[default] + A, + B, +} + +fn app() -> App { + let mut app = App::new(); + app.add_plugins(StatesPlugin); + app.add_plugins(Test); + app +} + +#[xtest] +fn test_auto_init_state() { + let mut app = app(); + assert_eq!(app.world().get_resource::>().map(State::get), None); + + app.world_mut().resource_mut::>().set(FooState::End); + app.update(); + assert_eq!(app.world().get_resource::>().map(State::get), Some(&BarState::A)); + + app.world_mut().resource_mut::>().set(FooState::Start); + app.update(); + assert_eq!(app.world().get_resource::>().map(State::get), None); +} + +#[xtest] +fn test_auto_register_types() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!(type_registry.contains(type_id_of::()), "did not auto register type"); + assert!( + type_registry.contains(type_id_of::>()), + "did not auto register State type" + ); + assert!( + type_registry.contains(type_id_of::>()), + "did not auto register NextState type" + ); +} diff --git a/tests/e2e/rewrites/mod.rs b/tests/e2e/rewrites/mod.rs index 859c775f..92819d2d 100644 --- a/tests/e2e/rewrites/mod.rs +++ b/tests/e2e/rewrites/mod.rs @@ -1 +1,3 @@ mod auto_component; +mod auto_states; +mod auto_sub_states; From 19b2c776e14b788f8f142f6d57ec9b5028522bda Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 6 Jan 2026 22:21:56 -0500 Subject: [PATCH 161/162] chore: drop `rust-version` field from Cargo.toml --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index dcdb9cce..01eb7f78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,6 @@ repository = "https://github.com/StrikeForceZero/bevy_auto_plugin" license = "MIT OR Apache-2.0" description = "Procedural attribute macros for Bevy apps that reduce boilerplate by automatically registering components, resources, events, states, and systems in your plugin's build function." edition = "2024" -rust-version = "1.88" publish = true [features] From 2f706d17c4310255fd5df32e56a39882c5fce7eb Mon Sep 17 00:00:00 2001 From: bstriker Date: Tue, 6 Jan 2026 23:19:01 -0500 Subject: [PATCH 162/162] chore(tests): add e2e tests for rewrites: component, event, message, observer, resource, and system --- tests/e2e/rewrites/auto_component.rs | 26 ++++++++++++ tests/e2e/rewrites/auto_event.rs | 58 ++++++++++++++++++++++++++ tests/e2e/rewrites/auto_message.rs | 45 ++++++++++++++++++++ tests/e2e/rewrites/auto_observer.rs | 33 +++++++++++++++ tests/e2e/rewrites/auto_resource.rs | 48 ++++++++++++++++++++++ tests/e2e/rewrites/auto_system.rs | 61 ++++++++++++++++++++++++++++ tests/e2e/rewrites/mod.rs | 5 +++ 7 files changed, 276 insertions(+) create mode 100644 tests/e2e/rewrites/auto_event.rs create mode 100644 tests/e2e/rewrites/auto_message.rs create mode 100644 tests/e2e/rewrites/auto_observer.rs create mode 100644 tests/e2e/rewrites/auto_resource.rs create mode 100644 tests/e2e/rewrites/auto_system.rs diff --git a/tests/e2e/rewrites/auto_component.rs b/tests/e2e/rewrites/auto_component.rs index 6d3ebea7..d4a1e6ba 100644 --- a/tests/e2e/rewrites/auto_component.rs +++ b/tests/e2e/rewrites/auto_component.rs @@ -16,6 +16,9 @@ struct Test; #[auto_component(plugin = Test, derive, register, reflect, auto_name)] struct FooComponent; +#[auto_component(plugin = Test, generics(usize), derive, register, reflect, auto_name)] +struct GenericComponent(T); + fn app() -> App { let mut app = create_minimal_app(); app.add_plugins(StatesPlugin); @@ -31,6 +34,17 @@ fn test_auto_register_type_foo_component() { assert!(type_registry.contains(type_id_of::()), "did not auto register type"); } +#[xtest] +fn test_auto_register_type_generic_component() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!( + type_registry.contains(type_id_of::>()), + "did not auto register generic type" + ); +} + #[xtest] fn test_auto_name_foo_component() { let mut app = app(); @@ -42,3 +56,15 @@ fn test_auto_name_foo_component() { .expect("failed to query FooComponent"); assert_eq!(name, &Name::new("FooComponent"), "did not auto name FooComponent"); } + +#[xtest] +fn test_auto_name_generic_component() { + let mut app = app(); + app.world_mut().spawn(GenericComponent(10usize)); + let name = app + .world_mut() + .query_filtered::<&Name, With>>() + .single(app.world()) + .expect("failed to query GenericComponent"); + assert_eq!(name, &Name::new("GenericComponent"), "did not auto name GenericComponent"); +} diff --git a/tests/e2e/rewrites/auto_event.rs b/tests/e2e/rewrites/auto_event.rs new file mode 100644 index 00000000..26626567 --- /dev/null +++ b/tests/e2e/rewrites/auto_event.rs @@ -0,0 +1,58 @@ +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; +use internal_test_proc_macro::xtest; +use internal_test_util::{ + create_minimal_app, + type_id_of, +}; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct Test; + +#[auto_event(plugin = Test, target(global), derive(Debug, Default, PartialEq), reflect, register)] +struct FooGlobalEvent(usize); + +#[auto_event(plugin = Test, target(entity), derive(Debug, PartialEq), reflect, register)] +struct FooEntityEvent(#[event_target] Entity); + +fn app() -> App { + let mut app = create_minimal_app(); + app.add_plugins(Test); + app +} + +#[xtest] +fn test_auto_register_type_foo_global_event() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!( + type_registry.contains(type_id_of::()), + "did not auto register global event type" + ); +} + +#[xtest] +fn test_auto_register_type_foo_entity_event() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!( + type_registry.contains(type_id_of::()), + "did not auto register entity event type" + ); +} + +#[xtest] +fn test_global_event_trigger() { + let mut app = app(); + app.world_mut().trigger(FooGlobalEvent(42)); +} + +#[xtest] +fn test_entity_event_trigger() { + let mut app = app(); + let entity = app.world_mut().spawn_empty().id(); + app.world_mut().trigger(FooEntityEvent(entity)); +} diff --git a/tests/e2e/rewrites/auto_message.rs b/tests/e2e/rewrites/auto_message.rs new file mode 100644 index 00000000..456e9a88 --- /dev/null +++ b/tests/e2e/rewrites/auto_message.rs @@ -0,0 +1,45 @@ +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; +use internal_test_proc_macro::xtest; +use internal_test_util::{ + create_minimal_app, + type_id_of, +}; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct Test; + +#[auto_message(plugin = Test, derive(Debug, Default, PartialEq), reflect, register)] +struct FooMessage(usize); + +#[auto_message(plugin = Test, generics(usize), derive(Debug, Default, PartialEq), reflect, register)] +struct GenericMessage(T); + +fn app() -> App { + let mut app = create_minimal_app(); + app.add_plugins(Test); + app +} + +#[xtest] +fn test_auto_register_type_foo_message() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!( + type_registry.contains(type_id_of::()), + "did not auto register message type" + ); +} + +#[xtest] +fn test_auto_register_type_generic_message() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!( + type_registry.contains(type_id_of::>()), + "did not auto register generic message type" + ); +} diff --git a/tests/e2e/rewrites/auto_observer.rs b/tests/e2e/rewrites/auto_observer.rs new file mode 100644 index 00000000..3fb3db12 --- /dev/null +++ b/tests/e2e/rewrites/auto_observer.rs @@ -0,0 +1,33 @@ +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; +use internal_test_proc_macro::xtest; +use internal_test_util::create_minimal_app; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct Test; + +#[derive(Component)] +struct Foo; + +#[derive(Resource, Default)] +struct ObserverCount(usize); + +#[auto_observer(plugin = Test)] +fn foo_observer(_trigger: On, mut count: ResMut) { + count.0 += 1; +} + +fn app() -> App { + let mut app = create_minimal_app(); + app.init_resource::(); + app.add_plugins(Test); + app +} + +#[xtest] +fn test_auto_observer() { + let mut app = app(); + app.world_mut().spawn(Foo); + assert_eq!(app.world().resource::().0, 1); +} diff --git a/tests/e2e/rewrites/auto_resource.rs b/tests/e2e/rewrites/auto_resource.rs new file mode 100644 index 00000000..9ec40f29 --- /dev/null +++ b/tests/e2e/rewrites/auto_resource.rs @@ -0,0 +1,48 @@ +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; +use internal_test_proc_macro::xtest; +use internal_test_util::{ + create_minimal_app, + type_id_of, +}; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct Test; + +#[auto_resource(plugin = Test, derive(Debug, Default, PartialEq), reflect, register, init)] +struct FooResource(usize); + +#[auto_resource(plugin = Test, generics(usize), derive(Debug, Default, PartialEq), reflect, register, init)] +struct GenericResource(T); + +fn app() -> App { + let mut app = create_minimal_app(); + app.add_plugins(Test); + app +} + +#[xtest] +fn test_auto_register_type_foo_resource() { + let app = app(); + let type_registry = app.world().resource::().0.clone(); + let type_registry = type_registry.read(); + assert!( + type_registry.contains(type_id_of::()), + "did not auto register resource type" + ); +} + +#[xtest] +fn test_auto_init_resource() { + let app = app(); + assert!(app.world().contains_resource::()); + assert_eq!(app.world().resource::().0, 0); +} + +#[xtest] +fn test_auto_init_generic_resource() { + let app = app(); + assert!(app.world().contains_resource::>()); + assert_eq!(app.world().resource::>().0, 0); +} diff --git a/tests/e2e/rewrites/auto_system.rs b/tests/e2e/rewrites/auto_system.rs new file mode 100644 index 00000000..8e632047 --- /dev/null +++ b/tests/e2e/rewrites/auto_system.rs @@ -0,0 +1,61 @@ +use bevy::prelude::*; +use bevy_auto_plugin::prelude::*; +use internal_test_proc_macro::xtest; +use internal_test_util::create_minimal_app; + +#[derive(AutoPlugin)] +#[auto_plugin(impl_plugin_trait)] +struct Test; + +#[derive(Resource, Default)] +struct SystemCounter(Vec<&'static str>); + +#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone)] +enum TestSet { + Set, +} + +#[auto_system(plugin = Test, schedule = Update)] +fn basic_system(mut counter: ResMut) { + counter.0.push("basic"); +} + +#[auto_system(plugin = Test, schedule = Update, config(in_set = TestSet::Set))] +fn set_system(mut counter: ResMut) { + counter.0.push("set"); +} + +#[auto_system(plugin = Test, schedule = Update, config(after = basic_system))] +fn after_system(mut counter: ResMut) { + counter.0.push("after"); +} + +#[auto_system(plugin = Test, schedule = Update, generics(usize))] +fn generic_system(mut counter: ResMut) { + counter.0.push("generic"); +} + +fn app() -> App { + let mut app = create_minimal_app(); + app.init_resource::(); + app.configure_sets(Update, TestSet::Set); + app.add_plugins(Test); + app +} + +#[xtest] +fn test_auto_systems() { + let mut app = app(); + app.update(); + let counter = &app.world().resource::().0; + assert!(counter.contains(&"basic"), "did not auto register basic system"); + assert!(counter.contains(&"set"), "did not auto register set system"); + assert!(counter.contains(&"after"), "did not auto register after system"); + assert!(counter.contains(&"generic"), "did not auto register generic system"); + assert_eq!(counter.len(), 4); + assert!( + counter.iter().position(|s| s == &"after").unwrap() + > counter.iter().position(|s| s == &"basic").unwrap(), + "after system not executed after basic system" + ); +} diff --git a/tests/e2e/rewrites/mod.rs b/tests/e2e/rewrites/mod.rs index 92819d2d..d69dbb81 100644 --- a/tests/e2e/rewrites/mod.rs +++ b/tests/e2e/rewrites/mod.rs @@ -1,3 +1,8 @@ mod auto_component; +mod auto_event; +mod auto_message; +mod auto_observer; +mod auto_resource; mod auto_states; mod auto_sub_states; +mod auto_system;