mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Move get_short_name
utility method from bevy_reflect
into bevy_utils
(#5174)
# Summary This method strips a long type name like `bevy::render:📷:PerspectiveCameraBundle` down into the bare type name (`PerspectiveCameraBundle`). This is generally useful utility method, needed by #4299 and #5121. As a result: - This method was moved to `bevy_utils` for easier reuse. - The legibility and robustness of this method has been significantly improved. - Harder test cases have been added. This change was split out of #4299 to unblock it and make merging / reviewing the rest of those changes easier. ## Changelog - added `bevy_utils::get_short_name`, which strips the path from a type name for convenient display. - removed the `TypeRegistry::get_short_name` method. Use the function in `bevy_utils` instead.
This commit is contained in:
parent
de92054bbe
commit
8f721d8d0a
5 changed files with 120 additions and 90 deletions
|
@ -231,7 +231,7 @@ impl TypeRegistryArc {
|
|||
/// a [`TypeData`] which can be used to downcast [`Reflect`] trait objects of
|
||||
/// this type to trait objects of the relevant trait.
|
||||
///
|
||||
/// [short name]: TypeRegistration::get_short_name
|
||||
/// [short name]: bevy_utils::get_short_name
|
||||
/// [`TypeInfo`]: crate::TypeInfo
|
||||
/// [0]: crate::Reflect
|
||||
/// [1]: crate::Reflect
|
||||
|
@ -287,14 +287,14 @@ impl TypeRegistration {
|
|||
let type_name = std::any::type_name::<T>();
|
||||
Self {
|
||||
data: HashMap::default(),
|
||||
short_name: Self::get_short_name(type_name),
|
||||
short_name: bevy_utils::get_short_name(type_name),
|
||||
type_info: T::type_info(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the [short name] of the type.
|
||||
///
|
||||
/// [short name]: TypeRegistration::get_short_name
|
||||
/// [short name]: bevy_utils::get_short_name
|
||||
pub fn short_name(&self) -> &str {
|
||||
&self.short_name
|
||||
}
|
||||
|
@ -305,49 +305,6 @@ impl TypeRegistration {
|
|||
pub fn type_name(&self) -> &'static str {
|
||||
self.type_info.type_name()
|
||||
}
|
||||
|
||||
/// Calculates the short name of a type.
|
||||
///
|
||||
/// 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<core::option::Option<u32>>`
|
||||
/// would be `Vec<Option<u32>>`.
|
||||
pub fn get_short_name(full_name: &str) -> String {
|
||||
let mut short_name = String::new();
|
||||
|
||||
{
|
||||
// A typename may be a composition of several other type names (e.g. generic parameters)
|
||||
// separated by the characters that we try to find below.
|
||||
// Then, each individual typename is shortened to its last path component.
|
||||
//
|
||||
// Note: Instead of `find`, `split_inclusive` would be nice but it's still unstable...
|
||||
let mut remainder = full_name;
|
||||
while let Some(index) = remainder.find(&['<', '>', '(', ')', '[', ']', ',', ';'][..]) {
|
||||
let (path, new_remainder) = remainder.split_at(index);
|
||||
// Push the shortened path in front of the found character
|
||||
short_name.push_str(path.rsplit(':').next().unwrap());
|
||||
// Push the character that was found
|
||||
let character = new_remainder.chars().next().unwrap();
|
||||
short_name.push(character);
|
||||
// Advance the remainder
|
||||
if character == ',' || character == ';' {
|
||||
// A comma or semicolon is always followed by a space
|
||||
short_name.push(' ');
|
||||
remainder = &new_remainder[2..];
|
||||
} else {
|
||||
remainder = &new_remainder[1..];
|
||||
}
|
||||
}
|
||||
|
||||
// The remainder will only be non-empty if there were no matches at all
|
||||
if !remainder.is_empty() {
|
||||
// Then, the full typename is a path that has to be shortened
|
||||
short_name.push_str(remainder.rsplit(':').next().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
short_name
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for TypeRegistration {
|
||||
|
@ -459,42 +416,6 @@ mod test {
|
|||
use crate::TypeRegistration;
|
||||
use bevy_utils::HashMap;
|
||||
|
||||
#[test]
|
||||
fn test_get_short_name() {
|
||||
assert_eq!(
|
||||
TypeRegistration::get_short_name(std::any::type_name::<f64>()),
|
||||
"f64"
|
||||
);
|
||||
assert_eq!(
|
||||
TypeRegistration::get_short_name(std::any::type_name::<String>()),
|
||||
"String"
|
||||
);
|
||||
assert_eq!(
|
||||
TypeRegistration::get_short_name(std::any::type_name::<(u32, f64)>()),
|
||||
"(u32, f64)"
|
||||
);
|
||||
assert_eq!(
|
||||
TypeRegistration::get_short_name(std::any::type_name::<(String, String)>()),
|
||||
"(String, String)"
|
||||
);
|
||||
assert_eq!(
|
||||
TypeRegistration::get_short_name(std::any::type_name::<[f64]>()),
|
||||
"[f64]"
|
||||
);
|
||||
assert_eq!(
|
||||
TypeRegistration::get_short_name(std::any::type_name::<[String]>()),
|
||||
"[String]"
|
||||
);
|
||||
assert_eq!(
|
||||
TypeRegistration::get_short_name(std::any::type_name::<[f64; 16]>()),
|
||||
"[f64; 16]"
|
||||
);
|
||||
assert_eq!(
|
||||
TypeRegistration::get_short_name(std::any::type_name::<[String; 16]>()),
|
||||
"[String; 16]"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_property_type_registration() {
|
||||
assert_eq!(
|
||||
|
|
|
@ -4,6 +4,8 @@ pub mod prelude {
|
|||
|
||||
pub mod futures;
|
||||
pub mod label;
|
||||
mod short_names;
|
||||
pub use short_names::get_short_name;
|
||||
|
||||
mod default;
|
||||
mod float_ord;
|
||||
|
|
110
crates/bevy_utils/src/short_names.rs
Normal file
110
crates/bevy_utils/src/short_names.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
/// 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<core::option::Option<u32>>`
|
||||
/// would be `Vec<Option<u32>>`.
|
||||
pub fn get_short_name(full_name: &str) -> String {
|
||||
// Generics result in nested paths within <..> blocks.
|
||||
// Consider "bevy_render::camera::camera::extract_cameras<bevy_render::camera::bundle::Camera3d>".
|
||||
// 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();
|
||||
let mut parsed_name = String::new();
|
||||
|
||||
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();
|
||||
parsed_name += collapse_type_name(segment_to_collapse);
|
||||
// Insert the special character
|
||||
let special_character =
|
||||
&rest_of_string[special_character_index..=special_character_index];
|
||||
parsed_name.push_str(special_character);
|
||||
// Move the index just past the special character
|
||||
index += special_character_index + 1;
|
||||
} else {
|
||||
// If there are no special characters left, we're done!
|
||||
parsed_name += collapse_type_name(rest_of_string);
|
||||
index = end_of_string;
|
||||
}
|
||||
}
|
||||
parsed_name
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn collapse_type_name(string: &str) -> &str {
|
||||
string.split("::").last().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod name_formatting_tests {
|
||||
use super::get_short_name;
|
||||
|
||||
#[test]
|
||||
fn trivial() {
|
||||
assert_eq!(get_short_name("test_system"), "test_system");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_seperated() {
|
||||
assert_eq!(
|
||||
get_short_name("bevy_prelude::make_fun_game"),
|
||||
"make_fun_game".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_type() {
|
||||
assert_eq!(
|
||||
get_short_name("(String, String)"),
|
||||
"(String, String)".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_type() {
|
||||
assert_eq!(get_short_name("[i32; 3]"), "[i32; 3]".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trivial_generics() {
|
||||
assert_eq!(get_short_name("a<B>"), "a<B>".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_type_parameters() {
|
||||
assert_eq!(get_short_name("a<B, C>"), "a<B, C>".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generics() {
|
||||
assert_eq!(
|
||||
get_short_name("bevy_render::camera::camera::extract_cameras<bevy_render::camera::bundle::Camera3d>"),
|
||||
"extract_cameras<Camera3d>".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nested_generics() {
|
||||
assert_eq!(
|
||||
get_short_name("bevy::mad_science::do_mad_science<mad_science::Test<mad_science::Tube>, bavy::TypeSystemAbuse>"),
|
||||
"do_mad_science<Test<Tube>, TypeSystemAbuse>".to_string()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -12,5 +12,5 @@ serde = { version = "1.0", features = ["derive"] }
|
|||
clap = { version = "3.2", features = ["derive"] }
|
||||
regex = "1.5"
|
||||
termcolor = "1.1"
|
||||
bevy_reflect = { path = "../../crates/bevy_reflect", version = "0.8.0-dev" }
|
||||
bevy_utils = { path = "../../crates/bevy_utils", version = "0.8.0-dev" }
|
||||
lazy_static = "1.4"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bevy_reflect::TypeRegistration;
|
||||
use bevy_utils::get_short_name;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use termcolor::{Color, ColorSpec, StandardStream, WriteColor};
|
||||
|
@ -206,21 +206,18 @@ lazy_static! {
|
|||
|
||||
pub fn simplify_name(name: &str) -> String {
|
||||
if let Some(captures) = SYSTEM_NAME.captures(name) {
|
||||
return format!(
|
||||
r#"system: name="{}""#,
|
||||
TypeRegistration::get_short_name(&captures[1])
|
||||
);
|
||||
return format!(r#"system: name="{}""#, get_short_name(&captures[1]));
|
||||
}
|
||||
if let Some(captures) = SYSTEM_OVERHEAD.captures(name) {
|
||||
return format!(
|
||||
r#"system overhead: name="{}""#,
|
||||
TypeRegistration::get_short_name(&captures[1])
|
||||
get_short_name(&captures[1])
|
||||
);
|
||||
}
|
||||
if let Some(captures) = SYSTEM_COMMANDS.captures(name) {
|
||||
return format!(
|
||||
r#"system_commands: name="{}""#,
|
||||
TypeRegistration::get_short_name(&captures[1])
|
||||
get_short_name(&captures[1])
|
||||
);
|
||||
}
|
||||
name.to_string()
|
||||
|
|
Loading…
Reference in a new issue