From cc609f32b1eef2d0f6fa947a2e078bdc8899a5bd Mon Sep 17 00:00:00 2001 From: targrub Date: Mon, 10 Oct 2022 20:59:38 +0000 Subject: [PATCH] Adding Debug implementations for App, Stage, Schedule, Query, QueryState, etc. (#6214) # Objective - Adding Debug implementations for App, Stage, Schedule, Query, QueryState. - Fixes #1130. ## Solution - Implemented std::fmt::Debug for a number of structures. --- ## Changelog Also added Debug implementations for ParallelSystemExecutor, SingleThreadedExecutor, various RunCriteria structures, SystemContainer, and SystemDescriptor. Opinions are sure to differ as to what information to provide in a Debug implementation. Best guess was taken for this initial version for these structures. Co-authored-by: targrub <62773321+targrub@users.noreply.github.com> --- crates/bevy_app/src/app.rs | 20 +++++ crates/bevy_ecs/src/query/state.rs | 11 +++ crates/bevy_ecs/src/schedule/executor.rs | 9 ++- crates/bevy_ecs/src/schedule/mod.rs | 2 +- crates/bevy_ecs/src/schedule/run_criteria.rs | 58 ++++++++++++++- crates/bevy_ecs/src/schedule/stage.rs | 73 ++++++++++++++++++- .../bevy_ecs/src/schedule/system_container.rs | 7 ++ .../src/schedule/system_descriptor.rs | 3 +- crates/bevy_ecs/src/system/query.rs | 6 ++ crates/bevy_ecs/src/system/system.rs | 19 +++++ 10 files changed, 202 insertions(+), 6 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index e71cda2229307..25c2271365544 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -70,12 +70,32 @@ pub struct App { sub_apps: HashMap, } +impl Debug for App { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "App {{ sub_apps: ")?; + f.debug_map() + .entries(self.sub_apps.iter().map(|(k, v)| (k, v))) + .finish()?; + write!(f, "}}") + } +} + /// Each `SubApp` has its own [`Schedule`] and [`World`], enabling a separation of concerns. struct SubApp { app: App, runner: Box, } +impl Debug for SubApp { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "SubApp {{ app: ")?; + f.debug_map() + .entries(self.app.sub_apps.iter().map(|(k, v)| (k, v))) + .finish()?; + write!(f, "}}") + } +} + impl Default for App { fn default() -> Self { let mut app = App::empty(); diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 262e0bcd9fa0c..80326b586ca46 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -35,6 +35,17 @@ pub struct QueryState { pub(crate) filter_state: F::State, } +impl std::fmt::Debug for QueryState { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "QueryState matched_table_ids: {} matched_archetype_ids: {}", + self.matched_table_ids.len(), + self.matched_archetype_ids.len() + ) + } +} + impl FromWorld for QueryState { fn from_world(world: &mut World) -> Self { world.query_filtered() diff --git a/crates/bevy_ecs/src/schedule/executor.rs b/crates/bevy_ecs/src/schedule/executor.rs index 4e649d47086f9..ef0cb45fb229d 100644 --- a/crates/bevy_ecs/src/schedule/executor.rs +++ b/crates/bevy_ecs/src/schedule/executor.rs @@ -1,4 +1,5 @@ use crate::{schedule::SystemContainer, world::World}; +use core::fmt::Debug; use downcast_rs::{impl_downcast, Downcast}; pub trait ParallelSystemExecutor: Downcast + Send + Sync { @@ -8,9 +9,15 @@ pub trait ParallelSystemExecutor: Downcast + Send + Sync { fn run_systems(&mut self, systems: &mut [SystemContainer], world: &mut World); } +impl Debug for dyn ParallelSystemExecutor { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "dyn ParallelSystemExecutor") + } +} + impl_downcast!(ParallelSystemExecutor); -#[derive(Default)] +#[derive(Debug, Default)] pub struct SingleThreadedExecutor; impl ParallelSystemExecutor for SingleThreadedExecutor { diff --git a/crates/bevy_ecs/src/schedule/mod.rs b/crates/bevy_ecs/src/schedule/mod.rs index a6d41240e96f4..8f0e6edf2c906 100644 --- a/crates/bevy_ecs/src/schedule/mod.rs +++ b/crates/bevy_ecs/src/schedule/mod.rs @@ -37,7 +37,7 @@ use bevy_utils::HashMap; /// In this way, the properties of the child schedule can be set differently from the parent. /// For example, it can be set to run only once during app execution, while the parent schedule /// runs indefinitely. -#[derive(Default)] +#[derive(Debug, Default)] pub struct Schedule { stages: HashMap>, stage_order: Vec, diff --git a/crates/bevy_ecs/src/schedule/run_criteria.rs b/crates/bevy_ecs/src/schedule/run_criteria.rs index 575a63080d3fc..8bfd84bf04c22 100644 --- a/crates/bevy_ecs/src/schedule/run_criteria.rs +++ b/crates/bevy_ecs/src/schedule/run_criteria.rs @@ -1,8 +1,10 @@ use crate::{ + prelude::System, schedule::{GraphNode, RunCriteriaLabel, RunCriteriaLabelId}, system::{BoxedSystem, IntoSystem, Local}, world::World, }; +use core::fmt::Debug; use std::borrow::Cow; /// Determines whether a system should be executed or not, and how many times it should be ran each @@ -66,7 +68,7 @@ impl From for ShouldRun { } } -#[derive(Default)] +#[derive(Debug, Default)] pub(crate) struct BoxedRunCriteria { criteria_system: Option>, initialized: bool, @@ -93,6 +95,7 @@ impl BoxedRunCriteria { } } +#[derive(Debug)] pub(crate) enum RunCriteriaInner { Single(BoxedSystem<(), ShouldRun>), Piped { @@ -101,6 +104,7 @@ pub(crate) enum RunCriteriaInner { }, } +#[derive(Debug)] pub(crate) struct RunCriteriaContainer { pub(crate) should_run: ShouldRun, pub(crate) inner: RunCriteriaInner, @@ -165,17 +169,19 @@ impl GraphNode for RunCriteriaContainer { } } +#[derive(Debug)] pub enum RunCriteriaDescriptorOrLabel { Descriptor(RunCriteriaDescriptor), Label(RunCriteriaLabelId), } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub(crate) enum DuplicateLabelStrategy { Panic, Discard, } +#[derive(Debug)] pub struct RunCriteriaDescriptor { pub(crate) system: RunCriteriaSystem, pub(crate) label: Option, @@ -184,6 +190,7 @@ pub struct RunCriteriaDescriptor { pub(crate) after: Vec, } +#[derive(Debug)] pub(crate) enum RunCriteriaSystem { Single(BoxedSystem<(), ShouldRun>), Piped(BoxedSystem), @@ -326,6 +333,7 @@ where } } +#[derive(Debug)] pub struct RunCriteria { label: RunCriteriaLabelId, } @@ -346,3 +354,49 @@ impl RunCriteria { } } } + +impl Debug for dyn System + 'static { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "System {} with In=(), Out=ShouldRun: {{{}}}", + self.name(), + { + if self.is_send() { + if self.is_exclusive() { + "is_send is_exclusive" + } else { + "is_send" + } + } else if self.is_exclusive() { + "is_exclusive" + } else { + "" + } + }, + ) + } +} + +impl Debug for dyn System + 'static { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "System {} with In=ShouldRun, Out=ShouldRun: {{{}}}", + self.name(), + { + if self.is_send() { + if self.is_exclusive() { + "is_send is_exclusive" + } else { + "is_send" + } + } else if self.is_exclusive() { + "is_exclusive" + } else { + "" + } + }, + ) + } +} diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index ff9479c715c37..bb14e63e05057 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -14,9 +14,10 @@ use crate::{ }; use bevy_ecs_macros::Resource; use bevy_utils::{tracing::warn, HashMap, HashSet}; +use core::fmt::Debug; use downcast_rs::{impl_downcast, Downcast}; -use super::IntoSystemDescriptor; +use super::{IntoSystemDescriptor, Schedule}; /// A type that can run as a step of a [`Schedule`](super::Schedule). pub trait Stage: Downcast + Send + Sync { @@ -25,6 +26,18 @@ pub trait Stage: Downcast + Send + Sync { fn run(&mut self, world: &mut World); } +impl Debug for dyn Stage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(as_systemstage) = self.as_any().downcast_ref::() { + write!(f, "{:?}", as_systemstage) + } else if let Some(as_schedule) = self.as_any().downcast_ref::() { + write!(f, "{:?}", as_schedule) + } else { + write!(f, "Unknown dyn Stage") + } + } +} + impl_downcast!(Stage); /// When this resource is present in the `App`'s `Resources`, @@ -584,6 +597,64 @@ impl SystemStage { } Ok(labels) } + + pub fn vec_system_container_debug( + &self, + name: &str, + v: &Vec, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + write!(f, "{}: ", name)?; + if v.len() > 1 { + writeln!(f, "[")?; + for sc in v.iter() { + writeln!(f, "{:?},", sc)?; + } + write!(f, "], ") + } else { + write!(f, "{:?}, ", v) + } + } +} + +impl std::fmt::Debug for SystemStage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "SystemStage: {{ ")?; + write!( + f, + "world_id: {:?}, executor: {:?}, stage_run_criteria: {:?}, run_criteria: {:?}, ", + self.world_id, self.executor, self.stage_run_criteria, self.run_criteria + )?; + self.vec_system_container_debug("exclusive_at_start", &self.exclusive_at_start, f)?; + self.vec_system_container_debug( + "exclusive_before_commands", + &self.exclusive_before_commands, + f, + )?; + self.vec_system_container_debug("exclusive_at_end", &self.exclusive_at_end, f)?; + self.vec_system_container_debug("parallel", &self.parallel, f)?; + write!( + f, + "systems_modified: {:?}, uninitialized_run_criteria: {:?}, ", + self.systems_modified, self.uninitialized_run_criteria + )?; + write!( + f, + "uninitialized_at_start: {:?}, uninitialized_before_commands: {:?}, ", + self.uninitialized_at_start, self.uninitialized_before_commands + )?; + write!( + f, + "uninitialized_at_end: {:?}, uninitialized_parallel: {:?}, ", + self.uninitialized_at_end, self.uninitialized_parallel + )?; + write!( + f, + "last_tick_check: {:?}, apply_buffers: {:?}, ", + self.last_tick_check, self.apply_buffers + )?; + write!(f, "must_read_resource: {:?}}}", self.must_read_resource) + } } /// Sorts given system containers topologically, populates their resolved dependencies diff --git a/crates/bevy_ecs/src/schedule/system_container.rs b/crates/bevy_ecs/src/schedule/system_container.rs index 9083ad37c5a2f..4178d14c24c38 100644 --- a/crates/bevy_ecs/src/schedule/system_container.rs +++ b/crates/bevy_ecs/src/schedule/system_container.rs @@ -6,6 +6,7 @@ use crate::{ }, system::System, }; +use core::fmt::Debug; use std::borrow::Cow; pub struct SystemContainer { @@ -83,6 +84,12 @@ impl SystemContainer { } } +impl Debug for SystemContainer { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{{{:?}}}", &self.system()) + } +} + impl GraphNode for SystemContainer { type Label = SystemLabelId; diff --git a/crates/bevy_ecs/src/schedule/system_descriptor.rs b/crates/bevy_ecs/src/schedule/system_descriptor.rs index 8d0d87b9d9a47..8628069e9042a 100644 --- a/crates/bevy_ecs/src/schedule/system_descriptor.rs +++ b/crates/bevy_ecs/src/schedule/system_descriptor.rs @@ -4,7 +4,7 @@ use crate::{ }; /// Configures ambiguity detection for a single system. -#[derive(Default)] +#[derive(Debug, Default)] pub(crate) enum AmbiguityDetection { #[default] Check, @@ -41,6 +41,7 @@ pub(crate) enum AmbiguityDetection { /// .with_system(do_the_other_thing.after(Something)) /// .with_system(do_something_else.at_end()); /// ``` +#[derive(Debug)] pub struct SystemDescriptor { pub(crate) system: BoxedSystem<(), ()>, pub(crate) exclusive_insertion_point: Option, diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index ce6cc2e470151..43542e0f114a7 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -280,6 +280,12 @@ pub struct Query<'world, 'state, Q: WorldQuery, F: ReadOnlyWorldQuery = ()> { pub(crate) change_tick: u32, } +impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> std::fmt::Debug for Query<'w, 's, Q, F> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Query {{ matched entities: {}, world: {:?}, state: {:?}, last_change_tick: {}, change_tick: {} }}", self.iter().count(), self.world, self.state, self.last_change_tick, self.change_tick) + } +} + impl<'w, 's, Q: WorldQuery, F: ReadOnlyWorldQuery> Query<'w, 's, Q, F> { /// Creates a new query. /// diff --git a/crates/bevy_ecs/src/system/system.rs b/crates/bevy_ecs/src/system/system.rs index 354d4aa1b0dd7..43fcdb41dd3cb 100644 --- a/crates/bevy_ecs/src/system/system.rs +++ b/crates/bevy_ecs/src/system/system.rs @@ -1,4 +1,5 @@ use bevy_utils::tracing::warn; +use core::fmt::Debug; use crate::{ archetype::ArchetypeComponentId, change_detection::MAX_CHANGE_AGE, component::ComponentId, @@ -95,3 +96,21 @@ pub(crate) fn check_system_change_tick( *last_change_tick = change_tick.wrapping_sub(MAX_CHANGE_AGE); } } + +impl Debug for dyn System { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "System {}: {{{}}}", self.name(), { + if self.is_send() { + if self.is_exclusive() { + "is_send is_exclusive" + } else { + "is_send" + } + } else if self.is_exclusive() { + "is_exclusive" + } else { + "" + } + },) + } +}