com.wallstop-studios.dxmessaging 2.2.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/CHANGELOG.md +106 -67
  2. package/CHANGELOG.md.meta +7 -7
  3. package/Editor/Analyzers/BaseCallIlInspector.cs +277 -0
  4. package/Editor/Analyzers/BaseCallIlInspector.cs.meta +11 -0
  5. package/Editor/Analyzers/BaseCallLogMessageParser.cs +295 -0
  6. package/Editor/Analyzers/BaseCallLogMessageParser.cs.meta +11 -0
  7. package/Editor/Analyzers/BaseCallReportAggregator.cs +308 -0
  8. package/Editor/Analyzers/BaseCallReportAggregator.cs.meta +11 -0
  9. package/Editor/Analyzers/BaseCallTypeScanner.cs +110 -0
  10. package/Editor/Analyzers/BaseCallTypeScanner.cs.meta +11 -0
  11. package/Editor/Analyzers/BaseCallTypeScannerCore.cs +562 -0
  12. package/Editor/Analyzers/BaseCallTypeScannerCore.cs.meta +11 -0
  13. package/Editor/Analyzers/DxMessagingConsoleHarvester.cs +1122 -0
  14. package/Editor/Analyzers/DxMessagingConsoleHarvester.cs.meta +11 -0
  15. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +44 -44
  16. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +44 -44
  17. package/Editor/Analyzers/System.Collections.Immutable.dll.meta +44 -44
  18. package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +44 -44
  19. package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +44 -44
  20. package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll +0 -0
  21. package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll.meta +33 -0
  22. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
  23. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +72 -72
  24. package/Editor/Analyzers.meta +8 -8
  25. package/Editor/AssemblyInfo.cs.meta +3 -3
  26. package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs +81 -0
  27. package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs.meta +11 -0
  28. package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs +420 -0
  29. package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs.meta +11 -0
  30. package/Editor/CustomEditors/MessagingComponentEditor.cs +1 -1
  31. package/Editor/CustomEditors/MessagingComponentEditor.cs.meta +2 -2
  32. package/Editor/CustomEditors.meta +2 -2
  33. package/Editor/DxMessagingEditorInitializer.cs.meta +2 -2
  34. package/Editor/DxMessagingMenu.cs.meta +11 -11
  35. package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -11
  36. package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs +190 -0
  37. package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs.meta +11 -0
  38. package/Editor/Settings/DxMessagingSettings.cs +189 -0
  39. package/Editor/Settings/DxMessagingSettings.cs.meta +2 -2
  40. package/Editor/Settings/DxMessagingSettingsProvider.cs +50 -33
  41. package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +2 -2
  42. package/Editor/Settings.meta +2 -2
  43. package/Editor/SetupCscRsp.cs +209 -8
  44. package/Editor/SetupCscRsp.cs.meta +2 -2
  45. package/Editor/Testing/MessagingComponentEditorHarness.cs +1 -1
  46. package/Editor/Testing/MessagingComponentEditorHarness.cs.meta +3 -3
  47. package/Editor/Testing.meta +3 -3
  48. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef +14 -14
  49. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef.meta +7 -7
  50. package/Editor.meta +8 -8
  51. package/LICENSE.md +9 -9
  52. package/LICENSE.md.meta +7 -7
  53. package/README.md +941 -900
  54. package/README.md.meta +7 -7
  55. package/Runtime/AssemblyInfo.cs +4 -0
  56. package/Runtime/AssemblyInfo.cs.meta +2 -2
  57. package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs.meta +2 -2
  58. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs.meta +2 -2
  59. package/Runtime/Core/Attributes/DxIgnoreMissingBaseCallAttribute.cs +26 -0
  60. package/Runtime/Core/Attributes/DxIgnoreMissingBaseCallAttribute.cs.meta +11 -0
  61. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs.meta +2 -2
  62. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs.meta +2 -2
  63. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs.meta +2 -2
  64. package/Runtime/Core/Attributes.meta +2 -2
  65. package/Runtime/Core/Configuration/DxMessagingRuntimeSettings.cs +195 -0
  66. package/Runtime/Core/Configuration/DxMessagingRuntimeSettings.cs.meta +11 -0
  67. package/Runtime/Core/Configuration/DxMessagingRuntimeSettingsProvider.cs +179 -0
  68. package/Runtime/Core/Configuration/DxMessagingRuntimeSettingsProvider.cs.meta +11 -0
  69. package/Runtime/Core/Configuration.meta +9 -0
  70. package/Runtime/Core/DataStructure/CyclicBuffer.cs +2 -2
  71. package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +2 -2
  72. package/Runtime/Core/DataStructure.meta +2 -2
  73. package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +2 -2
  74. package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +2 -2
  75. package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +2 -2
  76. package/Runtime/Core/Diagnostics.meta +2 -2
  77. package/Runtime/Core/DxMessagingStaticState.cs +19 -0
  78. package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -11
  79. package/Runtime/Core/Extensions/EnumExtensions.cs.meta +2 -2
  80. package/Runtime/Core/Extensions/IListExtensions.cs.meta +2 -2
  81. package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -12
  82. package/Runtime/Core/Extensions/MessageExtensions.cs.meta +11 -11
  83. package/Runtime/Core/Extensions.meta +8 -8
  84. package/Runtime/Core/Helper/MessageCache.cs +32 -0
  85. package/Runtime/Core/Helper/MessageCache.cs.meta +2 -2
  86. package/Runtime/Core/Helper/MessageHelperIndexer.cs.meta +2 -2
  87. package/Runtime/Core/Helper.meta +2 -2
  88. package/Runtime/Core/IMessage.cs +3 -3
  89. package/Runtime/Core/IMessage.cs.meta +11 -11
  90. package/Runtime/Core/InstanceId.cs.meta +11 -11
  91. package/Runtime/Core/Internal/TypedDispatchLinkIndex.cs +51 -0
  92. package/Runtime/Core/Internal/TypedDispatchLinkIndex.cs.meta +11 -0
  93. package/Runtime/Core/Internal/TypedGlobalSlotIndex.cs +38 -0
  94. package/Runtime/Core/Internal/TypedGlobalSlotIndex.cs.meta +11 -0
  95. package/Runtime/Core/Internal/TypedSlotIndex.cs +81 -0
  96. package/Runtime/Core/Internal/TypedSlotIndex.cs.meta +11 -0
  97. package/Runtime/Core/Internal/TypedSlots.cs +613 -0
  98. package/Runtime/Core/Internal/TypedSlots.cs.meta +11 -0
  99. package/Runtime/Core/Internal.meta +9 -0
  100. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -11
  101. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -11
  102. package/Runtime/Core/MessageBus/IMessageBus.cs +177 -3
  103. package/Runtime/Core/MessageBus/IMessageBus.cs.meta +11 -11
  104. package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -11
  105. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -11
  106. package/Runtime/Core/MessageBus/Internal/BusContextIndex.cs +16 -0
  107. package/Runtime/Core/MessageBus/Internal/BusContextIndex.cs.meta +11 -0
  108. package/Runtime/Core/MessageBus/Internal/BusSinkIndex.cs +40 -0
  109. package/Runtime/Core/MessageBus/Internal/BusSinkIndex.cs.meta +11 -0
  110. package/Runtime/Core/MessageBus/Internal/BusSlots.cs +718 -0
  111. package/Runtime/Core/MessageBus/Internal/BusSlots.cs.meta +11 -0
  112. package/Runtime/Core/MessageBus/Internal/DispatchKind.cs +38 -0
  113. package/Runtime/Core/MessageBus/Internal/DispatchKind.cs.meta +11 -0
  114. package/Runtime/Core/MessageBus/Internal/DispatchPhase.cs +20 -0
  115. package/Runtime/Core/MessageBus/Internal/DispatchPhase.cs.meta +11 -0
  116. package/Runtime/Core/MessageBus/Internal/DispatchVariant.cs +28 -0
  117. package/Runtime/Core/MessageBus/Internal/DispatchVariant.cs.meta +11 -0
  118. package/Runtime/Core/MessageBus/Internal/IEvictableSlot.cs +48 -0
  119. package/Runtime/Core/MessageBus/Internal/IEvictableSlot.cs.meta +11 -0
  120. package/Runtime/Core/MessageBus/Internal/ISweepable.cs +15 -0
  121. package/Runtime/Core/MessageBus/Internal/ISweepable.cs.meta +11 -0
  122. package/Runtime/Core/MessageBus/Internal/RegistrationMethodAxes.cs +222 -0
  123. package/Runtime/Core/MessageBus/Internal/RegistrationMethodAxes.cs.meta +11 -0
  124. package/Runtime/Core/MessageBus/Internal/SlotKey.cs +192 -0
  125. package/Runtime/Core/MessageBus/Internal/SlotKey.cs.meta +11 -0
  126. package/Runtime/Core/MessageBus/Internal.meta +9 -0
  127. package/Runtime/Core/MessageBus/MessageBus.cs +2651 -500
  128. package/Runtime/Core/MessageBus/MessageBus.cs.meta +11 -11
  129. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -11
  130. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -11
  131. package/Runtime/Core/MessageBus/MessagingRegistration.cs.meta +11 -11
  132. package/Runtime/Core/MessageBus/RegistrationLog.cs.meta +11 -11
  133. package/Runtime/Core/MessageBus.meta +8 -8
  134. package/Runtime/Core/MessageHandler.cs +2019 -542
  135. package/Runtime/Core/MessageHandler.cs.meta +11 -11
  136. package/Runtime/Core/MessageRegistrationHandle.cs.meta +11 -11
  137. package/Runtime/Core/MessageRegistrationToken.cs +7 -0
  138. package/Runtime/Core/MessageRegistrationToken.cs.meta +11 -11
  139. package/Runtime/Core/Messages/GlobalStringMessage.cs.meta +2 -2
  140. package/Runtime/Core/Messages/IBroadcastMessage.cs.meta +11 -11
  141. package/Runtime/Core/Messages/ITargetedMessage.cs.meta +11 -11
  142. package/Runtime/Core/Messages/IUntargetedMessage.cs.meta +11 -11
  143. package/Runtime/Core/Messages/ReflexiveMessage.cs.meta +2 -2
  144. package/Runtime/Core/Messages/SourcedStringMessage.cs.meta +11 -11
  145. package/Runtime/Core/Messages/StringMessage.cs.meta +2 -2
  146. package/Runtime/Core/Messages.meta +8 -8
  147. package/Runtime/Core/MessagingDebug.cs.meta +11 -11
  148. package/Runtime/Core/Pooling/CollectionPool.cs +266 -0
  149. package/Runtime/Core/Pooling/CollectionPool.cs.meta +11 -0
  150. package/Runtime/Core/Pooling/CollectionPoolDiagnostics.cs +30 -0
  151. package/Runtime/Core/Pooling/CollectionPoolDiagnostics.cs.meta +11 -0
  152. package/Runtime/Core/Pooling/DxPools.cs +157 -0
  153. package/Runtime/Core/Pooling/DxPools.cs.meta +11 -0
  154. package/Runtime/Core/Pooling/EvictionPlayerLoopHook.cs +106 -0
  155. package/Runtime/Core/Pooling/EvictionPlayerLoopHook.cs.meta +11 -0
  156. package/Runtime/Core/Pooling/IDxMessagingClock.cs +18 -0
  157. package/Runtime/Core/Pooling/IDxMessagingClock.cs.meta +11 -0
  158. package/Runtime/Core/Pooling/PoolDiagnosticsSnapshot.cs +55 -0
  159. package/Runtime/Core/Pooling/PoolDiagnosticsSnapshot.cs.meta +11 -0
  160. package/Runtime/Core/Pooling/StopwatchClock.cs +27 -0
  161. package/Runtime/Core/Pooling/StopwatchClock.cs.meta +11 -0
  162. package/Runtime/Core/Pooling/UnityRealtimeClock.cs +31 -0
  163. package/Runtime/Core/Pooling/UnityRealtimeClock.cs.meta +11 -0
  164. package/Runtime/Core/Pooling.meta +9 -0
  165. package/Runtime/Core.meta +8 -8
  166. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +12 -12
  167. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -11
  168. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +12 -12
  169. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +2 -2
  170. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +73 -0
  171. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +11 -11
  172. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef +20 -20
  173. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef.meta +7 -7
  174. package/Runtime/Unity/Integrations/Reflex.meta +8 -8
  175. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +2 -2
  176. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +109 -1
  177. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +11 -11
  178. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef +30 -30
  179. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef.meta +7 -7
  180. package/Runtime/Unity/Integrations/VContainer.meta +8 -8
  181. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +2 -2
  182. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef +30 -30
  183. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef.meta +7 -7
  184. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +79 -1
  185. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +11 -11
  186. package/Runtime/Unity/Integrations/Zenject.meta +8 -8
  187. package/Runtime/Unity/Integrations.meta +8 -8
  188. package/Runtime/Unity/MessageAwareComponent.cs +29 -0
  189. package/Runtime/Unity/MessageAwareComponent.cs.meta +11 -11
  190. package/Runtime/Unity/MessageBusProviderHandle.cs.meta +12 -12
  191. package/Runtime/Unity/MessagingComponent.cs.meta +11 -11
  192. package/Runtime/Unity/MessagingComponentInstaller.cs.meta +12 -12
  193. package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +12 -12
  194. package/Runtime/Unity.meta +8 -8
  195. package/Runtime/WallstopStudios.DxMessaging.asmdef +14 -14
  196. package/Runtime/WallstopStudios.DxMessaging.asmdef.meta +7 -7
  197. package/Runtime.meta +8 -8
  198. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab +98 -98
  199. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab.meta +7 -7
  200. package/Samples~/DI/Prefabs.meta +8 -8
  201. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset +14 -14
  202. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset.meta +8 -8
  203. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset +14 -14
  204. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset.meta +8 -8
  205. package/Samples~/DI/Providers.meta +8 -8
  206. package/Samples~/DI/README.md +51 -51
  207. package/Samples~/DI/README.md.meta +7 -7
  208. package/Samples~/DI/Reflex/SampleInstaller.cs +7 -0
  209. package/Samples~/DI/Reflex/SampleInstaller.cs.meta +11 -11
  210. package/Samples~/DI/Reflex.meta +8 -8
  211. package/Samples~/DI/VContainer/SampleLifetimeScope.cs +6 -1
  212. package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +11 -11
  213. package/Samples~/DI/VContainer.meta +8 -8
  214. package/Samples~/DI/Zenject/SampleInstaller.cs +8 -0
  215. package/Samples~/DI/Zenject/SampleInstaller.cs.meta +11 -11
  216. package/Samples~/DI/Zenject.meta +8 -8
  217. package/Samples~/DI.meta +8 -8
  218. package/Samples~/Mini Combat/Boot.cs.meta +11 -11
  219. package/Samples~/Mini Combat/Enemy.cs.meta +11 -11
  220. package/Samples~/Mini Combat/Messages.cs.meta +11 -11
  221. package/Samples~/Mini Combat/Player.cs.meta +11 -11
  222. package/Samples~/Mini Combat/README.md +324 -323
  223. package/Samples~/Mini Combat/README.md.meta +7 -7
  224. package/Samples~/Mini Combat/UIOverlay.cs.meta +11 -11
  225. package/Samples~/Mini Combat/Walkthrough.md +430 -430
  226. package/Samples~/Mini Combat/Walkthrough.md.meta +7 -7
  227. package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef +13 -13
  228. package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef.meta +7 -7
  229. package/Samples~/Mini Combat.meta +8 -8
  230. package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs.meta +11 -11
  231. package/Samples~/UI Buttons + Inspector/Messages.cs.meta +11 -11
  232. package/Samples~/UI Buttons + Inspector/MessagingObserver.cs.meta +11 -11
  233. package/Samples~/UI Buttons + Inspector/README.md +210 -209
  234. package/Samples~/UI Buttons + Inspector/README.md.meta +7 -7
  235. package/Samples~/UI Buttons + Inspector/UIButtonEmitter.cs.meta +11 -11
  236. package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef +13 -13
  237. package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef.meta +7 -7
  238. package/Samples~/UI Buttons + Inspector.meta +8 -8
  239. package/SourceGenerators/Directory.Build.props.meta +7 -7
  240. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs.meta +11 -11
  241. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs.meta +2 -2
  242. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj.meta +7 -7
  243. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.meta +8 -8
  244. package/SourceGenerators.meta +8 -8
  245. package/Third Party Notices.md +3 -3
  246. package/Third Party Notices.md.meta +7 -7
  247. package/package.json +115 -92
  248. package/package.json.meta +7 -7
