Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - bevy_reflect: Improve debug formatting for reflected types #4218

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use syn::{Meta, NestedMeta, Path};

// The "special" trait idents that are used internally for reflection.
// Received via attributes like `#[reflect(PartialEq, Hash, ...)]`
const DEBUG_ATTR: &str = "Debug";
const PARTIAL_EQ_ATTR: &str = "PartialEq";
const HASH_ATTR: &str = "Hash";
const SERIALIZE_ATTR: &str = "Serialize";
Expand Down Expand Up @@ -46,6 +47,7 @@ impl Default for TraitImpl {
/// `Reflect` derive macro using the helper attribute: `#[reflect(...)]`.
///
/// The list of special traits are as follows:
/// * `Debug`
/// * `Hash`
/// * `PartialEq`
/// * `Serialize`
Expand Down Expand Up @@ -101,6 +103,7 @@ impl Default for TraitImpl {
///
#[derive(Default)]
pub(crate) struct ReflectTraits {
debug: TraitImpl,
hash: TraitImpl,
partial_eq: TraitImpl,
serialize: TraitImpl,
Expand All @@ -123,6 +126,7 @@ impl ReflectTraits {
};

match ident.as_str() {
DEBUG_ATTR => traits.debug = TraitImpl::Implemented,
PARTIAL_EQ_ATTR => traits.partial_eq = TraitImpl::Implemented,
HASH_ATTR => traits.hash = TraitImpl::Implemented,
SERIALIZE_ATTR => traits.serialize = TraitImpl::Implemented,
Expand All @@ -145,6 +149,7 @@ impl ReflectTraits {
// This should be the ident of the custom function
let trait_func_ident = TraitImpl::Custom(segment.ident.clone());
match ident.as_str() {
DEBUG_ATTR => traits.debug = trait_func_ident,
PARTIAL_EQ_ATTR => traits.partial_eq = trait_func_ident,
HASH_ATTR => traits.hash = trait_func_ident,
SERIALIZE_ATTR => traits.serialize = trait_func_ident,
Expand Down Expand Up @@ -239,6 +244,25 @@ impl ReflectTraits {
TraitImpl::NotImplemented => None,
}
}

/// Returns the implementation of `Reflect::debug` as a `TokenStream`.
///
/// If `Debug` was not registered, returns `None`.
pub fn get_debug_impl(&self) -> Option<proc_macro2::TokenStream> {
match &self.debug {
TraitImpl::Implemented => Some(quote! {
fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
}
}),
TraitImpl::Custom(impl_fn) => Some(quote! {
fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
#impl_fn(self, f)
}
}),
TraitImpl::NotImplemented => None,
}
}
}

impl Parse for ReflectTraits {
Expand Down
9 changes: 9 additions & 0 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream {
}
}
});
let debug_fn = derive_data.traits().get_debug_impl();

let get_type_registration_impl = derive_data.get_type_registration();
let (impl_generics, ty_generics, where_clause) = derive_data.generics().split_for_impl();
Expand Down Expand Up @@ -166,6 +167,8 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream {

#partial_eq_fn

#debug_fn

#serialize_fn
}
})
Expand Down Expand Up @@ -196,6 +199,7 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream
}
}
});
let debug_fn = derive_data.traits().get_debug_impl();

let (impl_generics, ty_generics, where_clause) = derive_data.generics().split_for_impl();
TokenStream::from(quote! {
Expand Down Expand Up @@ -291,6 +295,8 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream

#partial_eq_fn

#debug_fn

#serialize_fn
}
})
Expand All @@ -307,6 +313,7 @@ pub(crate) fn impl_value(
let hash_fn = reflect_traits.get_hash_impl(bevy_reflect_path);
let serialize_fn = reflect_traits.get_serialize_impl(bevy_reflect_path);
let partial_eq_fn = reflect_traits.get_partial_eq_impl(bevy_reflect_path);
let debug_fn = reflect_traits.get_debug_impl();

let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
TokenStream::from(quote! {
Expand Down Expand Up @@ -372,6 +379,8 @@ pub(crate) fn impl_value(

#partial_eq_fn

#debug_fn

#serialize_fn
}
})
Expand Down
27 changes: 27 additions & 0 deletions crates/bevy_reflect/src/array.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{serde::Serializable, Reflect, ReflectMut, ReflectRef};
use serde::ser::SerializeSeq;
use std::fmt::Debug;
use std::{
any::Any,
hash::{Hash, Hasher},
Expand Down Expand Up @@ -298,3 +299,29 @@ pub fn array_partial_eq<A: Array>(array: &A, reflect: &dyn Reflect) -> Option<bo

Some(true)
}

/// The default debug formatter for [`Array`] types.
///
/// # Example
/// ```
/// use bevy_reflect::Reflect;
///
/// let my_array: &dyn Reflect = &[1, 2, 3];
/// println!("{:#?}", my_array);
///
/// // Output:
///
/// // [
/// // 1,
/// // 2,
/// // 3,
/// // ]
/// ```
#[inline]
pub fn array_debug(dyn_array: &dyn Array, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut debug = f.debug_list();
for item in dyn_array.iter() {
debug.entry(&item as &dyn Debug);
}
debug.finish()
}
38 changes: 19 additions & 19 deletions crates/bevy_reflect/src/impls/glam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_struct, impl_ref
use glam::*;

impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct IVec2 {
x: i32,
y: i32,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct IVec3 {
x: i32,
y: i32,
z: i32,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct IVec4 {
x: i32,
y: i32,
Expand All @@ -31,22 +31,22 @@ impl_reflect_struct!(
);

impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct UVec2 {
x: u32,
y: u32,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct UVec3 {
x: u32,
y: u32,
z: u32,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct UVec4 {
x: u32,
y: u32,
Expand All @@ -56,30 +56,30 @@ impl_reflect_struct!(
);

impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct Vec2 {
x: f32,
y: f32,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct Vec3 {
x: f32,
y: f32,
z: f32,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct Vec3A {
x: f32,
y: f32,
z: f32,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct Vec4 {
x: f32,
y: f32,
Expand All @@ -89,22 +89,22 @@ impl_reflect_struct!(
);

impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct DVec2 {
x: f64,
y: f64,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct DVec3 {
x: f64,
y: f64,
z: f64,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct DVec4 {
x: f64,
y: f64,
Expand All @@ -114,15 +114,15 @@ impl_reflect_struct!(
);

impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct Mat3 {
x_axis: Vec3,
y_axis: Vec3,
z_axis: Vec3,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct Mat4 {
x_axis: Vec4,
y_axis: Vec4,
Expand All @@ -132,15 +132,15 @@ impl_reflect_struct!(
);

impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct DMat3 {
x_axis: DVec3,
y_axis: DVec3,
z_axis: DVec3,
}
);
impl_reflect_struct!(
#[reflect(PartialEq, Serialize, Deserialize, Default)]
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
struct DMat4 {
x_axis: DVec4,
y_axis: DVec4,
Expand All @@ -153,8 +153,8 @@ impl_reflect_struct!(
// mechanisms for read-only fields. I doubt those mechanisms would be added,
// so for now quaternions will remain as values. They are represented identically
// to Vec4 and DVec4, so you may use those instead and convert between.
impl_reflect_value!(Quat(PartialEq, Serialize, Deserialize, Default));
impl_reflect_value!(DQuat(PartialEq, Serialize, Deserialize, Default));
impl_reflect_value!(Quat(Debug, PartialEq, Serialize, Deserialize, Default));
impl_reflect_value!(DQuat(Debug, PartialEq, Serialize, Deserialize, Default));

impl_from_reflect_value!(Quat);
impl_from_reflect_value!(DQuat);
36 changes: 18 additions & 18 deletions crates/bevy_reflect/src/impls/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,27 @@ use std::{
ops::Range,
};

impl_reflect_value!(bool(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(char(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u8(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u16(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u32(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u64(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u128(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(usize(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i8(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i16(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i32(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i64(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i128(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(isize(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(f32(PartialEq, Serialize, Deserialize));
impl_reflect_value!(f64(PartialEq, Serialize, Deserialize));
impl_reflect_value!(String(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(bool(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(char(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u8(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u16(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u32(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u64(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(u128(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(usize(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i8(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i16(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i32(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i64(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(i128(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(isize(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(f32(Debug, PartialEq, Serialize, Deserialize));
impl_reflect_value!(f64(Debug, PartialEq, Serialize, Deserialize));
impl_reflect_value!(String(Debug, Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(Option<T: Serialize + Clone + for<'de> Deserialize<'de> + Reflect + 'static>(Serialize, Deserialize));
impl_reflect_value!(HashSet<T: Serialize + Hash + Eq + Clone + for<'de> Deserialize<'de> + Send + Sync + 'static>(Serialize, Deserialize));
impl_reflect_value!(Range<T: Serialize + Clone + for<'de> Deserialize<'de> + Send + Sync + 'static>(Serialize, Deserialize));
impl_reflect_value!(Duration(Hash, PartialEq, Serialize, Deserialize));
impl_reflect_value!(Duration(Debug, Hash, PartialEq, Serialize, Deserialize));

impl_from_reflect_value!(bool);
impl_from_reflect_value!(char);
Expand Down
Loading