com.wallstop-studios.dxmessaging 2.2.0 → 3.1.0

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 (270) hide show
  1. package/CHANGELOG.md +315 -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 +1129 -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 +46 -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 +11 -3
  26. package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs +81 -0
  27. package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs.meta +11 -0
  28. package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs +429 -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 +11 -3
  32. package/Editor/CustomEditors.meta +2 -2
  33. package/Editor/DxMessagingEditorIdle.cs +62 -0
  34. package/Editor/DxMessagingEditorIdle.cs.meta +11 -0
  35. package/Editor/DxMessagingEditorInitializer.cs +112 -15
  36. package/Editor/DxMessagingEditorInitializer.cs.meta +11 -3
  37. package/Editor/DxMessagingEditorLog.cs +32 -0
  38. package/Editor/DxMessagingEditorLog.cs.meta +11 -0
  39. package/Editor/DxMessagingMenu.cs.meta +11 -11
  40. package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -11
  41. package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs +313 -0
  42. package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs.meta +11 -0
  43. package/Editor/Settings/DxMessagingSettings.cs +261 -11
  44. package/Editor/Settings/DxMessagingSettings.cs.meta +11 -3
  45. package/Editor/Settings/DxMessagingSettingsProvider.cs +50 -33
  46. package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +11 -3
  47. package/Editor/Settings.meta +2 -2
  48. package/Editor/SetupCscRsp.cs +406 -39
  49. package/Editor/SetupCscRsp.cs.meta +11 -3
  50. package/Editor/Testing/MessagingComponentEditorHarness.cs +2 -2
  51. package/Editor/Testing/MessagingComponentEditorHarness.cs.meta +11 -3
  52. package/Editor/Testing.meta +3 -3
  53. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef +14 -14
  54. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef.meta +7 -7
  55. package/Editor.meta +8 -8
  56. package/LICENSE.md +9 -9
  57. package/LICENSE.md.meta +7 -7
  58. package/README.md +940 -900
  59. package/README.md.meta +7 -7
  60. package/Runtime/AssemblyInfo.cs +4 -0
  61. package/Runtime/AssemblyInfo.cs.meta +11 -3
  62. package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs.meta +11 -3
  63. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs.meta +11 -3
  64. package/Runtime/Core/Attributes/DxIgnoreMissingBaseCallAttribute.cs +26 -0
  65. package/Runtime/Core/Attributes/DxIgnoreMissingBaseCallAttribute.cs.meta +11 -0
  66. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +2 -4
  67. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs.meta +11 -3
  68. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs.meta +11 -3
  69. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs.meta +11 -3
  70. package/Runtime/Core/Attributes/Il2CppSetOptionAttribute.cs +56 -0
  71. package/Runtime/Core/Attributes/Il2CppSetOptionAttribute.cs.meta +11 -0
  72. package/Runtime/Core/Attributes.meta +2 -2
  73. package/Runtime/Core/Configuration/DxMessagingRuntimeSettings.cs +195 -0
  74. package/Runtime/Core/Configuration/DxMessagingRuntimeSettings.cs.meta +11 -0
  75. package/Runtime/Core/Configuration/DxMessagingRuntimeSettingsProvider.cs +179 -0
  76. package/Runtime/Core/Configuration/DxMessagingRuntimeSettingsProvider.cs.meta +11 -0
  77. package/Runtime/Core/Configuration.meta +9 -0
  78. package/Runtime/Core/DataStructure/CyclicBuffer.cs +46 -28
  79. package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +11 -3
  80. package/Runtime/Core/DataStructure.meta +2 -2
  81. package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +11 -3
  82. package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +11 -3
  83. package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +11 -3
  84. package/Runtime/Core/Diagnostics.meta +2 -2
  85. package/Runtime/Core/DxMessagingStaticState.cs +19 -0
  86. package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -11
  87. package/Runtime/Core/Extensions/EnumExtensions.cs +6 -5
  88. package/Runtime/Core/Extensions/EnumExtensions.cs.meta +11 -3
  89. package/Runtime/Core/Extensions/IListExtensions.cs.meta +11 -3
  90. package/Runtime/Core/Extensions/MessageBusExtensions.cs.meta +12 -12
  91. package/Runtime/Core/Extensions/MessageExtensions.cs +0 -60
  92. package/Runtime/Core/Extensions/MessageExtensions.cs.meta +11 -11
  93. package/Runtime/Core/Extensions.meta +8 -8
  94. package/Runtime/Core/Helper/MessageCache.cs +32 -0
  95. package/Runtime/Core/Helper/MessageCache.cs.meta +11 -3
  96. package/Runtime/Core/Helper/MessageHelperIndexer.cs.meta +11 -3
  97. package/Runtime/Core/Helper.meta +2 -2
  98. package/Runtime/Core/IMessage.cs +3 -3
  99. package/Runtime/Core/IMessage.cs.meta +11 -11
  100. package/Runtime/Core/InstanceId.cs +25 -1
  101. package/Runtime/Core/InstanceId.cs.meta +11 -11
  102. package/Runtime/Core/Internal/DxUnsafe.cs +60 -0
  103. package/Runtime/Core/Internal/DxUnsafe.cs.meta +11 -0
  104. package/Runtime/Core/Internal/FlatDispatch.cs +198 -0
  105. package/Runtime/Core/Internal/FlatDispatch.cs.meta +11 -0
  106. package/Runtime/Core/Internal/TypedGlobalSlotIndex.cs +38 -0
  107. package/Runtime/Core/Internal/TypedGlobalSlotIndex.cs.meta +11 -0
  108. package/Runtime/Core/Internal/TypedSlotIndex.cs +81 -0
  109. package/Runtime/Core/Internal/TypedSlotIndex.cs.meta +11 -0
  110. package/Runtime/Core/Internal/TypedSlots.cs +597 -0
  111. package/Runtime/Core/Internal/TypedSlots.cs.meta +11 -0
  112. package/Runtime/Core/Internal.meta +9 -0
  113. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -11
  114. package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +11 -11
  115. package/Runtime/Core/MessageBus/IMessageBus.cs +189 -15
  116. package/Runtime/Core/MessageBus/IMessageBus.cs.meta +11 -11
  117. package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +11 -11
  118. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +1 -0
  119. package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +11 -11
  120. package/Runtime/Core/MessageBus/Internal/BusContextIndex.cs +16 -0
  121. package/Runtime/Core/MessageBus/Internal/BusContextIndex.cs.meta +11 -0
  122. package/Runtime/Core/MessageBus/Internal/BusSinkIndex.cs +40 -0
  123. package/Runtime/Core/MessageBus/Internal/BusSinkIndex.cs.meta +11 -0
  124. package/Runtime/Core/MessageBus/Internal/BusSlots.cs +719 -0
  125. package/Runtime/Core/MessageBus/Internal/BusSlots.cs.meta +11 -0
  126. package/Runtime/Core/MessageBus/Internal/DispatchKind.cs +38 -0
  127. package/Runtime/Core/MessageBus/Internal/DispatchKind.cs.meta +11 -0
  128. package/Runtime/Core/MessageBus/Internal/DispatchPhase.cs +20 -0
  129. package/Runtime/Core/MessageBus/Internal/DispatchPhase.cs.meta +11 -0
  130. package/Runtime/Core/MessageBus/Internal/DispatchVariant.cs +28 -0
  131. package/Runtime/Core/MessageBus/Internal/DispatchVariant.cs.meta +11 -0
  132. package/Runtime/Core/MessageBus/Internal/IEvictableSlot.cs +48 -0
  133. package/Runtime/Core/MessageBus/Internal/IEvictableSlot.cs.meta +11 -0
  134. package/Runtime/Core/MessageBus/Internal/ISweepable.cs +15 -0
  135. package/Runtime/Core/MessageBus/Internal/ISweepable.cs.meta +11 -0
  136. package/Runtime/Core/MessageBus/Internal/RegistrationMethodAxes.cs +222 -0
  137. package/Runtime/Core/MessageBus/Internal/RegistrationMethodAxes.cs.meta +11 -0
  138. package/Runtime/Core/MessageBus/Internal/SlotKey.cs +192 -0
  139. package/Runtime/Core/MessageBus/Internal/SlotKey.cs.meta +11 -0
  140. package/Runtime/Core/MessageBus/Internal.meta +9 -0
  141. package/Runtime/Core/MessageBus/MessageBus.cs +5366 -3838
  142. package/Runtime/Core/MessageBus/MessageBus.cs.meta +11 -11
  143. package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +11 -11
  144. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +187 -14
  145. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +11 -11
  146. package/Runtime/Core/MessageBus/MessagingRegistration.cs.meta +11 -11
  147. package/Runtime/Core/MessageBus/RegistrationLog.cs.meta +11 -11
  148. package/Runtime/Core/MessageBus.meta +8 -8
  149. package/Runtime/Core/MessageHandler.cs +2399 -1042
  150. package/Runtime/Core/MessageHandler.cs.meta +11 -11
  151. package/Runtime/Core/MessageRegistrationHandle.cs.meta +11 -11
  152. package/Runtime/Core/MessageRegistrationToken.cs +429 -44
  153. package/Runtime/Core/MessageRegistrationToken.cs.meta +11 -11
  154. package/Runtime/Core/Messages/GlobalStringMessage.cs.meta +11 -3
  155. package/Runtime/Core/Messages/IBroadcastMessage.cs.meta +11 -11
  156. package/Runtime/Core/Messages/ITargetedMessage.cs.meta +11 -11
  157. package/Runtime/Core/Messages/IUntargetedMessage.cs.meta +11 -11
  158. package/Runtime/Core/Messages/ReflexiveMessage.cs.meta +11 -3
  159. package/Runtime/Core/Messages/SourcedStringMessage.cs.meta +11 -11
  160. package/Runtime/Core/Messages/StringMessage.cs.meta +11 -3
  161. package/Runtime/Core/Messages.meta +8 -8
  162. package/Runtime/Core/MessagingDebug.cs.meta +11 -11
  163. package/Runtime/Core/Pooling/CollectionPool.cs +266 -0
  164. package/Runtime/Core/Pooling/CollectionPool.cs.meta +11 -0
  165. package/Runtime/Core/Pooling/CollectionPoolDiagnostics.cs +30 -0
  166. package/Runtime/Core/Pooling/CollectionPoolDiagnostics.cs.meta +11 -0
  167. package/Runtime/Core/Pooling/DxPools.cs +157 -0
  168. package/Runtime/Core/Pooling/DxPools.cs.meta +11 -0
  169. package/Runtime/Core/Pooling/EvictionPlayerLoopHook.cs +106 -0
  170. package/Runtime/Core/Pooling/EvictionPlayerLoopHook.cs.meta +11 -0
  171. package/Runtime/Core/Pooling/IDxMessagingClock.cs +18 -0
  172. package/Runtime/Core/Pooling/IDxMessagingClock.cs.meta +11 -0
  173. package/Runtime/Core/Pooling/PoolDiagnosticsSnapshot.cs +55 -0
  174. package/Runtime/Core/Pooling/PoolDiagnosticsSnapshot.cs.meta +11 -0
  175. package/Runtime/Core/Pooling/StopwatchClock.cs +27 -0
  176. package/Runtime/Core/Pooling/StopwatchClock.cs.meta +11 -0
  177. package/Runtime/Core/Pooling/UnityRealtimeClock.cs +31 -0
  178. package/Runtime/Core/Pooling/UnityRealtimeClock.cs.meta +11 -0
  179. package/Runtime/Core/Pooling.meta +9 -0
  180. package/Runtime/Core.meta +8 -8
  181. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +12 -12
  182. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -11
  183. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +12 -12
  184. package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +11 -3
  185. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +73 -0
  186. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +11 -11
  187. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef +20 -20
  188. package/Runtime/Unity/Integrations/Reflex/WallstopStudios.DxMessaging.Reflex.asmdef.meta +7 -7
  189. package/Runtime/Unity/Integrations/Reflex.meta +8 -8
  190. package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +11 -3
  191. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +109 -1
  192. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +11 -11
  193. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef +30 -30
  194. package/Runtime/Unity/Integrations/VContainer/WallstopStudios.DxMessaging.VContainer.asmdef.meta +7 -7
  195. package/Runtime/Unity/Integrations/VContainer.meta +8 -8
  196. package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +11 -3
  197. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef +30 -30
  198. package/Runtime/Unity/Integrations/Zenject/WallstopStudios.DxMessaging.Zenject.asmdef.meta +7 -7
  199. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +79 -1
  200. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +11 -11
  201. package/Runtime/Unity/Integrations/Zenject.meta +8 -8
  202. package/Runtime/Unity/Integrations.meta +8 -8
  203. package/Runtime/Unity/MessageAwareComponent.cs +74 -0
  204. package/Runtime/Unity/MessageAwareComponent.cs.meta +11 -11
  205. package/Runtime/Unity/MessageBusProviderHandle.cs.meta +12 -12
  206. package/Runtime/Unity/MessagingComponent.cs +43 -10
  207. package/Runtime/Unity/MessagingComponent.cs.meta +11 -11
  208. package/Runtime/Unity/MessagingComponentInstaller.cs.meta +12 -12
  209. package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +12 -12
  210. package/Runtime/Unity.meta +8 -8
  211. package/Runtime/WallstopStudios.DxMessaging.asmdef +14 -14
  212. package/Runtime/WallstopStudios.DxMessaging.asmdef.meta +7 -7
  213. package/Runtime.meta +8 -8
  214. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab +98 -98
  215. package/Samples~/DI/Prefabs/MessagingInstallerSample.prefab.meta +7 -7
  216. package/Samples~/DI/Prefabs.meta +8 -8
  217. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset +14 -14
  218. package/Samples~/DI/Providers/GlobalMessageBusProvider.asset.meta +8 -8
  219. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset +14 -14
  220. package/Samples~/DI/Providers/InitialGlobalMessageBusProvider.asset.meta +8 -8
  221. package/Samples~/DI/Providers.meta +8 -8
  222. package/Samples~/DI/README.md +51 -51
  223. package/Samples~/DI/README.md.meta +7 -7
  224. package/Samples~/DI/Reflex/SampleInstaller.cs +7 -0
  225. package/Samples~/DI/Reflex/SampleInstaller.cs.meta +11 -11
  226. package/Samples~/DI/Reflex.meta +8 -8
  227. package/Samples~/DI/VContainer/SampleLifetimeScope.cs +6 -1
  228. package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +11 -11
  229. package/Samples~/DI/VContainer.meta +8 -8
  230. package/Samples~/DI/Zenject/SampleInstaller.cs +8 -0
  231. package/Samples~/DI/Zenject/SampleInstaller.cs.meta +11 -11
  232. package/Samples~/DI/Zenject.meta +8 -8
  233. package/Samples~/DI.meta +8 -8
  234. package/Samples~/Mini Combat/Boot.cs.meta +11 -11
  235. package/Samples~/Mini Combat/Enemy.cs.meta +11 -11
  236. package/Samples~/Mini Combat/Messages.cs.meta +11 -11
  237. package/Samples~/Mini Combat/Player.cs.meta +11 -11
  238. package/Samples~/Mini Combat/README.md +324 -323
  239. package/Samples~/Mini Combat/README.md.meta +7 -7
  240. package/Samples~/Mini Combat/UIOverlay.cs.meta +11 -11
  241. package/Samples~/Mini Combat/Walkthrough.md +430 -430
  242. package/Samples~/Mini Combat/Walkthrough.md.meta +7 -7
  243. package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef +13 -13
  244. package/Samples~/Mini Combat/WallstopStudios.DxMessaging.MiniCombat.Sample.asmdef.meta +7 -7
  245. package/Samples~/Mini Combat.meta +8 -8
  246. package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs.meta +11 -11
  247. package/Samples~/UI Buttons + Inspector/Messages.cs.meta +11 -11
  248. package/Samples~/UI Buttons + Inspector/MessagingObserver.cs.meta +11 -11
  249. package/Samples~/UI Buttons + Inspector/README.md +210 -209
  250. package/Samples~/UI Buttons + Inspector/README.md.meta +7 -7
  251. package/Samples~/UI Buttons + Inspector/UIButtonEmitter.cs.meta +11 -11
  252. package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef +13 -13
  253. package/Samples~/UI Buttons + Inspector/WallstopStudios.DxMessaging.UIButtons.Sample.asmdef.meta +7 -7
  254. package/Samples~/UI Buttons + Inspector.meta +8 -8
  255. package/SourceGenerators/Directory.Build.props +50 -3
  256. package/SourceGenerators/Directory.Build.props.meta +7 -7
  257. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +96 -63
  258. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs.meta +11 -11
  259. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +745 -87
  260. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs.meta +11 -3
  261. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +39 -46
  262. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj.meta +7 -7
  263. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.meta +8 -8
  264. package/SourceGenerators/global.json +7 -0
  265. package/SourceGenerators/global.json.meta +7 -0
  266. package/SourceGenerators.meta +8 -8
  267. package/Third Party Notices.md +3 -3
  268. package/Third Party Notices.md.meta +7 -7
  269. package/package.json +102 -92
  270. package/package.json.meta +7 -7