package/CHANGELOG.md CHANGED
@@ -1,67 +1,106 @@
1
- # Changelog
2
-
3
- All notable changes to this project will be documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [Unreleased]
9
-
10
- ## [2.2.0]
11
-
12
- ### Fixed
13
-
14
- - Fixed a bug where no messages would get received by any listeners due to specifics in Unity play mode timings
15
-
16
- ## [2.1.8]
17
-
18
- ### Fixed
19
-
20
- - Added npmignore for proper npm publishing (incorrectly packaging some items)
21
-
22
- ## [2.1.7]
23
-
24
- ### Changed
25
-
26
- - Improved README with prominent Mental Model section
27
- - Added Mermaid diagrams and decision flowchart for choosing message types
28
- - Added Common Mistakes callout with troubleshooting link
29
- - Updated performance comparison table with accurate benchmark range (10-17M ops/sec)
30
-
31
- ### Fixed
32
-
33
- - Regenerated corrupted meta files in `scripts/wiki`
34
-
35
- ## [2.1.6]
36
-
37
- ### Added
38
-
39
- - Concepts index page and Mental Model documentation for understanding DxMessaging's design principles
40
-
41
- ### Fixed
42
-
43
- - Orphaned documentation pages in Concepts section now included in mkdocs.yml navigation
44
- - Burst compiler assembly resolution errors when using DxMessaging as a package on disk and building for player platforms. Benchmarks and integration test assembly definitions now specify Editor-only platform to prevent Burst from attempting to resolve these assemblies during player builds.
45
-
46
- ## [2.1.5]
47
-
48
- ### Added
49
-
50
- - GitHub Pages documentation deployment with MkDocs Material theme
51
- - Wiki synchronization workflow that automatically syncs documentation to GitHub Wiki
52
- - Documentation validation workflow that runs on pull requests and pushes
53
- - MkDocs build validation in pre-push hooks
54
- - Searchable documentation site at <https://wallstop.github.io/DxMessaging/>
55
- - Theme-aware Mermaid diagrams with automatic light/dark mode switching for GitHub Pages
56
- - User-visible error messages when Mermaid diagrams fail to render
57
-
58
- ### Changed
59
-
60
- - Updated `documentationUrl` in package.json to point to GitHub Pages site
61
- - Enhanced README.md with links to documentation site, wiki, and changelog
62
- - Mermaid diagrams now use neutral theme fallback for GitHub/VSCode markdown preview compatibility
63
-
64
- ### Fixed
65
-
66
- - Comprehensive syntax highlighting for C# code blocks in documentation with distinct colors for keywords, types, functions, strings, numbers, comments, namespaces, and attributes
67
- - WCAG AA accessibility compliance for code syntax highlighting in both light and dark themes
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [3.0.1]
11
+
12
+ ### Added
13
+
14
+ - New Roslyn base-call analyzer (`MessageAwareComponentBaseCallAnalyzer`) that flags `MessageAwareComponent` subclasses whose lifecycle overrides forget to invoke `base.Awake()`, `base.OnEnable()`, `base.OnDisable()`, `base.OnDestroy()`, or `base.RegisterMessageHandlers()`. Introduces diagnostics `DXMSG006` (missing base call), `DXMSG007` (lifecycle method hidden with `new`), `DXMSG008` (opt-out marker), `DXMSG009` (method implicitly hides a lifecycle method without `override`/`new`), and `DXMSG010` (`base.{method}()` chains into an override that does not reach `MessageAwareComponent`). DXMSG006's diagnostic message is now per-method: each guarded method emits a sentence describing the runtime consequence (registration token never created, handlers not re-enabled, memory leak, etc.) so users immediately see what breaks. The inspector overlay HelpBox renders the same per-method sentences. Severity is tunable per project via `.editorconfig` (e.g. `dotnet_diagnostic.DXMSG006.severity = error`). Ships as a separate `WallstopStudios.DxMessaging.Analyzer.dll` deployed alongside the existing source-generator DLL by `SetupCscRsp` so it loads under both Unity 2021's Roslyn 3.8 analyzer host and newer Unity versions. Diagnostic help links now open the current analyzer reference page in the DxMessaging repository.
15
+ - Runtime self-check breadcrumb on `MessageAwareComponent`: `OnEnable` now logs a one-time `Debug.LogError` per instance when the registration token is null, with a link to the DXMSG006 reference. Gated on `UNITY_EDITOR || DEBUG`, so release builds pay no cost. Catches the case where the analyzer DLL was disabled or did not run, surfacing the silent failure as a loud editor error instead.
16
+ - New public `[DxIgnoreMissingBaseCall]` attribute (`DxMessaging.Core.Attributes`) for source-level opt-out of the base-call analyzer. Applied to a class, every guarded lifecycle method on that class is exempt; applied to a single method, only that method is exempt. The analyzer still emits an Info-level `DXMSG008` at the suppression site so opt-outs remain auditable, and the inspector overlay's snapshot honours the same scoping (method-level suppresses only the annotated method, type-level opts out the entire type). Not inherited -- derived classes must opt out explicitly.
17
+ - New inspector overlay (`MessageAwareComponentInspectorOverlay`) for every `MessageAwareComponent` subclass: missing-base-call warnings reported by the analyzer or harvested from the Unity console are surfaced as a HelpBox in the inspector header without clobbering user-defined `[CustomEditor]`s (the overlay hooks `Editor.finishedDefaultHeaderGUI`). The overlay restores the previous session's report immediately on Unity Editor startup (loaded from `Library/DxMessaging/baseCallReport.json`) instead of waiting for the first post-reload scan to complete; the HelpBox is annotated `(cached from previous session -- refreshing...)` until the first scan refreshes it. A companion fallback editor (`MessageAwareComponentFallbackEditor`) hosts the overlay for subclasses with no other custom editor and renders the body via `DrawDefaultInspector()` so subclasses with no serialized fields no longer leave an empty vertical gap below the inspector header.
18
+ - New DxMessaging project-wide settings asset (`DxMessagingSettings`, stored at `Assets/Editor/DxMessagingSettings.asset`) accessible from Unity's Project Settings. Controls diagnostics targets applied to `IMessageBus.GlobalDiagnosticsTargets`, the editor message buffer size, the domain-reload warning suppression, the base-call analyzer toggle, the project-wide base-call ignore list, and the optional Unity console bridge that feeds the inspector overlay.
19
+ - New `docs/reference/analyzers.md` reference page documenting every `DXMSG###` diagnostic the package emits, with severity, source generator/analyzer, trigger conditions, message text, and code samples for each. Added to the Reference section of the documentation site navigation.
20
+ - Added `llms.txt` plus README onboarding guidance so users can connect AI assistants with accurate DxMessaging package context.
21
+ - Test-suite hardening: parameterized scenario fixture (`MessageScenario`, `MessageScenarios`, `ScenarioHarness`, `AllocationAssertions`) under `Tests/Runtime/TestUtilities/` enabling kind-parameterized tests.
22
+ - Behavioural gap closures: `HandlerExceptionTests`, `ReentrantEmissionTests`, `NullAndInvalidInputTests`, `SingleThreadContractTests` pinning exception-in-handler, re-entrancy, null-input, and threading contracts.
23
+ - `AllocationMatrixTests` covering zero-GC dispatch across kinds, interceptors, post-processors, diagnostics, and priority-based dispatch.
24
+ - Expanded coverage now pins source-generator and analyzer behaviour that users rely on: generic / record struct / nested partial / nullable annotation cases for `DxMessageIdGenerator`; `[DxOptionalParameter]` permutations and DXMSG005 boundary cases for `DxAutoConstructorGenerator`; positive opt-out cases for `DxIgnoreMissingBaseCallAttribute`. No runtime API change.
25
+ - Three new public read-only registration counters on `IMessageBus`: `RegisteredInterceptors`, `RegisteredPostProcessors`, and `RegisteredGlobalAcceptAll`. Lets diagnostic and leak-check tooling distinguish interceptor / post-processor / global accept-all leaks from regular handler leaks, and lets external monitors aggregate the bus's registration footprint without reflecting on internals. `MessageBus` aggregates the counters on each read by walking the per-message-type caches; consumers polling these properties in tight loops should snapshot at region boundaries.
26
+ - Runtime memory-reclamation foundations: `DxMessagingRuntimeSettings` loads from `Resources/DxMessagingRuntimeSettings` and hot-reloads eviction cadence, enablement, trim opt-out, and pool-cap changes without recreating the bus. Pooled internal collections and typed/bus slot registries preserve existing dispatch APIs while making empty handler and interceptor slots reclaimable. `IMessageBus.Trim(force)` and `MessageHandler.TrimAll(force)` reset dirty empty slots and trim shared pools on demand, `OccupiedTypeSlots` / `OccupiedTargetSlots` expose the retained bus and dirty typed-handler slot footprint for diagnostics, and idle sweeps run from emits and Unity's PlayerLoop. New user-facing reference and tuning docs ship at `docs/reference/runtime-settings.md` (per-setting reference table) and `docs/guides/memory-reclamation.md` (forced trim, idle sweep, and pool tuning narrative).
27
+ - New explicit-factory registration helpers across all three DI integrations: `VContainerRegistrationExtensions.RegisterDxMessagingBus`, `ReflexRegistrationExtensions.AddDxMessagingBus`, and `ZenjectRegistrationExtensions.BindDxMessagingBus`. Each helper exposes the bus under both the concrete `MessageBus` contract and the `IMessageBus` interface, accepts an overloadable lifetime where the container supports it, accepts a user-supplied `Func<TResolver, MessageBus>` factory, and accepts an `IDxMessagingClock` overload that constructs the bus through the new internal-only `MessageBus.CreateForInternalUse` factory so test-side clocks (for example `FakeClock`) can be injected through the container. The VContainer helper registers both contracts in one registration call, avoiding VContainer environments where chained `.AsSelf().As<IMessageBus>()` drops the concrete contract and fails with `No such registration of type: DxMessaging.Core.MessageBus.MessageBus`; the DI samples either call the helper directly or document the corresponding helper preference for their container shape.
28
+
29
+ ### Changed
30
+
31
+ - Mutation tests now exercise every messaging kind (Untargeted/Targeted/Broadcast) via a single parameterized fixture (`[ValueSource(MessageScenarios.AllKinds)]`) across `MutationDuringEmissionTests`, `MutationInterceptorTests`, and `MutationDestructionTests`. Users get tighter cross-kind parity guarantees; no runtime API change. (~720 lines of duplication removed; test count preserved.)
32
+ - Renamed `UntargetedTests`, `TargetedTests`, `BroadcastTests` to `EmitUntargetedSpecificTests`, `EmitTargetedSpecificTests`, `EmitBroadcastSpecificTests` to clarify that kind-common tests live in `EmitTests` and kind-specific tests live in the renamed files. (Test-suite hardening is test-only; no `Runtime/` behavior was modified.)
33
+ - Documentation now warns up front that `MessageAwareComponent` subclasses must call `base.Awake()`, `base.OnEnable()`, `base.OnDisable()`, `base.OnDestroy()`, and `base.RegisterMessageHandlers()` from any override; admonitions added to the Quick Start, Getting Started Guide, Visual Guide, README, FAQ, and Troubleshooting pages all link to [`DXMSG006`](docs/reference/analyzers.md#dxmsg006-missing-base-call) (issue #195).
34
+
35
+ ### Fixed
36
+
37
+ - Cross-priority deregistration during in-flight emit no longer drops handlers from the current dispatch.
38
+ - Previously, when a handler at one priority removed a handler at a later priority of the same emission, the later priority's typed-handler stack was rebuilt from the now-mutated registry on first touch and the scheduled-for-removal handler was silently skipped, breaking the documented "frozen handler list per emission" contract.
39
+ - This affected sourced-broadcast, broadcast-without-source, and targeted-without-targeting dispatch (the targeted/untargeted paths already pre-froze every bucket up-front).
40
+ - The bus now pre-freezes every priority bucket's typed-handler caches up-front for every dispatch surface (sourced-broadcast, broadcast-without-source, targeted-without-targeting) and uses the per-emission snapshot count for the dispatch-loop early-out.
41
+ - The sourced-broadcast and broadcast-without-source dispatch loops also no longer short-circuit on the live `cache.handlers.Count == 0` when the per-emission snapshot still holds the deregistered handler.
42
+ - Post-processor prefreeze no longer takes a single-bucket/single-entry fast-path that skipped pre-freezing per-MessageHandler post-processor caches; a regular handler that registers a new post-processor on the same MessageHandler+priority during its own callback now sees the new post-processor on the next emission, not the in-flight one.
43
+ - The same fix extends to cross-`MessageHandler` post-processor dispatch: the inner per-handler `RunFastHandlers` overload used by `TargetedWithoutTargeting`/`BroadcastWithoutSource` post-processors now consults the per-emission snapshot list directly instead of bailing on the live `cache.entries` count, so a sibling `MessageHandler` removing a not-yet-dispatched post-processor no longer silently skips the snapshot-pinned invocation.
44
+ - `RegisterGlobalAcceptAll` (`HandleGlobalUntargeted`/`HandleGlobalTargeted`/`HandleGlobalBroadcast`) is intentionally NOT covered by this fix. The bus's global accept-all dispatch path prefreezes lazily per-entry inside the dispatch loop, so a sibling `MessageHandler` that removes another's global registration mid-emit causes the removed handler to be skipped on the in-flight emission. The behavior is pinned by `MutationPostProcessorAcrossHandlersTests.RemoveOtherGlobalAcceptAllAcrossHandlersDuringDispatch`; if a future change introduces upfront global-handler prefreeze, that test must be updated to expect the snapshot semantics that the per-kind paths already provide.
45
+ - `DxMessagingStaticState.Reset` is now race-safe against deferred deregistrations. Previously, when a message-aware component was destroyed but its disable callback had not yet run (Unity defers Object.Destroy to end of frame) and Reset ran in between, the deferred token teardown would log spurious "Received over-deregistration of {type} for {handler}" errors against the user's Unity console. The bus now stamps each captured deregister closure with a generation counter and silently no-ops closures captured before a Reset. Applied uniformly across every register entry point (untargeted, targeted, broadcast, GlobalAcceptAll, and all three interceptor kinds). The same race-safety guarantee is now propagated to user-installed custom global buses via `MessageBus.BumpResetGeneration()`, which `DxMessagingStaticState.Reset` invokes on the active global bus when it differs from the built-in default; the custom bus's sinks are intentionally left intact to avoid clobbering state the user installed it to preserve. User code is unaffected except that previously-spurious error logs disappear.
46
+ - `MessageRegistrationToken.RemoveRegistration(handle)` no longer leaks the staged registration entry, so a `Disable()`/`Enable()` cycle after `RemoveRegistration` no longer silently re-registers the removed handler. The fix also drops the matching metadata and call-count entries so diagnostic mode does not accumulate stale handles.
47
+ - Resolved [issue #204](https://github.com/wallstop/DxMessaging/issues/204) (build artifacts and orphaned `.meta` files leaking into the npm tarball) and prevented its regression: `scripts/validate-npm-meta.js` now runs `validateNoBuildArtifactsInTarball` (rejects `bin/`, `obj/`, `*.pdb`, `*.tmp`, `*.csproj.user`, `.vs/`, `.idea/`, `*.suo`, and `*.DotSettings.user` paths in the tarball) and `validatePublishedFilesArePairedWithMetas` (every shipped Unity-relevant file has its `.meta` neighbour and every shipped directory has its directory `.meta`), wired into `prepack` and the `validate-npm-meta` workflow so the next publish cannot reintroduce the regression.
48
+
49
+ ## [2.2.0]
50
+
51
+ ### Fixed
52
+
53
+ - Fixed a bug where no messages would get received by any listeners due to specifics in Unity play mode timings
54
+
55
+ ## [2.1.8]
56
+
57
+ ### Fixed
58
+
59
+ - Added npmignore for proper npm publishing (incorrectly packaging some items)
60
+
61
+ ## [2.1.7]
62
+
63
+ ### Changed
64
+
65
+ - Improved README with prominent Mental Model section
66
+ - Added Mermaid diagrams and decision flowchart for choosing message types
67
+ - Added Common Mistakes callout with troubleshooting link
68
+ - Updated performance comparison table with accurate benchmark range (10-17M ops/sec)
69
+
70
+ ### Fixed
71
+
72
+ - Regenerated corrupted meta files in `scripts/wiki`
73
+
74
+ ## [2.1.6]
75
+
76
+ ### Added
77
+
78
+ - Concepts index page and Mental Model documentation for understanding DxMessaging's design principles
79
+
80
+ ### Fixed
81
+
82
+ - Orphaned documentation pages in Concepts section now included in mkdocs.yml navigation
83
+ - Burst compiler assembly resolution errors when using DxMessaging as a package on disk and building for player platforms. Benchmarks and integration test assembly definitions now specify Editor-only platform to prevent Burst from attempting to resolve these assemblies during player builds.
84
+
85
+ ## [2.1.5]
86
+
87
+ ### Added
88
+
89
+ - GitHub Pages documentation deployment with MkDocs Material theme
90
+ - Wiki synchronization workflow that automatically syncs documentation to GitHub Wiki
91
+ - Documentation validation workflow that runs on pull requests and pushes
92
+ - MkDocs build validation in pre-push hooks
93
+ - Searchable documentation site at <https://wallstop.github.io/DxMessaging/>
94
+ - Theme-aware Mermaid diagrams with automatic light/dark mode switching for GitHub Pages
95
+ - User-visible error messages when Mermaid diagrams fail to render
96
+
97
+ ### Changed
98
+
99
+ - Updated `documentationUrl` in package.json to point to GitHub Pages site
100
+ - Enhanced README.md with links to documentation site, wiki, and changelog
101
+ - Mermaid diagrams now use neutral theme fallback for GitHub/VSCode markdown preview compatibility
102
+
103
+ ### Fixed
104
+
105
+ - Comprehensive syntax highlighting for C# code blocks in documentation with distinct colors for keywords, types, functions, strings, numbers, comments, namespaces, and attributes
106
+ - WCAG AA accessibility compliance for code syntax highlighting in both light and dark themes
package/CHANGELOG.md.meta CHANGED
@@ -1,7 +1,7 @@
1
- fileFormatVersion: 2
2
- guid: 341323775e849a648922d928083dda86
3
- TextScriptImporter:
4
- externalObjects: {}
5
- userData:
6
- assetBundleName:
7
- assetBundleVariant:
1
+ fileFormatVersion: 2
2
+ guid: 341323775e849a648922d928083dda86
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,277 @@
1
+ // The Unity Editor assembly that hosts this file does not enable nullable annotations; the
2
+ // dotnet-test project that compiles a linked copy DOES (`<Nullable>enable</Nullable>`). Pin the
3
+ // nullable state per-file so behavior is identical in both compilation contexts.
4
+ #nullable disable
5
+ namespace DxMessaging.Editor.Analyzers
6
+ {
7
+ using System;
8
+ using System.Reflection;
9
+ using System.Reflection.Emit;
10
+
11
+ /// <summary>
12
+ /// Pure (Unity-API-free) IL inspector that decides whether a given <see cref="MethodInfo"/>'s
13
+ /// IL body invokes a parent's same-named method (i.e. the IL emit shape of <c>base.X()</c>).
14
+ /// Extracted from <c>BaseCallTypeScanner</c> so the dotnet-test project can cover the byte
15
+ /// walker without depending on Unity APIs.
16
+ /// </summary>
17
+ /// <remarks>
18
+ /// <para>
19
+ /// <b>Why does this exist?</b> The console-scrape harvester is non-deterministic across Unity
20
+ /// 2021 cache hits (Unity skips routing analyzer warnings to <c>LogEntries</c> /
21
+ /// <c>CompilerMessage[]</c> on incremental compiles where Bee/csc reused a cached output).
22
+ /// IL reflection over the loaded assemblies in the AppDomain is deterministic -- the bytes do
23
+ /// not depend on Unity's compile-pipeline state. <see cref="BaseCallTypeScanner"/> uses this
24
+ /// helper to classify every loaded <c>MessageAwareComponent</c> subclass on every domain
25
+ /// reload.
26
+ /// </para>
27
+ /// <para>
28
+ /// <b>Proper OpCodes-table walker.</b> The walker decodes every CIL instruction by looking up
29
+ /// its <see cref="OpCode"/> in the static tables built from <see cref="OpCodes"/> reflection
30
+ /// (single-byte and two-byte 0xFE-prefix forms) and steps the operand-size that the opcode
31
+ /// declares (<see cref="OpCode.OperandType"/>). Misalignment past multi-byte-operand opcodes
32
+ /// (<c>switch</c> jump tables, <c>ldstr</c> 4-byte tokens, 8-byte literal constants, etc.) is
33
+ /// therefore impossible -- the walker either consumes every byte correctly or stops at the
34
+ /// first unrecognised opcode. Phantom DXMSG006 from a misread <c>0x28</c> inside a wider
35
+ /// operand is no longer a failure mode.
36
+ /// </para>
37
+ /// <para>
38
+ /// <b>Defensive bias.</b> When we cannot reason at all (null method, empty name, inaccessible
39
+ /// IL body, <c>GetMethodBody()</c> returns null on abstract / P/Invoke / IL2CPP-stripped
40
+ /// targets, or any reflection exception), the inspector returns <c>true</c>
41
+ /// ("assume clean -- calls base") so the scanner never invents a phantom warning. The
42
+ /// compile-time analyzer is the authoritative source for CI builds (DXMSG006/007/009/010 via
43
+ /// full Roslyn semantic-model precision); the IL scanner exists only to make the editor
44
+ /// overlay light up at edit-time, where a missed warning is far worse than a phantom one.
45
+ /// </para>
46
+ /// </remarks>
47
+ public static class BaseCallIlInspector
48
+ {
49
+ // CIL opcode tables, indexed by the low byte of OpCode.Value. Built once by reflecting over
50
+ // System.Reflection.Emit.OpCodes; every public static OpCode field there represents a
51
+ // canonical CIL instruction. The two-byte form of the table is used when a 0xFE prefix is
52
+ // observed in the IL stream; otherwise we use the single-byte form. Because CIL specifies
53
+ // exactly two prefix bytes (single-byte = direct, two-byte = 0xFE prefix), this division
54
+ // covers every defined opcode.
55
+ private static readonly OpCode[] s_singleByteOps = BuildOpCodeTable(twoByte: false);
56
+ private static readonly OpCode[] s_twoByteOps = BuildOpCodeTable(twoByte: true);
57
+
58
+ private static OpCode[] BuildOpCodeTable(bool twoByte)
59
+ {
60
+ OpCode[] table = new OpCode[256];
61
+ foreach (
62
+ FieldInfo field in typeof(OpCodes).GetFields(
63
+ BindingFlags.Public | BindingFlags.Static
64
+ )
65
+ )
66
+ {
67
+ if (field.GetValue(null) is not OpCode op)
68
+ {
69
+ continue;
70
+ }
71
+ ushort value = (ushort)op.Value;
72
+ bool isTwoByte = (value & 0xFF00) == 0xFE00;
73
+ bool isSingleByte = (value & 0xFF00) == 0;
74
+ if (twoByte && isTwoByte)
75
+ {
76
+ table[value & 0xFF] = op;
77
+ }
78
+ else if (!twoByte && isSingleByte)
79
+ {
80
+ table[value & 0xFF] = op;
81
+ }
82
+ }
83
+ return table;
84
+ }
85
+
86
+ /// <summary>
87
+ /// Returns <c>true</c> if <paramref name="method"/>'s IL body contains a
88
+ /// <c>call</c>/<c>callvirt</c> to a parent type's same-named method. Defensive:
89
+ /// returns <c>true</c> (assume-clean) if the IL body is null/inaccessible to avoid
90
+ /// false-positive warnings on platforms or methods where reflection on bodies is
91
+ /// restricted (abstract methods, P/Invoke, IL2CPP-stripped bodies, etc.).
92
+ /// </summary>
93
+ /// <param name="method">The override on the descendant type whose IL we wish to inspect.</param>
94
+ /// <param name="methodName">The expected base method name (e.g. <c>"OnEnable"</c>).</param>
95
+ /// <returns>
96
+ /// <c>true</c> if the IL contains a base-call shape, OR the IL was inaccessible (safe
97
+ /// default -- assume clean). <c>false</c> only when IL was readable AND no call/callvirt
98
+ /// targeting a parent same-named method was found.
99
+ /// </returns>
100
+ public static bool MethodIlContainsBaseCall(MethodInfo method, string methodName)
101
+ {
102
+ if (method == null || string.IsNullOrEmpty(methodName))
103
+ {
104
+ // Defensive: treat as clean when we don't have enough information to reason. This
105
+ // ensures the scanner never emits a phantom warning on a degenerate input.
106
+ return true;
107
+ }
108
+
109
+ try
110
+ {
111
+ MethodBody body = method.GetMethodBody();
112
+ if (body == null)
113
+ {
114
+ // Abstract / extern / runtime-implemented / IL2CPP-stripped; cannot inspect.
115
+ return true;
116
+ }
117
+
118
+ byte[] il = body.GetILAsByteArray();
119
+ if (il == null || il.Length == 0)
120
+ {
121
+ return true;
122
+ }
123
+
124
+ Module module = method.Module;
125
+ Type[] genericTypeArgs =
126
+ method.DeclaringType?.IsGenericType == true
127
+ ? method.DeclaringType.GetGenericArguments()
128
+ : null;
129
+ Type[] genericMethodArgs = method.IsGenericMethod
130
+ ? method.GetGenericArguments()
131
+ : null;
132
+
133
+ int i = 0;
134
+ while (i < il.Length)
135
+ {
136
+ OpCode op;
137
+ if (il[i] == 0xFE)
138
+ {
139
+ // Two-byte (0xFE-prefixed) opcode. Without a following byte we cannot
140
+ // decode the instruction; bail out conservatively. Truncated IL is not a
141
+ // shape Roslyn ever emits, so reaching this path means we mis-stepped and
142
+ // the safest answer is the assume-clean default.
143
+ if (i + 1 >= il.Length)
144
+ {
145
+ return true;
146
+ }
147
+ op = s_twoByteOps[il[i + 1]];
148
+ i += 2;
149
+ }
150
+ else
151
+ {
152
+ op = s_singleByteOps[il[i]];
153
+ i += 1;
154
+ }
155
+
156
+ // Unrecognised opcode (zero-initialised slot in the table); abandon the walk
157
+ // rather than risk the rest of the stream getting misread. Returning the
158
+ // assume-clean default keeps the scanner from inventing a phantom warning.
159
+ if (op.Size == 0)
160
+ {
161
+ return true;
162
+ }
163
+
164
+ if (op == OpCodes.Call || op == OpCodes.Callvirt)
165
+ {
166
+ if (i + 4 > il.Length)
167
+ {
168
+ return true;
169
+ }
170
+ int token = BitConverter.ToInt32(il, i);
171
+ try
172
+ {
173
+ MethodBase target = module.ResolveMethod(
174
+ token,
175
+ genericTypeArgs,
176
+ genericMethodArgs
177
+ );
178
+ if (
179
+ target != null
180
+ && string.Equals(target.Name, methodName, StringComparison.Ordinal)
181
+ )
182
+ {
183
+ Type declaring = method.DeclaringType;
184
+ Type resolved = target.DeclaringType;
185
+ // Guard against false-positives: the resolved method must live on a
186
+ // STRICT base type of the declaring class (not the declaring class
187
+ // itself, not a sibling, not a generic-arg shadow). IsAssignableFrom
188
+ // checks "is `declaring` assignable TO `resolved`"; i.e. is
189
+ // `resolved` an ancestor of `declaring`.
190
+ if (
191
+ declaring != null
192
+ && resolved != null
193
+ && declaring != resolved
194
+ && resolved.IsAssignableFrom(declaring)
195
+ )
196
+ {
197
+ return true;
198
+ }
199
+ }
200
+ }
201
+ catch
202
+ {
203
+ // ResolveMethod throws on tokens that don't bind in our generic-arg
204
+ // context (e.g. a MemberRef into a closed generic we can't resolve).
205
+ // The OpCodes-table walker means we can no longer land on a misaligned
206
+ // 0x28 inside a wider operand, so this catch only protects against
207
+ // legitimate-but-unbindable tokens; we swallow and continue scanning.
208
+ }
209
+ i += 4;
210
+ continue;
211
+ }
212
+
213
+ // Step over the operand based on the opcode's declared operand type. Every
214
+ // CIL operand size is decided by OperandType, which is exactly why the table
215
+ // walker is misalignment-proof.
216
+ i += GetOperandSize(op, il, i);
217
+ }
218
+ return false;
219
+ }
220
+ catch
221
+ {
222
+ // Any reflection failure → assume clean. We never want the scanner itself to
223
+ // become the source of a phantom warning.
224
+ return true;
225
+ }
226
+ }
227
+
228
+ // Returns the number of operand bytes that follow an opcode of the given OperandType,
229
+ // given the operand-start offset (needed for InlineSwitch's variable-length jump table).
230
+ private static int GetOperandSize(OpCode op, byte[] il, int operandStart)
231
+ {
232
+ switch (op.OperandType)
233
+ {
234
+ case OperandType.InlineNone:
235
+ return 0;
236
+ case OperandType.ShortInlineBrTarget:
237
+ case OperandType.ShortInlineI:
238
+ case OperandType.ShortInlineVar:
239
+ return 1;
240
+ case OperandType.InlineVar:
241
+ return 2;
242
+ case OperandType.InlineBrTarget:
243
+ case OperandType.InlineField:
244
+ case OperandType.InlineI:
245
+ case OperandType.InlineMethod:
246
+ case OperandType.InlineSig:
247
+ case OperandType.InlineString:
248
+ case OperandType.InlineTok:
249
+ case OperandType.InlineType:
250
+ case OperandType.ShortInlineR:
251
+ return 4;
252
+ case OperandType.InlineI8:
253
+ case OperandType.InlineR:
254
+ return 8;
255
+ case OperandType.InlineSwitch:
256
+ // 4-byte case count, then N × 4-byte branch targets. Truncated stream → bail
257
+ // by consuming the rest defensively (the outer loop's bounds check then ends
258
+ // the walk).
259
+ if (operandStart + 4 > il.Length)
260
+ {
261
+ return il.Length - operandStart;
262
+ }
263
+ int caseCount = BitConverter.ToInt32(il, operandStart);
264
+ if (caseCount < 0)
265
+ {
266
+ // Negative case-count is malformed IL; bail conservatively.
267
+ return il.Length - operandStart;
268
+ }
269
+ return 4 + caseCount * 4;
270
+ default:
271
+ // Unknown OperandType; bail conservatively by consuming the rest of the
272
+ // stream so the outer loop terminates without misaligning further.
273
+ return il.Length - operandStart;
274
+ }
275
+ }
276
+ }
277
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: f713afea6aef44cab4d711a4f2d17d6e
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant: