From f07a489d96e88d9ef03292984d4d92da5cb00758 Mon Sep 17 00:00:00 2001 From: Mikhail <99481254+DCFApixels@users.noreply.github.com> Date: Mon, 26 Jun 2023 01:57:50 +0800 Subject: [PATCH] update exceptions --- src/Builtin/InjectSystem.cs | 10 ++-- src/EcsAspect.cs | 15 ++---- src/EcsGroup.cs | 44 +++++------------ src/EcsPipeline.cs | 29 ++--------- src/EcsRunner.cs | 3 +- src/EcsWorld.cs | 8 ++-- src/EcsWorld.static.cs | 1 + src/Utils/Exceptions.cs | 96 +++++++++++++++++++++++++++++++++++++ src/entlong.cs | 26 +++------- 9 files changed, 132 insertions(+), 100 deletions(-) diff --git a/src/Builtin/InjectSystem.cs b/src/Builtin/InjectSystem.cs index e618f57..03c6a7c 100644 --- a/src/Builtin/InjectSystem.cs +++ b/src/Builtin/InjectSystem.cs @@ -2,7 +2,7 @@ using DCFApixels.DragonECS.RunnersCore; using System; using System.Linq; -using System.Runtime.CompilerServices; +using static DCFApixels.DragonECS.EcsThrowHalper; namespace DCFApixels.DragonECS { @@ -59,12 +59,10 @@ namespace DCFApixels.DragonECS private EcsBaseTypeInjectRunner _baseTypeInjectRunner; void IEcsInject.Inject(T obj) { - if (obj == null) ThrowArgumentNullException(); + if (obj == null) Throw.ArgumentNull(); _baseTypeInjectRunner.Inject(obj); foreach (var item in targets) item.Inject(obj); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ThrowArgumentNullException() => throw new ArgumentNullException(); protected override void OnSetup() { Type baseType = typeof(T).BaseType; @@ -112,7 +110,7 @@ namespace DCFApixels.DragonECS void IEcsInject.Inject(PreInitInjectController obj) => _injectController = obj; public InjectSystem(T injectedData) { - if (injectedData == null) throw new ArgumentNullException(); + if (injectedData == null) Throw.ArgumentNull(); _injectedData = injectedData; } public void PreInit(EcsPipeline pipeline) @@ -149,7 +147,7 @@ namespace DCFApixels.DragonECS { public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, T data) { - if (data == null) throw new ArgumentNullException(); + if (data == null) Throw.ArgumentNull(); return self.Add(new InjectSystem(data)); } public static EcsPipeline.Builder Inject(this EcsPipeline.Builder self, A a, B b) diff --git a/src/EcsAspect.cs b/src/EcsAspect.cs index 6a6a2fc..0ff7038 100644 --- a/src/EcsAspect.cs +++ b/src/EcsAspect.cs @@ -6,14 +6,13 @@ using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; +using static DCFApixels.DragonECS.EcsThrowHalper; namespace DCFApixels.DragonECS { public abstract class EcsAspect { - [EditorBrowsable(EditorBrowsableState.Always)] internal EcsWorld source; - [EditorBrowsable(EditorBrowsableState.Always)] internal EcsMask mask; private bool _isInit; @@ -85,7 +84,7 @@ namespace DCFApixels.DragonECS { int id = _world.GetComponentID(type); #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_inc.Contains(id) || _exc.Contains(id)) throw new EcsFrameworkException($"{type.Name} already in constraints list."); + if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(type); #endif _inc.Add(id); } @@ -93,7 +92,7 @@ namespace DCFApixels.DragonECS { int id = _world.GetComponentID(type); #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_inc.Contains(id) || _exc.Contains(id)) throw new EcsFrameworkException($"{type.Name} already in constraints list."); + if (_inc.Contains(id) || _exc.Contains(id)) Throw.ConstraintIsAlreadyContainedInMask(type); #endif _exc.Add(id); } @@ -279,14 +278,6 @@ namespace DCFApixels.DragonECS public override string ToString() => CreateLogString(worldTypeID, included, excluded); } #endregion - - #region ThrowHelper - internal static class ThrowHelper - { - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowArgumentDifferentWorldsException() => throw new ArgumentException("The groups belong to different worlds."); - } - #endregion } #endregion diff --git a/src/EcsGroup.cs b/src/EcsGroup.cs index 7ec7c8c..5886d20 100644 --- a/src/EcsGroup.cs +++ b/src/EcsGroup.cs @@ -6,7 +6,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS -using static DCFApixels.DragonECS.EcsGroup.ThrowHelper; +using static DCFApixels.DragonECS.EcsThrowHalper; #endif namespace DCFApixels.DragonECS @@ -151,7 +151,7 @@ namespace DCFApixels.DragonECS get { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (index < 0 || index >= Count) ThrowArgumentOutOfRange(); + if (index < 0 || index >= Count) Throw.ArgumentOutOfRange(); #endif return _dense[++index]; } @@ -200,7 +200,7 @@ namespace DCFApixels.DragonECS internal void AddInternal(int entityID) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (Has(entityID)) ThrowAlreadyContains(entityID); + if (Has(entityID)) Throw.Group_AlreadyContains(entityID); #endif if (++_count >= _dense.Length) Array.Resize(ref _dense, _dense.Length << 1); @@ -218,7 +218,7 @@ namespace DCFApixels.DragonECS internal void RemoveInternal(int entityID) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!Has(entityID)) ThrowDoesNotContain(entityID); + if (!Has(entityID)) Throw.Group_DoesNotContain(entityID); #endif _dense[_sparse[entityID]] = _dense[_count]; _sparse[_dense[_count--]] = _sparse[entityID]; @@ -287,7 +287,7 @@ namespace DCFApixels.DragonECS public ReadOnlySpan ToSpan(int start, int length) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (start + length > _count) ThrowArgumentOutOfRangeException(); + if (start + length > _count) Throw.ArgumentOutOfRange(); #endif return new ReadOnlySpan(_dense, start, length); } @@ -301,7 +301,7 @@ namespace DCFApixels.DragonECS public void UnionWith(EcsGroup group) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_source != group.World) ThrowArgumentDifferentWorldsException(); + if (_source != group.World) Throw.Group_ArgumentDifferentWorldsException(); #endif foreach (var item in group) if (!Has(item)) @@ -315,7 +315,7 @@ namespace DCFApixels.DragonECS public void ExceptWith(EcsGroup group) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_source != group.World) ThrowArgumentDifferentWorldsException(); + if (_source != group.World) Throw.Group_ArgumentDifferentWorldsException(); #endif foreach (var item in this) if (group.Has(item)) @@ -329,7 +329,7 @@ namespace DCFApixels.DragonECS public void IntersectWith(EcsGroup group) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (World != group.World) ThrowArgumentDifferentWorldsException(); + if (World != group.World) Throw.Group_ArgumentDifferentWorldsException(); #endif foreach (var item in this) if (!group.Has(item)) @@ -343,7 +343,7 @@ namespace DCFApixels.DragonECS public void SymmetricExceptWith(EcsGroup group) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (_source != group.World) ThrowArgumentDifferentWorldsException(); + if (_source != group.World) Throw.Group_ArgumentDifferentWorldsException(); #endif foreach (var item in group) if (Has(item)) @@ -367,7 +367,7 @@ namespace DCFApixels.DragonECS public static EcsGroup Union(EcsGroup a, EcsGroup b) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (a._source != b._source) ThrowArgumentDifferentWorldsException(); + if (a._source != b._source) Throw.Group_ArgumentDifferentWorldsException(); #endif EcsGroup result = a._source.GetFreeGroup(); foreach (var item in a) @@ -381,7 +381,7 @@ namespace DCFApixels.DragonECS public static EcsGroup Except(EcsGroup a, EcsGroup b) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (a._source != b._source) ThrowArgumentDifferentWorldsException(); + if (a._source != b._source) Throw.Group_ArgumentDifferentWorldsException(); #endif EcsGroup result = a._source.GetFreeGroup(); foreach (var item in a) @@ -394,7 +394,7 @@ namespace DCFApixels.DragonECS public static EcsGroup Intersect(EcsGroup a, EcsGroup b) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (a._source != b._source) ThrowArgumentDifferentWorldsException(); + if (a._source != b._source) Throw.Group_ArgumentDifferentWorldsException(); #endif EcsGroup result = a._source.GetFreeGroup(); foreach (var item in a) @@ -408,7 +408,7 @@ namespace DCFApixels.DragonECS public static EcsGroup SymmetricExcept(EcsGroup a, EcsGroup b) { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (a._source != b._source) ThrowArgumentDifferentWorldsException(); + if (a._source != b._source) Throw.Group_ArgumentDifferentWorldsException(); #endif EcsGroup result = a._source.GetFreeGroup(); foreach (var item in a) @@ -519,24 +519,6 @@ namespace DCFApixels.DragonECS } #endregion - #region ThrowHalper -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - internal static class ThrowHelper - { - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowAlreadyContains(int entityID) => throw new EcsFrameworkException($"This group already contains entity {entityID}."); - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowArgumentOutOfRange() => throw new ArgumentOutOfRangeException($"index is less than 0 or is equal to or greater than Count."); - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowDoesNotContain(int entityID) => throw new EcsFrameworkException($"This group does not contain entity {entityID}."); - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException(); - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowArgumentDifferentWorldsException() => throw new ArgumentException("The groups belong to different worlds."); - } -#endif - #endregion - #region DebuggerProxy internal class DebuggerProxy { diff --git a/src/EcsPipeline.cs b/src/EcsPipeline.cs index 5f915df..a06e1c5 100644 --- a/src/EcsPipeline.cs +++ b/src/EcsPipeline.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Runtime.CompilerServices; +using static DCFApixels.DragonECS.EcsThrowHalper; namespace DCFApixels.DragonECS { @@ -86,19 +87,19 @@ namespace DCFApixels.DragonECS public void Run() { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - CheckBeforeInitForMethod(nameof(Run)); - CheckAfterDestroyForMethod(nameof(Run)); + if (_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Run)); + if (_isDestoryed) Throw.Pipeline_MethodCalledAfterDestruction(nameof(Run)); #endif _runRunnerCache.Run(this); } public void Destroy() { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - CheckBeforeInitForMethod(nameof(Run)); + if (_isInit) Throw.Pipeline_MethodCalledBeforeInitialisation(nameof(Destroy)); #endif if (_isDestoryed == true) { - EcsDebug.Print("[Warning]", $"This {nameof(EcsPipeline)} has already been destroyed"); + EcsDebug.PrintWarning($"This {nameof(EcsPipeline)} has already been destroyed"); return; } _isDestoryed = true; @@ -106,26 +107,6 @@ namespace DCFApixels.DragonECS } #endregion - #region StateChecks -#if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - private void CheckBeforeInitForMethod(string methodName) - { - if (!_isInit) - throw new MethodAccessException($"It is forbidden to call {methodName}, before initialization {nameof(EcsPipeline)}"); - } - private void CheckAfterInitForMethod(string methodName) - { - if (_isInit) - throw new MethodAccessException($"It is forbidden to call {methodName}, after initialization {nameof(EcsPipeline)}"); - } - private void CheckAfterDestroyForMethod(string methodName) - { - if (_isDestoryed) - throw new MethodAccessException($"It is forbidden to call {methodName}, after destroying {nameof(EcsPipeline)}"); - } -#endif - #endregion - #region Builder public static Builder New() => new Builder(); public class Builder diff --git a/src/EcsRunner.cs b/src/EcsRunner.cs index a86185a..7e30725 100644 --- a/src/EcsRunner.cs +++ b/src/EcsRunner.cs @@ -73,8 +73,7 @@ namespace DCFApixels.DragonECS } if (delayedExceptions.Count > 0) { - foreach (var item in delayedExceptions) EcsDebug.Print(EcsConsts.DEBUG_ERROR_TAG, item.Message); - throw delayedExceptions[0]; + throw new AggregateException(delayedExceptions); } } diff --git a/src/EcsWorld.cs b/src/EcsWorld.cs index 7ab71dc..e062288 100644 --- a/src/EcsWorld.cs +++ b/src/EcsWorld.cs @@ -3,6 +3,7 @@ using DCFApixels.DragonECS.Utils; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; +using static DCFApixels.DragonECS.EcsThrowHalper; namespace DCFApixels.DragonECS { @@ -301,7 +302,7 @@ namespace DCFApixels.DragonECS var count = --_componentCounts[entityID]; if (count == 0 && _allEntites.Has(entityID)) DelEntity(entityID); #if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (count < 0) throw new EcsFrameworkException("нарушен баланс инкремента/декремента компонентов"); + if (count < 0) Throw.World_InvalidIncrementComponentsBalance(); #endif } #endregion @@ -322,8 +323,7 @@ namespace DCFApixels.DragonECS internal void ReleaseGroup(EcsGroup group) { #if (DEBUG && !DISABLE_DEBUG) || !DISABLE_DRAGONECS_ASSERT_CHEKS - if (group.World != this) - throw new ArgumentException("groupFilter.WorldIndex != this"); + if (group.World != this) Throw.World_GroupDoesNotBelongWorld(); #endif group._isReleased = true; group.Clear(); @@ -365,8 +365,6 @@ namespace DCFApixels.DragonECS #endregion } - internal sealed class EcsNullWorld : EcsWorld { } - #region Callbacks Interface public interface IEcsWorldEventListener { diff --git a/src/EcsWorld.static.cs b/src/EcsWorld.static.cs index d5e69af..cf61e9f 100644 --- a/src/EcsWorld.static.cs +++ b/src/EcsWorld.static.cs @@ -97,4 +97,5 @@ namespace DCFApixels.DragonECS } } } + internal sealed class EcsNullWorld : EcsWorld { } } diff --git a/src/Utils/Exceptions.cs b/src/Utils/Exceptions.cs index a965542..7cd999d 100644 --- a/src/Utils/Exceptions.cs +++ b/src/Utils/Exceptions.cs @@ -1,8 +1,104 @@ using System; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace DCFApixels.DragonECS { + public class EcsThrowHalper + { + public static readonly EcsThrowHalper Throw = new EcsThrowHalper(); + private EcsThrowHalper() { } + } + + public static class EcsThrowHalper_Core + { + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Pool_AlreadyHasComponent(this EcsThrowHalper _, int entityID) + { + throw new EcsFrameworkException($"Entity({entityID}) already has component {EcsDebugUtility.GetGenericTypeName()}."); + } + [MethodImpl(MethodImplOptions.NoInlining)] + public static void Pool_NotHaveComponent(this EcsThrowHalper _, int entityID) + { + throw new EcsFrameworkException($"Entity({entityID}) has no component {EcsDebugUtility.GetGenericTypeName()}."); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void ArgumentNull(this EcsThrowHalper _) + { + throw new ArgumentNullException(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void ConstraintIsAlreadyContainedInMask(this EcsThrowHalper _, Type type) + { + throw new EcsFrameworkException($"The {EcsDebugUtility.GetGenericTypeName(type)} constraint is already contained in the mask."); + } + + //[MethodImpl(MethodImplOptions.NoInlining)] + //public static void ArgumentDifferentWorldsException() + //{ + // throw new ArgumentException("The groups belong to different worlds."); + //} + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void ArgumentOutOfRange(this EcsThrowHalper _) + { + throw new ArgumentOutOfRangeException($"index is less than 0 or is equal to or greater than Count."); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void Group_AlreadyContains(this EcsThrowHalper _, int entityID) + { + throw new EcsFrameworkException($"This group already contains entity {entityID}."); + } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void Group_DoesNotContain(this EcsThrowHalper _, int entityID) + { + throw new EcsFrameworkException($"This group does not contain entity {entityID}."); + } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void Group_ArgumentDifferentWorldsException(this EcsThrowHalper _) + { + throw new ArgumentException("The groups belong to different worlds."); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void Pipeline_MethodCalledAfterInitialisation(this EcsThrowHalper _, string methodName) + { + throw new MethodAccessException($"It is forbidden to call {methodName}, after initialization {nameof(EcsPipeline)}."); + } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void Pipeline_MethodCalledBeforeInitialisation(this EcsThrowHalper _, string methodName) + { + throw new MethodAccessException($"It is forbidden to call {methodName}, before initialization {nameof(EcsPipeline)}."); + } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void Pipeline_MethodCalledAfterDestruction(this EcsThrowHalper _, string methodName) + { + throw new MethodAccessException($"It is forbidden to call {methodName}, after destroying {nameof(EcsPipeline)}."); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void World_InvalidIncrementComponentsBalance(this EcsThrowHalper _) + { + throw new MethodAccessException("Invalid increment components balance."); + } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void World_GroupDoesNotBelongWorld(this EcsThrowHalper _) + { + throw new MethodAccessException("The Group does not belong in this world."); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void Ent_ThrowIsNotAlive(this EcsThrowHalper _, entlong entity) + { + if (entity.IsNull) + throw new EcsFrameworkException($"The {entity} is null."); + else + throw new EcsFrameworkException($"The {entity} is not alive."); + } + } + [Serializable] public class EcsFrameworkException : Exception { diff --git a/src/entlong.cs b/src/entlong.cs index 2a4430a..ff49d76 100644 --- a/src/entlong.cs +++ b/src/entlong.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using static DCFApixels.DragonECS.entlong.ThrowHalper; +using static DCFApixels.DragonECS.EcsThrowHalper; namespace DCFApixels.DragonECS { @@ -33,7 +33,7 @@ namespace DCFApixels.DragonECS public bool IsNull { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => full == 0l; + get => full == 0L; } public int ID { @@ -41,7 +41,7 @@ namespace DCFApixels.DragonECS get { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!IsAlive) ThrowIsNotAlive(this); + if (!IsAlive) Throw.Ent_ThrowIsNotAlive(this); #endif return id; } @@ -52,7 +52,7 @@ namespace DCFApixels.DragonECS get { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!IsAlive) ThrowIsNotAlive(this); + if (!IsAlive) Throw.Ent_ThrowIsNotAlive(this); #endif return gen; } @@ -63,7 +63,7 @@ namespace DCFApixels.DragonECS get { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!IsAlive) ThrowIsNotAlive(this); + if (!IsAlive) Throw.Ent_ThrowIsNotAlive(this); #endif return EcsWorld.GetWorld(world); } @@ -74,7 +74,7 @@ namespace DCFApixels.DragonECS get { #if (DEBUG && !DISABLE_DEBUG) || ENABLE_DRAGONECS_ASSERT_CHEKS - if (!IsAlive) ThrowIsNotAlive(this); + if (!IsAlive) Throw.Ent_ThrowIsNotAlive(this); #endif return world; } @@ -143,20 +143,6 @@ namespace DCFApixels.DragonECS public static explicit operator entlong(in long a) => new entlong(a); #endregion - #region ThrowHalper - internal static class ThrowHalper - { - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowIsNotAlive(entlong entity) - { - if (entity.IsNull) - throw new EcsFrameworkException($"The {entity} is null."); - else - throw new EcsFrameworkException($"The {entity} is not alive."); - } - } - #endregion - #region DebuggerProxy internal class DebuggerProxy {