Skip to content

Commit 9e0c66b

Browse files
Ecs derive docs (#19892)
# Objective Concise syntax docs on `Component`/`Event` derives. Partial fix for #19537. ## Solution Only document syntax. The doc tests are set to ignore because the macro relies on the presence of `bevy_ecs`.
1 parent d05c435 commit 9e0c66b

File tree

2 files changed

+100
-3
lines changed

2 files changed

+100
-3
lines changed

crates/bevy_ecs/macros/src/component.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ pub fn derive_resource(input: TokenStream) -> TokenStream {
115115
})
116116
}
117117

118+
/// Component derive syntax is documented on both the macro and the trait.
118119
pub fn derive_component(input: TokenStream) -> TokenStream {
119120
let mut ast = parse_macro_input!(input as DeriveInput);
120121
let bevy_ecs_path: Path = crate::bevy_ecs_path();
@@ -453,7 +454,11 @@ pub const MAP_ENTITIES: &str = "map_entities";
453454
pub const IMMUTABLE: &str = "immutable";
454455
pub const CLONE_BEHAVIOR: &str = "clone_behavior";
455456

456-
/// All allowed attribute value expression kinds for component hooks
457+
/// All allowed attribute value expression kinds for component hooks.
458+
/// This doesn't simply use general expressions because of conflicting needs:
459+
/// - we want to be able to use `Self` & generic parameters in paths
460+
/// - call expressions producing a closure need to be wrapped in a function
461+
/// to turn them into function pointers, which prevents access to the outer generic params
457462
#[derive(Debug)]
458463
enum HookAttributeKind {
459464
/// expressions like function or struct names

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,17 @@ pub fn derive_event(input: TokenStream) -> TokenStream {
560560
component::derive_event(input)
561561
}
562562

563-
/// Implement the `EntityEvent` trait.
563+
/// Cheat sheet for derive syntax,
564+
/// see full explanation on `EntityEvent` trait docs.
565+
///
566+
/// ```ignore
567+
/// #[derive(Event, EntityEvent)]
568+
/// /// Traversal component
569+
/// #[entity_event(traversal = &'static ChildOf)]
570+
/// /// Always propagate
571+
/// #[entity_event(auto_propagate)]
572+
/// struct MyEvent;
573+
/// ```
564574
#[proc_macro_derive(EntityEvent, attributes(entity_event))]
565575
pub fn derive_entity_event(input: TokenStream) -> TokenStream {
566576
component::derive_entity_event(input)
@@ -578,7 +588,89 @@ pub fn derive_resource(input: TokenStream) -> TokenStream {
578588
component::derive_resource(input)
579589
}
580590

581-
/// Implement the `Component` trait.
591+
/// Cheat sheet for derive syntax,
592+
/// see full explanation and examples on the `Component` trait doc.
593+
///
594+
/// ## Immutability
595+
/// ```ignore
596+
/// #[derive(Component)]
597+
/// #[component(immutable)]
598+
/// struct MyComponent;
599+
/// ```
600+
///
601+
/// ## Sparse instead of table-based storage
602+
/// ```ignore
603+
/// #[derive(Component)]
604+
/// #[component(storage = "SparseSet")]
605+
/// struct MyComponent;
606+
/// ```
607+
///
608+
/// ## Required Components
609+
///
610+
/// ```ignore
611+
/// #[derive(Component)]
612+
/// #[require(
613+
/// // `Default::default()`
614+
/// A,
615+
/// // tuple structs
616+
/// B(1),
617+
/// // named-field structs
618+
/// C {
619+
/// x: 1,
620+
/// ..default()
621+
/// },
622+
/// // unit structs/variants
623+
/// D::One,
624+
/// // associated consts
625+
/// E::ONE,
626+
/// // constructors
627+
/// F::new(1),
628+
/// // arbitrary expressions
629+
/// G = make(1, 2, 3)
630+
/// )]
631+
/// struct MyComponent;
632+
/// ```
633+
///
634+
/// ## Relationships
635+
/// ```ignore
636+
/// #[derive(Component)]
637+
/// #[relationship(relationship_target = Children)]
638+
/// pub struct ChildOf {
639+
/// // Marking the field is not necessary if there is only one.
640+
/// #[relationship]
641+
/// pub parent: Entity,
642+
/// internal: u8,
643+
/// };
644+
///
645+
/// #[derive(Component)]
646+
/// #[relationship_target(relationship = ChildOf)]
647+
/// pub struct Children(Vec<Entity>);
648+
/// ```
649+
///
650+
/// On despawn, also despawn all related entities:
651+
/// ```ignore
652+
/// #[derive(Component)]
653+
/// #[relationship_target(relationship_target = Children, linked_spawn)]
654+
/// pub struct Children(Vec<Entity>);
655+
/// ```
656+
///
657+
/// ## Hooks
658+
/// ```ignore
659+
/// #[derive(Component)]
660+
/// #[component(hook_name = function)]
661+
/// struct MyComponent;
662+
/// ```
663+
/// where `hook_name` is `on_add`, `on_insert`, `on_replace` or `on_remove`;
664+
/// `function` can be either a path, e.g. `some_function::<Self>`,
665+
/// or a function call that returns a function that can be turned into
666+
/// a `ComponentHook`, e.g. `get_closure("Hi!")`.
667+
///
668+
/// ## Ignore this component when cloning an entity
669+
/// ```ignore
670+
/// #[derive(Component)]
671+
/// #[component(clone_behavior = Ignore)]
672+
/// struct MyComponent;
673+
/// ```
582674
#[proc_macro_derive(
583675
Component,
584676
attributes(component, require, relationship, relationship_target, entities)

0 commit comments

Comments
 (0)