@@ -0,0 +1,308 @@
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.Collections.Generic;
9
+
10
+ /// <summary>
11
+ /// Pure-BCL data-transfer object for an aggregated per-FQN report row. Mirrors the public
12
+ /// shape of <see cref="BaseCallReportEntry"/> but uses property-style PascalCase fields so it
13
+ /// does not depend on Unity's <c>JsonUtility</c> serialization conventions and is safely
14
+ /// constructible from <c>dotnet test</c>.
15
+ /// </summary>
16
+ /// <remarks>
17
+ /// The harvester wraps every DTO in a <see cref="BaseCallReportEntry"/> (with the lowercase
18
+ /// Unity-serialisable field names) before the snapshot crosses into Editor code. Keep this
19
+ /// shape in lock-step with that wrapper -- fields added here must also flow through to the
20
+ /// Unity-facing entry or the inspector overlay won't see them.
21
+ /// </remarks>
22
+ public sealed class BaseCallReportEntryDto
23
+ {
24
+ /// <summary>Fully-qualified name of the offending type (dot-form for nested types).</summary>
25
+ public string TypeName;
26
+
27
+ /// <summary>Method names whose overrides are missing the corresponding <c>base.*()</c> call.</summary>
28
+ public readonly SortedSet<string> MissingBaseFor = new(StringComparer.Ordinal);
29
+
30
+ /// <summary>Diagnostic IDs that contributed to this entry (e.g., DXMSG006/007/008/009).</summary>
31
+ public readonly HashSet<string> DiagnosticIds = new(StringComparer.Ordinal);
32
+
33
+ /// <summary>Source file path (best-effort) for "Open Script" actions in the inspector overlay.</summary>
34
+ public string FilePath;
35
+
36
+ /// <summary>1-based line number of the first relevant diagnostic, when known.</summary>
37
+ public int Line;
38
+ }
39
+
40
+ /// <summary>
41
+ /// Pure (Unity-API-free) aggregator for the per-assembly merge + retirement logic at the heart
42
+ /// of <see cref="DxMessagingConsoleHarvester"/>. Extracted so the merge contract is covered by
43
+ /// <c>dotnet test</c> via the linked-source pattern (see
44
+ /// <c>WallstopStudios.DxMessaging.SourceGenerators.Tests.csproj</c>).
45
+ /// </summary>
46
+ /// <remarks>
47
+ /// <para>
48
+ /// The harvester must own two pieces of cross-call state to do its job correctly:
49
+ /// </para>
50
+ /// <list type="number">
51
+ /// <item><description><c>typesByAssembly</c>: which FQNs each compiled assembly has reported.
52
+ /// When an assembly recompiles WITHOUT reporting a previously-seen FQN, that FQN is retired
53
+ /// -- the user fixed the offending base call.</description></item>
54
+ /// <item><description><c>mergedReports</c>: the per-FQN union of every assembly's latest
55
+ /// report. The final snapshot merges this with whatever the LogEntries scan yielded.</description></item>
56
+ /// </list>
57
+ /// <para>
58
+ /// Both maps mutate in lock-step inside <see cref="ApplyAssemblyReports"/>. Because retirement
59
+ /// crosses assembly boundaries (an FQN may live in two assemblies; only when neither still
60
+ /// reports it does it disappear from <c>mergedReports</c>), the bookkeeping is the most
61
+ /// failure-prone slice of the harvester. Keeping it pure makes it test-driven.
62
+ /// </para>
63
+ /// </remarks>
64
+ public static class BaseCallReportAggregator
65
+ {
66
+ /// <summary>
67
+ /// Apply a single assembly's freshly-parsed report batch. Replaces that assembly's prior
68
+ /// FQN attribution wholesale (so types the user fixed disappear) and rebuilds the merged
69
+ /// per-FQN map by unioning every assembly's latest reports.
70
+ /// </summary>
71
+ /// <param name="assemblyKey">Stable identifier for the source assembly (typically the
72
+ /// assembly path Unity passes via <c>CompilationPipeline.assemblyCompilationFinished</c>).</param>
73
+ /// <param name="latestReportsForAssembly">Reports parsed from this assembly's most recent
74
+ /// compilation. May be empty -- that case is the retirement path (every FQN this assembly
75
+ /// previously reported is dropped).</param>
76
+ /// <param name="typesByAssembly">Per-assembly FQN bookkeeping. Mutated in place.</param>
77
+ /// <param name="mergedReports">Per-FQN union across every assembly. Mutated in place;
78
+ /// rebuilt from scratch on every call so retirement Just Works regardless of which
79
+ /// assembly drops its claim.</param>
80
+ public static void ApplyAssemblyReports(
81
+ string assemblyKey,
82
+ IReadOnlyDictionary<string, ParsedTypeReport> latestReportsForAssembly,
83
+ Dictionary<string, HashSet<string>> typesByAssembly,
84
+ Dictionary<string, ParsedTypeReport> mergedReports
85
+ )
86
+ {
87
+ if (string.IsNullOrEmpty(assemblyKey))
88
+ {
89
+ throw new ArgumentException("Assembly key must be non-empty.", nameof(assemblyKey));
90
+ }
91
+ if (typesByAssembly is null)
92
+ {
93
+ throw new ArgumentNullException(nameof(typesByAssembly));
94
+ }
95
+ if (mergedReports is null)
96
+ {
97
+ throw new ArgumentNullException(nameof(mergedReports));
98
+ }
99
+
100
+ // 1. Replace this assembly's FQN set with the latest batch. Types absent from the new
101
+ // batch are dropped from the assembly's row; that's the per-assembly retirement.
102
+ if (!typesByAssembly.TryGetValue(assemblyKey, out HashSet<string> typeSet))
103
+ {
104
+ typeSet = new HashSet<string>(StringComparer.Ordinal);
105
+ typesByAssembly[assemblyKey] = typeSet;
106
+ }
107
+ typeSet.Clear();
108
+ if (latestReportsForAssembly is not null)
109
+ {
110
+ foreach (string fqn in latestReportsForAssembly.Keys)
111
+ {
112
+ if (!string.IsNullOrEmpty(fqn))
113
+ {
114
+ typeSet.Add(fqn);
115
+ }
116
+ }
117
+ }
118
+
119
+ // 2. Rebuild mergedReports from the per-assembly view. We can't simply remove "the
120
+ // types this assembly retired" because another assembly may still report them; the
121
+ // only correct algorithm is to start fresh from typesByAssembly + the freshest
122
+ // payload for each (assembly, FQN) pair.
123
+ //
124
+ // Per-FQN merge semantics:
125
+ // - Method list: union, deduplicated ordinally, stored in deterministic
126
+ // ordinal-sorted order.
127
+ // - Diagnostic IDs: union via HashSet.
128
+ // - File path / line: first non-empty wins (stable across recompiles).
129
+ Dictionary<string, ParsedTypeReport> rebuilt = new(StringComparer.Ordinal);
130
+ foreach (KeyValuePair<string, HashSet<string>> assemblyEntry in typesByAssembly)
131
+ {
132
+ string thisAssemblyKey = assemblyEntry.Key;
133
+ HashSet<string> fqns = assemblyEntry.Value;
134
+ if (fqns is null || fqns.Count == 0)
135
+ {
136
+ continue;
137
+ }
138
+
139
+ // For the assembly we just updated, prefer the freshly-parsed payload. For other
140
+ // assemblies, we need the previous merge to still carry their data; but that
141
+ // information is only retrievable from the OUTGOING mergedReports, so we read it
142
+ // before clearing.
143
+ IReadOnlyDictionary<string, ParsedTypeReport> source = string.Equals(
144
+ thisAssemblyKey,
145
+ assemblyKey,
146
+ StringComparison.OrdinalIgnoreCase
147
+ )
148
+ ? latestReportsForAssembly
149
+ : mergedReports;
150
+ if (source is null)
151
+ {
152
+ continue;
153
+ }
154
+
155
+ foreach (string fqn in fqns)
156
+ {
157
+ if (!source.TryGetValue(fqn, out ParsedTypeReport contribution))
158
+ {
159
+ continue;
160
+ }
161
+ if (contribution is null)
162
+ {
163
+ continue;
164
+ }
165
+
166
+ if (!rebuilt.TryGetValue(fqn, out ParsedTypeReport existing))
167
+ {
168
+ // Defensive copy so future ApplyAssemblyReports calls don't mutate state
169
+ // that callers may still hold a reference to.
170
+ existing = new ParsedTypeReport
171
+ {
172
+ TypeFullName = contribution.TypeFullName,
173
+ FilePath = contribution.FilePath,
174
+ Line = contribution.Line,
175
+ };
176
+ foreach (string method in contribution.MissingBaseFor)
177
+ {
178
+ if (!string.IsNullOrEmpty(method))
179
+ {
180
+ existing.MissingBaseFor.Add(method);
181
+ }
182
+ }
183
+ foreach (string id in contribution.DiagnosticIds)
184
+ {
185
+ existing.DiagnosticIds.Add(id);
186
+ }
187
+ rebuilt[fqn] = existing;
188
+ continue;
189
+ }
190
+
191
+ foreach (string method in contribution.MissingBaseFor)
192
+ {
193
+ if (!string.IsNullOrEmpty(method))
194
+ {
195
+ existing.MissingBaseFor.Add(method);
196
+ }
197
+ }
198
+ foreach (string id in contribution.DiagnosticIds)
199
+ {
200
+ existing.DiagnosticIds.Add(id);
201
+ }
202
+ if (
203
+ string.IsNullOrEmpty(existing.FilePath)
204
+ && !string.IsNullOrEmpty(contribution.FilePath)
205
+ )
206
+ {
207
+ existing.FilePath = contribution.FilePath;
208
+ existing.Line = contribution.Line;
209
+ }
210
+ }
211
+ }
212
+
213
+ mergedReports.Clear();
214
+ foreach (KeyValuePair<string, ParsedTypeReport> kvp in rebuilt)
215
+ {
216
+ mergedReports[kvp.Key] = kvp.Value;
217
+ }
218
+ }
219
+
220
+ /// <summary>
221
+ /// Builds the final flat snapshot for the inspector overlay by unioning the LogEntries
222
+ /// scan with the per-assembly merged reports. Both inputs are read-only; the result is a
223
+ /// fresh dictionary the caller owns.
224
+ /// </summary>
225
+ /// <param name="logEntriesReports">Reports harvested from <c>UnityEditor.LogEntries</c>.
226
+ /// May be empty (Unity 2021 path) or null (LogEntries reflection unavailable).</param>
227
+ /// <param name="mergedReports">Per-FQN merged view of every assembly's latest reports
228
+ /// produced by <see cref="ApplyAssemblyReports"/>. May be empty when no compilation
229
+ /// callbacks have fired yet.</param>
230
+ public static Dictionary<string, BaseCallReportEntryDto> BuildSnapshot(
231
+ IReadOnlyDictionary<string, ParsedTypeReport> logEntriesReports,
232
+ IReadOnlyDictionary<string, ParsedTypeReport> mergedReports
233
+ )
234
+ {
235
+ Dictionary<string, BaseCallReportEntryDto> snapshot = new(StringComparer.Ordinal);
236
+
237
+ if (logEntriesReports is not null)
238
+ {
239
+ foreach (KeyValuePair<string, ParsedTypeReport> kvp in logEntriesReports)
240
+ {
241
+ AddOrMerge(snapshot, kvp.Key, kvp.Value);
242
+ }
243
+ }
244
+
245
+ if (mergedReports is not null)
246
+ {
247
+ foreach (KeyValuePair<string, ParsedTypeReport> kvp in mergedReports)
248
+ {
249
+ AddOrMerge(snapshot, kvp.Key, kvp.Value);
250
+ }
251
+ }
252
+
253
+ return snapshot;
254
+ }
255
+
256
+ private static void AddOrMerge(
257
+ Dictionary<string, BaseCallReportEntryDto> snapshot,
258
+ string fqn,
259
+ ParsedTypeReport report
260
+ )
261
+ {
262
+ if (string.IsNullOrEmpty(fqn) || report is null)
263
+ {
264
+ return;
265
+ }
266
+
267
+ if (!snapshot.TryGetValue(fqn, out BaseCallReportEntryDto existing))
268
+ {
269
+ existing = new BaseCallReportEntryDto { TypeName = fqn };
270
+ snapshot[fqn] = existing;
271
+ }
272
+ if (string.IsNullOrEmpty(existing.TypeName))
273
+ {
274
+ existing.TypeName = fqn;
275
+ }
276
+
277
+ foreach (string method in report.MissingBaseFor)
278
+ {
279
+ if (!string.IsNullOrEmpty(method))
280
+ {
281
+ // Dedupe across the dual-source merge: LogEntries and CompilerMessage may
282
+ // both surface the same `<type>.<method>` pair on Unity 2022+, where both
283
+ // pipes are wired. MissingBaseFor is a SortedSet<string>, so duplicates are
284
+ // removed and HelpBox output remains stable via deterministic ordinal sorting.
285
+ existing.MissingBaseFor.Add(method);
286
+ }
287
+ }
288
+
289
+ foreach (string id in report.DiagnosticIds)
290
+ {
291
+ if (!string.IsNullOrEmpty(id))
292
+ {
293
+ // HashSet dedupes repeated IDs surfaced by the dual-source merge
294
+ // (LogEntries + CompilerMessage on Unity 2022+).
295
+ existing.DiagnosticIds.Add(id);
296
+ }
297
+ }
298
+
299
+ // First seen file/line wins so "Open Script" jumps to a stable location across
300
+ // rebuilds; which is what the user's eye lands on first in the console.
301
+ if (string.IsNullOrEmpty(existing.FilePath) && !string.IsNullOrEmpty(report.FilePath))
302
+ {
303
+ existing.FilePath = report.FilePath;
304
+ existing.Line = report.Line;
305
+ }
306
+ }
307
+ }
308
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: f94fb4275c724821995abe36ce51046a
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant:
@@ -0,0 +1,110 @@
1
+ namespace DxMessaging.Editor.Analyzers
2
+ {
3
+ #if UNITY_EDITOR
4
+ using System;
5
+ using System.Collections.Generic;
6
+ using DxMessaging.Editor.Settings;
7
+ using DxMessaging.Unity;
8
+ using UnityEditor;
9
+
10
+ /// <summary>
11
+ /// Edit-time scanner that walks loaded <see cref="MessageAwareComponent"/> subclasses via
12
+ /// <see cref="TypeCache"/> and forwards them to the pure (Unity-API-free) classification
13
+ /// helper <see cref="BaseCallTypeScannerCore"/>. Replaces the lossy console-scraping bridge
14
+ /// as the inspector overlay's primary data source.
15
+ /// </summary>
16
+ /// <remarks>
17
+ /// <para>
18
+ /// <b>Why IL reflection?</b> Unity's <c>CompilationPipeline.assemblyCompilationFinished</c> and
19
+ /// the <c>LogEntries</c> console store are both downstream of Unity's decision to actually
20
+ /// surface analyzer warnings. On Bee/csc cache hits -- which happen on most domain reloads
21
+ /// after the first -- Unity skips that surface entirely, so the scrape returns nothing even
22
+ /// though the analyzer ran successfully on the first compile. By contrast, IL reflection over
23
+ /// loaded types is deterministic: the assemblies are in the AppDomain, the methods have IL
24
+ /// bodies, the same scan produces the same result on every reload regardless of whether the
25
+ /// build was a fresh compile or a Bee cache hit.
26
+ /// </para>
27
+ /// <para>
28
+ /// <b>What it detects:</b>
29
+ /// <list type="bullet">
30
+ /// <item><description>DXMSG006 -- overrides one of the five guarded methods but the IL body
31
+ /// lacks a <c>call</c>/<c>callvirt</c> to the parent's same-named method.</description></item>
32
+ /// <item><description>DXMSG007 -- declares the method with the <c>new</c> modifier (IL: name
33
+ /// shadows a base virtual but the descendant method itself is not in an override slot).</description></item>
34
+ /// <item><description>DXMSG009 -- declares the method without override or new -- same IL shape
35
+ /// as DXMSG007 (both compile to a non-virtual hide-by-sig method). The scanner cannot
36
+ /// distinguish the two perfectly from IL alone, so it conservatively classifies this case as
37
+ /// DXMSG007. The compile-time analyzer is authoritative for the precise ID classification;
38
+ /// the scanner's job is just to make sure the inspector overlay lights up.</description></item>
39
+ /// <item><description>DXMSG010 -- overrides correctly (calls base) but an intermediate
40
+ /// ancestor's override in the chain does NOT call base. Walks parent-by-parent and re-runs the
41
+ /// IL check at every link until the chain terminates at <see cref="MessageAwareComponent"/>
42
+ /// or hits a broken link.</description></item>
43
+ /// </list>
44
+ /// </para>
45
+ /// <para>
46
+ /// <b>Cross-assembly assume-clean:</b> ancestors whose IL is unavailable
47
+ /// (<see cref="System.Reflection.MethodBase.GetMethodBody"/> returns null -- e.g., abstract or
48
+ /// extern methods) are trusted. Emitting an unactionable warning against a closed-source
49
+ /// third-party library would be hostile.
50
+ /// </para>
51
+ /// <para>
52
+ /// <b>Implementation split:</b> the Unity-coupled work (<see cref="TypeCache"/> lookup,
53
+ /// <see cref="DxMessagingSettings"/> read, conversion to the Unity-serializable
54
+ /// <see cref="BaseCallReportEntry"/>) lives here; everything else (chain walk, IL probe,
55
+ /// FQN normalisation, opt-out handling) lives in <see cref="BaseCallTypeScannerCore"/> so the
56
+ /// dotnet-test project can cover the classification logic via Roslyn-compiled fixtures.
57
+ /// </para>
58
+ /// </remarks>
59
+ internal static class BaseCallTypeScanner
60
+ {
61
+ /// <summary>
62
+ /// Scan all loaded <see cref="MessageAwareComponent"/> subclasses and return a per-type
63
+ /// report keyed by fully-qualified type name. The report shape matches what the
64
+ /// console-bridge produced, so the inspector overlay code path needs no changes.
65
+ /// </summary>
66
+ /// <remarks>
67
+ /// Types opted out via <c>[DxIgnoreMissingBaseCall]</c> or via the project's ignored-types
68
+ /// list are intentionally NOT included in the returned dictionary -- the overlay reads the
69
+ /// project ignore list directly to render its "Stop ignoring" HelpBox, and the snapshot
70
+ /// semantics here match the bridge path (DXMSG008-equivalent rows were never present in
71
+ /// the snapshot's <c>missingBaseFor</c> either).
72
+ /// </remarks>
73
+ internal static Dictionary<string, BaseCallReportEntry> Scan(DxMessagingSettings settings)
74
+ {
75
+ // TypeCache is Unity's domain-reload-cached type lookup. Effectively O(1) after the
76
+ // first call and survives across reloads via Unity's serialization layer. Using
77
+ // TypeCache (rather than scanning every loaded assembly via AppDomain) is important
78
+ // for performance; a fresh project can have hundreds of assemblies loaded.
79
+ TypeCache.TypeCollection candidates =
80
+ TypeCache.GetTypesDerivedFrom<MessageAwareComponent>();
81
+
82
+ // Defensive: TypeCache.GetTypesDerivedFrom<T>() returns strict subclasses, but
83
+ // belt-and-braces in case a future Unity version changes the contract; we feed the
84
+ // list through Core.Scan which itself skips MessageAwareComponent by FQN match.
85
+ // The Core handles abstract / generic-definition / null-FQN skipping uniformly.
86
+ Dictionary<string, BaseCallTypeScannerCore.ScanEntry> coreResult =
87
+ BaseCallTypeScannerCore.Scan(
88
+ candidates,
89
+ settings != null ? settings._baseCallIgnoredTypes : null
90
+ );
91
+
92
+ Dictionary<string, BaseCallReportEntry> result = new(StringComparer.Ordinal);
93
+ foreach (KeyValuePair<string, BaseCallTypeScannerCore.ScanEntry> kvp in coreResult)
94
+ {
95
+ BaseCallTypeScannerCore.ScanEntry core = kvp.Value;
96
+ BaseCallReportEntry entry = new()
97
+ {
98
+ typeName = core.TypeName,
99
+ missingBaseFor = new List<string>(core.MissingBaseFor),
100
+ diagnosticIds = new List<string>(core.DiagnosticIds),
101
+ filePath = string.Empty,
102
+ line = 0,
103
+ };
104
+ result[kvp.Key] = entry;
105
+ }
106
+ return result;
107
+ }
108
+ }
109
+ #endif
110
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 58c96078f9224e208d973216c43884a9
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant: