From 8a6d0b063c0b34037e9c5b8473e0024d3c2da845 Mon Sep 17 00:00:00 2001 From: Benjamin Brienen Date: Mon, 23 Sep 2024 19:34:17 +0200 Subject: [PATCH] Use crate: `disqualified` (#15372) # Objective Fixes #15351 ## Solution - Created new external crate and ported over the code ## Testing - CI ## Migration guide Replace references to `bevy_utils::ShortName` with `disqualified::ShortName`. --- crates/bevy_asset/Cargo.toml | 1 + crates/bevy_asset/src/handle.rs | 3 +- crates/bevy_ecs/Cargo.toml | 1 + crates/bevy_ecs/src/schedule/schedule.rs | 16 +- crates/bevy_hierarchy/Cargo.toml | 1 + .../src/valid_parent_check_plugin.rs | 4 +- crates/bevy_reflect/Cargo.toml | 1 + crates/bevy_reflect/src/lib.rs | 3 +- crates/bevy_reflect/src/short_name.rs | 214 ------------------ 9 files changed, 14 insertions(+), 230 deletions(-) delete mode 100644 crates/bevy_reflect/src/short_name.rs diff --git a/crates/bevy_asset/Cargo.toml b/crates/bevy_asset/Cargo.toml index b2348d6509..d05bb49888 100644 --- a/crates/bevy_asset/Cargo.toml +++ b/crates/bevy_asset/Cargo.toml @@ -35,6 +35,7 @@ async-fs = "2.0" async-lock = "3.0" crossbeam-channel = "0.5" downcast-rs = "1.2" +disqualified = "1.0" futures-io = "0.3" futures-lite = "2.0.1" blake3 = "1.5" diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 25bfee6cf7..6371b7e01b 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -3,8 +3,9 @@ use crate::{ UntypedAssetId, }; use bevy_ecs::prelude::*; -use bevy_reflect::{std_traits::ReflectDefault, Reflect, ShortName, TypePath}; +use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath}; use crossbeam_channel::{Receiver, Sender}; +use disqualified::ShortName; use std::{ any::TypeId, hash::{Hash, Hasher}, diff --git a/crates/bevy_ecs/Cargo.toml b/crates/bevy_ecs/Cargo.toml index 125054041a..9b10c1f981 100644 --- a/crates/bevy_ecs/Cargo.toml +++ b/crates/bevy_ecs/Cargo.toml @@ -29,6 +29,7 @@ bevy_ecs_macros = { path = "macros", version = "0.15.0-dev" } petgraph = "0.6" bitflags = "2.3" concurrent-queue = "2.4.0" +disqualified = "1.0" fixedbitset = "0.5" serde = { version = "1", optional = true, default-features = false } thiserror = "1.0" diff --git a/crates/bevy_ecs/src/schedule/schedule.rs b/crates/bevy_ecs/src/schedule/schedule.rs index 1185949388..83d0fbc644 100644 --- a/crates/bevy_ecs/src/schedule/schedule.rs +++ b/crates/bevy_ecs/src/schedule/schedule.rs @@ -10,6 +10,7 @@ use bevy_utils::{ tracing::{error, warn}, HashMap, HashSet, }; +use disqualified::ShortName; use fixedbitset::FixedBitSet; use petgraph::{algo::TarjanScc, prelude::*}; use thiserror::Error; @@ -1607,16 +1608,11 @@ impl ScheduleGraph { } } }; - #[cfg(feature = "bevy_reflect")] - { - if self.settings.use_shortnames { - bevy_reflect::ShortName(&name).to_string() - } else { - name - } + if self.settings.use_shortnames { + ShortName(&name).to_string() + } else { + name } - #[cfg(not(feature = "bevy_reflect"))] - name } fn anonymous_set_name(&self, id: &NodeId) -> String { @@ -2018,7 +2014,6 @@ pub struct ScheduleBuildSettings { /// If set to true, node names will be shortened instead of the fully qualified type path. /// /// Defaults to `true`. - #[cfg(feature = "bevy_reflect")] pub use_shortnames: bool, /// If set to true, report all system sets the conflicting systems are part of. /// @@ -2040,7 +2035,6 @@ impl ScheduleBuildSettings { ambiguity_detection: LogLevel::Ignore, hierarchy_detection: LogLevel::Warn, auto_insert_apply_deferred: true, - #[cfg(feature = "bevy_reflect")] use_shortnames: true, report_sets: true, } diff --git a/crates/bevy_hierarchy/Cargo.toml b/crates/bevy_hierarchy/Cargo.toml index 7e696bae12..68c32ab2ee 100644 --- a/crates/bevy_hierarchy/Cargo.toml +++ b/crates/bevy_hierarchy/Cargo.toml @@ -24,6 +24,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [ "smallvec", ], optional = true } bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" } +disqualified = "1.0" smallvec = { version = "1.11", features = ["union", "const_generics"] } diff --git a/crates/bevy_hierarchy/src/valid_parent_check_plugin.rs b/crates/bevy_hierarchy/src/valid_parent_check_plugin.rs index ef3aebd83d..d03460375e 100644 --- a/crates/bevy_hierarchy/src/valid_parent_check_plugin.rs +++ b/crates/bevy_hierarchy/src/valid_parent_check_plugin.rs @@ -4,9 +4,9 @@ use std::marker::PhantomData; use crate::Parent; use bevy_ecs::prelude::*; #[cfg(feature = "bevy_app")] -use bevy_reflect::ShortName; -#[cfg(feature = "bevy_app")] use bevy_utils::HashSet; +#[cfg(feature = "bevy_app")] +use disqualified::ShortName; /// When enabled, runs [`check_hierarchy_component_has_valid_parent`]. /// diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index a60549229a..336f002d41 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -36,6 +36,7 @@ bevy_ptr = { path = "../bevy_ptr", version = "0.15.0-dev" } # other erased-serde = "0.4" +disqualified = "1.0" downcast-rs = "1.2" thiserror = "1.0" serde = "1" diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 0d119ec0e5..db9dfff9cf 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -553,7 +553,6 @@ mod reflect; mod reflectable; mod remote; mod set; -mod short_name; mod struct_trait; mod tuple; mod tuple_struct; @@ -623,7 +622,6 @@ pub use type_registry::*; pub use bevy_reflect_derive::*; pub use erased_serde; -pub use short_name::ShortName; extern crate alloc; @@ -680,6 +678,7 @@ pub mod __macro_exports { mod tests { use ::serde::{de::DeserializeSeed, Deserialize, Serialize}; use bevy_utils::HashMap; + use disqualified::ShortName; use ron::{ ser::{to_string_pretty, PrettyConfig}, Deserializer, diff --git a/crates/bevy_reflect/src/short_name.rs b/crates/bevy_reflect/src/short_name.rs deleted file mode 100644 index 24f01a8ca1..0000000000 --- a/crates/bevy_reflect/src/short_name.rs +++ /dev/null @@ -1,214 +0,0 @@ -/// Lazily shortens a type name to remove all module paths. -/// -/// The short name of a type is its full name as returned by -/// [`std::any::type_name`], but with the prefix of all paths removed. For -/// example, the short name of `alloc::vec::Vec>` -/// would be `Vec>`. -/// -/// Shortening is performed lazily without allocation. -#[cfg_attr( - feature = "alloc", - doc = r#" To get a [`String`] from this type, use the [`to_string`](`alloc::string::ToString::to_string`) method."# -)] -/// -/// # Examples -/// -/// ```rust -/// # use bevy_reflect::ShortName; -/// # -/// # mod foo { -/// # pub mod bar { -/// # pub struct Baz; -/// # } -/// # } -/// // Baz -/// let short_name = ShortName::of::(); -/// ``` -#[derive(Clone, Copy)] -pub struct ShortName<'a>(pub &'a str); - -impl ShortName<'static> { - /// Gets a shortened version of the name of the type `T`. - pub fn of() -> Self { - Self(core::any::type_name::()) - } -} - -impl<'a> ShortName<'a> { - /// Gets the original name before shortening. - pub const fn original(&self) -> &'a str { - self.0 - } -} - -impl<'a> From<&'a str> for ShortName<'a> { - fn from(value: &'a str) -> Self { - Self(value) - } -} - -impl<'a> core::fmt::Debug for ShortName<'a> { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - let &ShortName(full_name) = self; - // Generics result in nested paths within <..> blocks. - // Consider "bevy_render::camera::camera::extract_cameras". - // To tackle this, we parse the string from left to right, collapsing as we go. - let mut index: usize = 0; - let end_of_string = full_name.len(); - - while index < end_of_string { - let rest_of_string = full_name.get(index..end_of_string).unwrap_or_default(); - - // Collapse everything up to the next special character, - // then skip over it - if let Some(special_character_index) = rest_of_string.find(|c: char| { - (c == ' ') - || (c == '<') - || (c == '>') - || (c == '(') - || (c == ')') - || (c == '[') - || (c == ']') - || (c == ',') - || (c == ';') - }) { - let segment_to_collapse = rest_of_string - .get(0..special_character_index) - .unwrap_or_default(); - - f.write_str(collapse_type_name(segment_to_collapse))?; - - // Insert the special character - let special_character = - &rest_of_string[special_character_index..=special_character_index]; - - f.write_str(special_character)?; - - match special_character { - ">" | ")" | "]" - if rest_of_string[special_character_index + 1..].starts_with("::") => - { - f.write_str("::")?; - // Move the index past the "::" - index += special_character_index + 3; - } - // Move the index just past the special character - _ => index += special_character_index + 1, - } - } else { - // If there are no special characters left, we're done! - f.write_str(collapse_type_name(rest_of_string))?; - index = end_of_string; - } - } - - Ok(()) - } -} - -impl<'a> core::fmt::Display for ShortName<'a> { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - ::fmt(self, f) - } -} - -#[inline(always)] -fn collapse_type_name(string: &str) -> &str { - // Enums types are retained. - // As heuristic, we assume the enum type to be uppercase. - let mut segments = string.rsplit("::"); - let (last, second_last): (&str, Option<&str>) = (segments.next().unwrap(), segments.next()); - let Some(second_last) = second_last else { - return last; - }; - - if second_last.starts_with(char::is_uppercase) { - let index = string.len() - last.len() - second_last.len() - 2; - &string[index..] - } else { - last - } -} - -#[cfg(all(test, feature = "alloc"))] -mod name_formatting_tests { - use super::ShortName; - - #[test] - fn trivial() { - assert_eq!(ShortName("test_system").to_string(), "test_system"); - } - - #[test] - fn path_separated() { - assert_eq!( - ShortName("bevy_prelude::make_fun_game").to_string(), - "make_fun_game" - ); - } - - #[test] - fn tuple_type() { - assert_eq!( - ShortName("(String, String)").to_string(), - "(String, String)" - ); - } - - #[test] - fn array_type() { - assert_eq!(ShortName("[i32; 3]").to_string(), "[i32; 3]"); - } - - #[test] - fn trivial_generics() { - assert_eq!(ShortName("a").to_string(), "a"); - } - - #[test] - fn multiple_type_parameters() { - assert_eq!(ShortName("a").to_string(), "a"); - } - - #[test] - fn enums() { - assert_eq!(ShortName("Option::None").to_string(), "Option::None"); - assert_eq!(ShortName("Option::Some(2)").to_string(), "Option::Some(2)"); - assert_eq!( - ShortName("bevy_render::RenderSet::Prepare").to_string(), - "RenderSet::Prepare" - ); - } - - #[test] - fn generics() { - assert_eq!( - ShortName("bevy_render::camera::camera::extract_cameras").to_string(), - "extract_cameras" - ); - } - - #[test] - fn nested_generics() { - assert_eq!( - ShortName("bevy::mad_science::do_mad_science, bavy::TypeSystemAbuse>").to_string(), - "do_mad_science, TypeSystemAbuse>" - ); - } - - #[test] - fn sub_path_after_closing_bracket() { - assert_eq!( - ShortName("bevy_asset::assets::Assets::asset_event_system").to_string(), - "Assets::asset_event_system" - ); - assert_eq!( - ShortName("(String, String)::default").to_string(), - "(String, String)::default" - ); - assert_eq!( - ShortName("[i32; 16]::default").to_string(), - "[i32; 16]::default" - ); - } -}