2024-10-09 14:20:58 +00:00
use derive_more ::derive ::{ Display , Error } ;
2023-09-11 19:04:22 +00:00
2024-09-26 13:31:11 +00:00
use crate ::{ entity ::Entity , world ::unsafe_world_cell ::UnsafeWorldCell } ;
2023-09-11 19:04:22 +00:00
/// An error that occurs when retrieving a specific [`Entity`]'s query result from [`Query`](crate::system::Query) or [`QueryState`](crate::query::QueryState).
// TODO: return the type_name as part of this error
2024-09-26 13:31:11 +00:00
#[ derive(Clone, Copy) ]
pub enum QueryEntityError < ' w > {
2023-09-11 19:04:22 +00:00
/// The given [`Entity`]'s components do not match the query.
///
/// Either it does not have a requested component, or it has a component which the query filters out.
2024-09-26 13:31:11 +00:00
QueryDoesNotMatch ( Entity , UnsafeWorldCell < ' w > ) ,
2023-09-11 19:04:22 +00:00
/// The given [`Entity`] does not exist.
NoSuchEntity ( Entity ) ,
/// The [`Entity`] was requested mutably more than once.
///
/// See [`QueryState::get_many_mut`](crate::query::QueryState::get_many_mut) for an example.
AliasedMutability ( Entity ) ,
}
2024-09-27 00:59:59 +00:00
impl < ' w > core ::error ::Error for QueryEntityError < ' w > { }
2024-09-26 13:31:11 +00:00
2024-09-27 00:59:59 +00:00
impl < ' w > core ::fmt ::Display for QueryEntityError < ' w > {
fn fmt ( & self , f : & mut core ::fmt ::Formatter < '_ > ) -> core ::fmt ::Result {
2024-09-26 13:31:11 +00:00
match * self {
Self ::QueryDoesNotMatch ( entity , world ) = > {
write! (
f ,
" The query does not match the entity {entity}, which has components "
) ? ;
format_archetype ( f , world , entity )
}
Self ::NoSuchEntity ( entity ) = > write! ( f , " The entity {entity} does not exist " ) ,
Self ::AliasedMutability ( entity ) = > write! (
f ,
" The entity {entity} was requested mutably more than once "
) ,
}
}
}
2024-09-27 00:59:59 +00:00
impl < ' w > core ::fmt ::Debug for QueryEntityError < ' w > {
fn fmt ( & self , f : & mut core ::fmt ::Formatter < '_ > ) -> core ::fmt ::Result {
2024-09-26 13:31:11 +00:00
match * self {
Self ::QueryDoesNotMatch ( entity , world ) = > {
write! ( f , " QueryDoesNotMatch({entity} with components " ) ? ;
format_archetype ( f , world , entity ) ? ;
write! ( f , " ) " )
}
Self ::NoSuchEntity ( entity ) = > write! ( f , " NoSuchEntity({entity}) " ) ,
Self ::AliasedMutability ( entity ) = > write! ( f , " AliasedMutability({entity}) " ) ,
}
}
}
fn format_archetype (
2024-09-27 00:59:59 +00:00
f : & mut core ::fmt ::Formatter < '_ > ,
2024-09-26 13:31:11 +00:00
world : UnsafeWorldCell < '_ > ,
entity : Entity ,
2024-09-27 00:59:59 +00:00
) -> core ::fmt ::Result {
2024-09-26 13:31:11 +00:00
// We know entity is still alive
let entity = world
. get_entity ( entity )
. expect ( " entity does not belong to world " ) ;
for ( i , component_id ) in entity . archetype ( ) . components ( ) . enumerate ( ) {
if i > 0 {
write! ( f , " , " ) ? ;
}
let name = world
. components ( )
. get_name ( component_id )
. expect ( " entity does not belong to world " ) ;
QueryEntityError: Use short name for components (#16032)
Use the new `disqualified` crate in `QueryEntityError` to make the error
message more readable.
---
## Showcase
Old:
QueryDoesNotMatch(0v1 with components my_game::main::foo::A,
my_game::main::foo::B, bevy_pbr::light::point_light::PointLight,
bevy_render::primitives::CubemapFrusta,
bevy_pbr::bundle::CubemapVisibleEntities,
bevy_transform::components::transform::Transform,
bevy_transform::components::global_transform::GlobalTransform,
bevy_render::view::visibility::Visibility,
bevy_render::view::visibility::InheritedVisibility,
bevy_render::view::visibility::ViewVisibility,
bevy_render::sync_world::SyncToRenderWorld)
New:
QueryDoesNotMatch(0v1 with components A, B, PointLight, CubemapFrusta,
CubemapVisibleEntities, Transform, GlobalTransform, Visibility,
InheritedVisibility, ViewVisibility, SyncToRenderWorld)
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-20 17:56:43 +00:00
write! ( f , " {} " , disqualified ::ShortName ( name ) ) ? ;
2024-09-26 13:31:11 +00:00
}
Ok ( ( ) )
}
impl < ' w > PartialEq for QueryEntityError < ' w > {
fn eq ( & self , other : & Self ) -> bool {
match ( self , other ) {
( Self ::QueryDoesNotMatch ( e1 , _ ) , Self ::QueryDoesNotMatch ( e2 , _ ) ) if e1 = = e2 = > true ,
( Self ::NoSuchEntity ( e1 ) , Self ::NoSuchEntity ( e2 ) ) if e1 = = e2 = > true ,
( Self ::AliasedMutability ( e1 ) , Self ::AliasedMutability ( e2 ) ) if e1 = = e2 = > true ,
_ = > false ,
}
}
}
impl < ' w > Eq for QueryEntityError < ' w > { }
2023-09-11 19:04:22 +00:00
/// An error that occurs when evaluating a [`Query`](crate::system::Query) or [`QueryState`](crate::query::QueryState) as a single expected result via
/// [`get_single`](crate::system::Query::get_single) or [`get_single_mut`](crate::system::Query::get_single_mut).
2024-10-09 14:20:58 +00:00
#[ derive(Debug, Error, Display) ]
2023-09-11 19:04:22 +00:00
pub enum QuerySingleError {
/// No entity fits the query.
2024-10-09 14:20:58 +00:00
#[ display( " No entities fit the query {_0} " ) ]
#[ error(ignore) ]
2023-09-11 19:04:22 +00:00
NoEntities ( & 'static str ) ,
/// Multiple entities fit the query.
2024-10-09 14:20:58 +00:00
#[ display( " Multiple entities fit the query {_0} " ) ]
#[ error(ignore) ]
2023-09-11 19:04:22 +00:00
MultipleEntities ( & 'static str ) ,
}
2024-09-26 13:31:11 +00:00
#[ cfg(test) ]
mod test {
use crate as bevy_ecs ;
use crate ::prelude ::World ;
use bevy_ecs_macros ::Component ;
#[ test ]
fn query_does_not_match ( ) {
let mut world = World ::new ( ) ;
#[ derive(Component) ]
struct Present1 ;
#[ derive(Component) ]
struct Present2 ;
#[ derive(Component, Debug) ]
struct NotPresent ;
let entity = world . spawn ( ( Present1 , Present2 ) ) . id ( ) ;
let err = world
. query ::< & NotPresent > ( )
. get ( & world , entity )
. unwrap_err ( ) ;
QueryEntityError: Use short name for components (#16032)
Use the new `disqualified` crate in `QueryEntityError` to make the error
message more readable.
---
## Showcase
Old:
QueryDoesNotMatch(0v1 with components my_game::main::foo::A,
my_game::main::foo::B, bevy_pbr::light::point_light::PointLight,
bevy_render::primitives::CubemapFrusta,
bevy_pbr::bundle::CubemapVisibleEntities,
bevy_transform::components::transform::Transform,
bevy_transform::components::global_transform::GlobalTransform,
bevy_render::view::visibility::Visibility,
bevy_render::view::visibility::InheritedVisibility,
bevy_render::view::visibility::ViewVisibility,
bevy_render::sync_world::SyncToRenderWorld)
New:
QueryDoesNotMatch(0v1 with components A, B, PointLight, CubemapFrusta,
CubemapVisibleEntities, Transform, GlobalTransform, Visibility,
InheritedVisibility, ViewVisibility, SyncToRenderWorld)
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-10-20 17:56:43 +00:00
assert_eq! (
format! ( " {err:?} " ) ,
" QueryDoesNotMatch(0v1 with components Present1, Present2) "
) ;
2024-09-26 13:31:11 +00:00
}
}