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
|
/// a [`TypeData`] which can be used to downcast [`Reflect`] trait objects of
|
||||||
/// this type to trait objects of the relevant trait.
|
/// 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
|
/// [`TypeInfo`]: crate::TypeInfo
|
||||||
/// [0]: crate::Reflect
|
/// [0]: crate::Reflect
|
||||||
/// [1]: crate::Reflect
|
/// [1]: crate::Reflect
|
||||||
|
@ -287,14 +287,14 @@ impl TypeRegistration {
|
||||||
let type_name = std::any::type_name::<T>();
|
let type_name = std::any::type_name::<T>();
|
||||||
Self {
|
Self {
|
||||||
data: HashMap::default(),
|
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(),
|
type_info: T::type_info(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the [short name] of the type.
|
/// 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 {
|
pub fn short_name(&self) -> &str {
|
||||||
&self.short_name
|
&self.short_name
|
||||||
}
|
}
|
||||||
|
@ -305,49 +305,6 @@ impl TypeRegistration {
|
||||||
pub fn type_name(&self) -> &'static str {
|
pub fn type_name(&self) -> &'static str {
|
||||||
self.type_info.type_name()
|
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 {
|
impl Clone for TypeRegistration {
|
||||||
|
@ -459,42 +416,6 @@ mod test {
|
||||||
use crate::TypeRegistration;
|
use crate::TypeRegistration;
|
||||||
use bevy_utils::HashMap;
|
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]
|
#[test]
|
||||||
fn test_property_type_registration() {
|
fn test_property_type_registration() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -4,6 +4,8 @@ pub mod prelude {
|
||||||
|
|
||||||
pub mod futures;
|
pub mod futures;
|
||||||
pub mod label;
|
pub mod label;
|
||||||
|
mod short_names;
|
||||||
|
pub use short_names::get_short_name;
|
||||||
|
|
||||||
mod default;
|
mod default;
|
||||||
mod float_ord;
|
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"] }
|
clap = { version = "3.2", features = ["derive"] }
|
||||||
regex = "1.5"
|
regex = "1.5"
|
||||||
termcolor = "1.1"
|
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"
|
lazy_static = "1.4"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use bevy_reflect::TypeRegistration;
|
use bevy_utils::get_short_name;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use termcolor::{Color, ColorSpec, StandardStream, WriteColor};
|
use termcolor::{Color, ColorSpec, StandardStream, WriteColor};
|
||||||
|
@ -206,21 +206,18 @@ lazy_static! {
|
||||||
|
|
||||||
pub fn simplify_name(name: &str) -> String {
|
pub fn simplify_name(name: &str) -> String {
|
||||||
if let Some(captures) = SYSTEM_NAME.captures(name) {
|
if let Some(captures) = SYSTEM_NAME.captures(name) {
|
||||||
return format!(
|
return format!(r#"system: name="{}""#, get_short_name(&captures[1]));
|
||||||
r#"system: name="{}""#,
|
|
||||||
TypeRegistration::get_short_name(&captures[1])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if let Some(captures) = SYSTEM_OVERHEAD.captures(name) {
|
if let Some(captures) = SYSTEM_OVERHEAD.captures(name) {
|
||||||
return format!(
|
return format!(
|
||||||
r#"system overhead: name="{}""#,
|
r#"system overhead: name="{}""#,
|
||||||
TypeRegistration::get_short_name(&captures[1])
|
get_short_name(&captures[1])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let Some(captures) = SYSTEM_COMMANDS.captures(name) {
|
if let Some(captures) = SYSTEM_COMMANDS.captures(name) {
|
||||||
return format!(
|
return format!(
|
||||||
r#"system_commands: name="{}""#,
|
r#"system_commands: name="{}""#,
|
||||||
TypeRegistration::get_short_name(&captures[1])
|
get_short_name(&captures[1])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
name.to_string()
|
name.to_string()
|
||||||
|
|
Loading…
Reference in a new issue