com.wallstop-studios.dxmessaging 2.1.1 → 2.1.3

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 (158) hide show
  1. package/.github/workflows/dotnet-tests.yml +72 -0
  2. package/.lychee.toml +4 -2
  3. package/AGENTS.md +13 -12
  4. package/Docs/Comparisons.md +5 -5
  5. package/Docs/Install.md +2 -1
  6. package/Docs/InterceptorsAndOrdering.md +1 -1
  7. package/Docs/Performance.md +15 -13
  8. package/Docs/QuickReference.md +1 -1
  9. package/Docs/Reference.md +5 -5
  10. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  11. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +13 -2
  12. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll +0 -0
  13. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +11 -0
  14. package/Editor/Analyzers/System.Collections.Immutable.dll +0 -0
  15. package/Editor/Analyzers/System.Collections.Immutable.dll.meta +11 -0
  16. package/Editor/Analyzers/System.Reflection.Metadata.dll +0 -0
  17. package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +13 -2
  18. package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll +0 -0
  19. package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +11 -0
  20. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
  21. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +3 -2
  22. package/Editor/AssemblyInfo.cs +3 -0
  23. package/Editor/AssemblyInfo.cs.meta +3 -0
  24. package/Editor/CustomEditors/MessagingComponentEditor.cs +24 -0
  25. package/Editor/DxMessagingEditorInitializer.cs +58 -1
  26. package/Editor/DxMessagingMenu.cs +38 -0
  27. package/Editor/DxMessagingMenu.cs.meta +11 -0
  28. package/Editor/DxMessagingSceneBuildProcessor.cs +81 -0
  29. package/Editor/DxMessagingSceneBuildProcessor.cs.meta +11 -0
  30. package/Editor/Settings/DxMessagingSettings.cs +37 -6
  31. package/Editor/Settings/DxMessagingSettingsProvider.cs +45 -7
  32. package/Editor/SetupCscRsp.cs +133 -53
  33. package/Editor/Testing/MessagingComponentEditorHarness.cs +218 -0
  34. package/Editor/Testing/MessagingComponentEditorHarness.cs.meta +3 -0
  35. package/Editor/Testing.meta +3 -0
  36. package/README.md +10 -4
  37. package/Runtime/AssemblyInfo.cs +1 -0
  38. package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +52 -0
  39. package/Runtime/Core/DataStructure/CyclicBuffer.cs +16 -0
  40. package/Runtime/Core/Diagnostics/MessageEmissionData.cs +27 -12
  41. package/Runtime/Core/Diagnostics/MessageRegistrationType.cs +62 -0
  42. package/Runtime/Core/DxMessagingStaticState.cs +108 -0
  43. package/Runtime/Core/DxMessagingStaticState.cs.meta +11 -0
  44. package/Runtime/Core/Extensions/IListExtensions.cs +24 -0
  45. package/Runtime/Core/Extensions/MessageBusExtensions.cs +144 -2
  46. package/Runtime/Core/Extensions/MessageExtensions.cs +2 -2
  47. package/Runtime/Core/Helper/MessageCache.cs +16 -0
  48. package/Runtime/Core/Helper/MessageHelperIndexer.cs +77 -0
  49. package/Runtime/Core/InstanceId.cs +91 -3
  50. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs +31 -0
  51. package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +11 -0
  52. package/Runtime/Core/MessageBus/IMessageBus.cs +44 -16
  53. package/Runtime/Core/MessageBus/MessageBus.cs +96 -25
  54. package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +46 -2
  55. package/Runtime/Core/MessageBus/MessagingRegistration.cs +63 -5
  56. package/Runtime/Core/MessageBus/RegistrationLog.cs +10 -0
  57. package/Runtime/Core/MessageHandler.cs +141 -8
  58. package/Runtime/Core/MessageRegistrationHandle.cs +59 -0
  59. package/Runtime/Core/MessageRegistrationToken.cs +20 -4
  60. package/Runtime/Core/Messages/ReflexiveMessage.cs +38 -0
  61. package/Runtime/Core/MessagingDebug.cs +16 -1
  62. package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +6 -0
  63. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs +19 -0
  64. package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +11 -0
  65. package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +6 -0
  66. package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +19 -0
  67. package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +10 -0
  68. package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +14 -0
  69. package/Runtime/Unity/MessageAwareComponent.cs +2 -0
  70. package/Runtime/Unity/MessageBusProviderHandle.cs +4 -0
  71. package/Runtime/Unity/MessagingComponent.cs +109 -0
  72. package/Runtime/Unity/MessagingComponentInstaller.cs +2 -0
  73. package/Runtime/Unity/ScriptableMessageBusProvider.cs +2 -0
  74. package/Samples~/DI/README.md +13 -13
  75. package/Samples~/Mini Combat/README.md +15 -15
  76. package/Samples~/Mini Combat/Walkthrough.md +12 -12
  77. package/Samples~/UI Buttons + Inspector/README.md +4 -4
  78. package/SourceGenerators/Directory.Build.props +9 -0
  79. package/{Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj.meta → SourceGenerators/Directory.Build.props.meta} +1 -1
  80. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +23 -24
  81. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +91 -27
  82. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +24 -4
  83. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DocsSnippetCompilationTests.cs +193 -0
  84. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DocsSnippetCompilationTests.cs.meta +11 -0
  85. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxAutoConstructorGeneratorDiagnosticsTests.cs +69 -0
  86. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxAutoConstructorGeneratorDiagnosticsTests.cs.meta +11 -0
  87. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxMessageIdGeneratorDiagnosticsTests.cs +66 -0
  88. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxMessageIdGeneratorDiagnosticsTests.cs.meta +11 -0
  89. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/GeneratorTestUtilities.cs +155 -0
  90. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/GeneratorTestUtilities.cs.meta +11 -0
  91. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/WallstopStudios.DxMessaging.SourceGenerators.Tests.csproj +20 -0
  92. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/WallstopStudios.DxMessaging.SourceGenerators.Tests.csproj.meta +7 -0
  93. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests.meta +8 -0
  94. package/Tests/Editor/MessagingComponentEditorHarnessTests.cs +243 -0
  95. package/Tests/Editor/MessagingComponentEditorHarnessTests.cs.meta +3 -0
  96. package/Tests/Editor/MessagingComponentSerializationTests.cs +129 -0
  97. package/Tests/Editor/MessagingComponentSerializationTests.cs.meta +3 -0
  98. package/Tests/Editor/WallstopStudios.DxMessaging.Tests.Editor.asmdef +19 -0
  99. package/Tests/Editor/WallstopStudios.DxMessaging.Tests.Editor.asmdef.meta +3 -0
  100. package/Tests/Editor.meta +3 -0
  101. package/Tests/Runtime/Benchmarks/BenchmarkSession.cs +3 -0
  102. package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs +3 -0
  103. package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs +3 -0
  104. package/Tests/Runtime/Benchmarks/PerformanceTests.cs +137 -0
  105. package/Tests/Runtime/Core/AlternateBusTests.cs +3 -0
  106. package/Tests/Runtime/Core/BroadcastTests.cs +3 -0
  107. package/Tests/Runtime/Core/CyclicBufferTests.cs +3 -0
  108. package/Tests/Runtime/Core/DefaultBusFallbackTests.cs +5 -2
  109. package/Tests/Runtime/Core/DiagnosticsTests.cs +6 -3
  110. package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs +69 -0
  111. package/Tests/Runtime/Core/DxMessagingStaticStateTests.cs.meta +11 -0
  112. package/Tests/Runtime/Core/EdgeCaseTests.cs +3 -0
  113. package/Tests/Runtime/Core/EnablementTests.cs +3 -0
  114. package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs +2 -2
  115. package/Tests/Runtime/Core/GenericMessageTests.cs +3 -0
  116. package/Tests/Runtime/Core/GlobalAcceptAllTests.cs +3 -0
  117. package/Tests/Runtime/Core/InterceptorCancellationTests.cs +3 -0
  118. package/Tests/Runtime/Core/LifecycleTests.cs +3 -0
  119. package/Tests/Runtime/Core/MessageEmissionDataTests.cs +70 -0
  120. package/Tests/Runtime/Core/MessageEmissionDataTests.cs.meta +11 -0
  121. package/Tests/Runtime/Core/MessagingComponentLifecycleTests.cs +3 -0
  122. package/Tests/Runtime/Core/MessagingTestBase.cs +3 -0
  123. package/Tests/Runtime/Core/MutationDedupeTests.cs +3 -0
  124. package/Tests/Runtime/Core/MutationDestructionTests.cs +3 -0
  125. package/Tests/Runtime/Core/MutationDuringEmissionTests.cs +3 -0
  126. package/Tests/Runtime/Core/MutationGlobalAddTests.cs +3 -0
  127. package/Tests/Runtime/Core/MutationInterceptorTests.cs +3 -0
  128. package/Tests/Runtime/Core/MutationPostProcessorAcrossHandlersTests.cs +3 -0
  129. package/Tests/Runtime/Core/MutationPostProcessorMoreTests.cs +3 -0
  130. package/Tests/Runtime/Core/MutationPriorityTests.cs +3 -0
  131. package/Tests/Runtime/Core/NominalTests.cs +3 -0
  132. package/Tests/Runtime/Core/OrderingTests.cs +3 -0
  133. package/Tests/Runtime/Core/OverDeregistrationTests.cs +3 -0
  134. package/Tests/Runtime/Core/PostProcessorTests.cs +3 -0
  135. package/Tests/Runtime/Core/ReflexiveErrorTests.cs +3 -0
  136. package/Tests/Runtime/Core/ReflexiveMessageWarningTests.cs +4 -1
  137. package/Tests/Runtime/Core/ReflexiveTests.cs +3 -0
  138. package/Tests/Runtime/Core/RegistrationTests.cs +3 -0
  139. package/Tests/Runtime/Core/StringShorthandTests.cs +3 -0
  140. package/Tests/Runtime/Core/TargetedTests.cs +3 -0
  141. package/Tests/Runtime/Core/TypedShorthandTests.cs +3 -0
  142. package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +3 -0
  143. package/Tests/Runtime/Core/UntargetedPrefreezeTests.cs +14 -78
  144. package/Tests/Runtime/Core/UntargetedTests.cs +3 -0
  145. package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs +4 -1
  146. package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs +3 -0
  147. package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs +3 -0
  148. package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +3 -0
  149. package/Tests/Runtime/Scripts/Components/ManualListenerComponent.cs +3 -0
  150. package/Tests/Runtime/Scripts/Components/ReflexiveReceiverComponent.cs +3 -0
  151. package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs +3 -0
  152. package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs +3 -0
  153. package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs +87 -3
  154. package/Tests/Runtime/Unity/MessagingComponentInstallerSceneTests.cs +109 -0
  155. package/Tests/Runtime/Unity/MessagingComponentInstallerSceneTests.cs.meta +11 -0
  156. package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs +159 -17
  157. package/package.json +1 -1
  158. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +0 -7
@@ -0,0 +1,69 @@
1
+ using System.Linq;
2
+ using Microsoft.CodeAnalysis;
3
+ using NUnit.Framework;
4
+
5
+ namespace WallstopStudios.DxMessaging.SourceGenerators.Tests;
6
+
7
+ [TestFixture]
8
+ public sealed class DxAutoConstructorGeneratorDiagnosticsTests
9
+ {
10
+ [Test]
11
+ public void ReportsNonPartialContainingType()
12
+ {
13
+ string source = """
14
+ using DxMessaging.Core.Attributes;
15
+
16
+ namespace Sample;
17
+
18
+ public class Container
19
+ {
20
+ [DxAutoConstructor]
21
+ public readonly struct NestedMessage
22
+ {
23
+ public readonly int value;
24
+ }
25
+ }
26
+ """;
27
+
28
+ GeneratorDriverRunResult result = GeneratorTestUtilities.RunDxAutoConstructor(source);
29
+ Diagnostic[] diagnostics = result.Results[0].Diagnostics.ToArray();
30
+
31
+ Assert.That(
32
+ diagnostics,
33
+ Has.Some.Matches<Diagnostic>(d => d.Id == "DXMSG003"),
34
+ "DXMSG003 should be reported when nested types are not declared inside partial containers."
35
+ );
36
+ Assert.That(
37
+ diagnostics,
38
+ Has.Some.Matches<Diagnostic>(d => d.Id == "DXMSG004"),
39
+ "DXMSG004 should suggest adding the partial keyword for the containing type."
40
+ );
41
+ }
42
+
43
+ [Test]
44
+ public void ReportsInvalidOptionalDefaultExpression()
45
+ {
46
+ string source = """
47
+ using DxMessaging.Core.Attributes;
48
+
49
+ namespace Sample;
50
+
51
+ [DxTargetedMessage]
52
+ [DxAutoConstructor]
53
+ public readonly partial struct InvalidOptional
54
+ {
55
+ [DxOptionalParameter(Expression = "value > 0")]
56
+ public readonly int value;
57
+ }
58
+ """;
59
+
60
+ GeneratorDriverRunResult result = GeneratorTestUtilities.RunDxAutoConstructor(source);
61
+ Diagnostic[] diagnostics = result.Results[0].Diagnostics.ToArray();
62
+
63
+ Assert.That(
64
+ diagnostics,
65
+ Has.Some.Matches<Diagnostic>(d => d.Id == "DXMSG005"),
66
+ "DXMSG005 should be reported for optional defaults that cannot be parsed."
67
+ );
68
+ }
69
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: dd2be1f0fdeebd647a23bc68fb76438a
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,66 @@
1
+ using System.Linq;
2
+ using Microsoft.CodeAnalysis;
3
+ using NUnit.Framework;
4
+
5
+ namespace WallstopStudios.DxMessaging.SourceGenerators.Tests;
6
+
7
+ [TestFixture]
8
+ public sealed class DxMessageIdGeneratorDiagnosticsTests
9
+ {
10
+ [Test]
11
+ public void ReportsMultipleMessageAttributes()
12
+ {
13
+ string source = """
14
+ using DxMessaging.Core.Attributes;
15
+ using DxMessaging.Core.Messages;
16
+
17
+ namespace Sample;
18
+
19
+ [DxUntargetedMessage]
20
+ public readonly partial struct ConflictingMessage : IUntargetedMessage { }
21
+
22
+ [DxBroadcastMessage]
23
+ public readonly partial struct ConflictingMessage : IBroadcastMessage { }
24
+ """;
25
+
26
+ GeneratorDriverRunResult result = GeneratorTestUtilities.RunDxMessageId(source);
27
+ Diagnostic[] diagnostics = result.Results[0].Diagnostics.ToArray();
28
+
29
+ Assert.That(
30
+ diagnostics,
31
+ Has.Some.Matches<Diagnostic>(d => d.Id == "DXMSG002"),
32
+ "DXMSG002 should be reported when a message type has multiple Dx message attributes."
33
+ );
34
+ }
35
+
36
+ [Test]
37
+ public void ReportsNonPartialContainerForMessageIds()
38
+ {
39
+ string source = """
40
+ using DxMessaging.Core.Attributes;
41
+ using DxMessaging.Core.Messages;
42
+
43
+ namespace Sample;
44
+
45
+ public class Container
46
+ {
47
+ [DxTargetedMessage]
48
+ public readonly struct NestedMessage : ITargetedMessage { }
49
+ }
50
+ """;
51
+
52
+ GeneratorDriverRunResult result = GeneratorTestUtilities.RunDxMessageId(source);
53
+ Diagnostic[] diagnostics = result.Results[0].Diagnostics.ToArray();
54
+
55
+ Assert.That(
56
+ diagnostics,
57
+ Has.Some.Matches<Diagnostic>(d => d.Id == "DXMSG003"),
58
+ "DXMSG003 should be reported when a nested message type lives inside a non-partial container."
59
+ );
60
+ Assert.That(
61
+ diagnostics,
62
+ Has.Some.Matches<Diagnostic>(d => d.Id == "DXMSG004"),
63
+ "DXMSG004 should suggest adding the partial keyword for the containing type."
64
+ );
65
+ }
66
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: a35b9c3acace20b498c3f8797df94e08
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,155 @@
1
+ using System.Collections.Immutable;
2
+ using System.Reflection;
3
+ using Microsoft.CodeAnalysis;
4
+ using Microsoft.CodeAnalysis.CSharp;
5
+ using WallstopStudios.DxMessaging.SourceGenerators;
6
+
7
+ namespace WallstopStudios.DxMessaging.SourceGenerators.Tests;
8
+
9
+ internal static class GeneratorTestUtilities
10
+ {
11
+ private static readonly CSharpParseOptions ParseOptions = new(
12
+ languageVersion: LanguageVersion.Latest,
13
+ documentationMode: DocumentationMode.Diagnose
14
+ );
15
+
16
+ private static readonly ImmutableArray<MetadataReference> CoreReferences =
17
+ BuildCoreReferences();
18
+
19
+ internal static GeneratorDriverRunResult RunDxAutoConstructor(string userSource)
20
+ {
21
+ SyntaxTree attributeTree = CSharpSyntaxTree.ParseText(SharedStubs, ParseOptions);
22
+ SyntaxTree userTree = CSharpSyntaxTree.ParseText(userSource, ParseOptions);
23
+
24
+ CSharpCompilation compilation = CSharpCompilation.Create(
25
+ assemblyName: "GeneratorTests",
26
+ syntaxTrees: new[] { attributeTree, userTree },
27
+ references: CoreReferences,
28
+ options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
29
+ );
30
+
31
+ DxAutoConstructorGenerator generator = new();
32
+ GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);
33
+ driver = driver.RunGenerators(compilation);
34
+
35
+ return driver.GetRunResult();
36
+ }
37
+
38
+ internal static GeneratorDriverRunResult RunDxMessageId(string userSource)
39
+ {
40
+ SyntaxTree stubs = CSharpSyntaxTree.ParseText(SharedStubs, ParseOptions);
41
+ SyntaxTree userTree = CSharpSyntaxTree.ParseText(userSource, ParseOptions);
42
+
43
+ CSharpCompilation compilation = CSharpCompilation.Create(
44
+ assemblyName: "GeneratorTests",
45
+ syntaxTrees: new[] { stubs, userTree },
46
+ references: CoreReferences,
47
+ options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
48
+ );
49
+
50
+ DxMessageIdGenerator generator = new();
51
+ GeneratorDriver driver = CSharpGeneratorDriver.Create(generator);
52
+ driver = driver.RunGenerators(compilation);
53
+
54
+ return driver.GetRunResult();
55
+ }
56
+
57
+ internal static ImmutableArray<Diagnostic> CompileSnippet(string userSource)
58
+ {
59
+ SyntaxTree stubs = CSharpSyntaxTree.ParseText(SharedStubs, ParseOptions);
60
+ SyntaxTree userTree = CSharpSyntaxTree.ParseText(
61
+ userSource,
62
+ ParseOptions.WithKind(SourceCodeKind.Script)
63
+ );
64
+
65
+ CSharpCompilation compilation = CSharpCompilation.Create(
66
+ assemblyName: "SnippetCompilation",
67
+ syntaxTrees: new[] { stubs, userTree },
68
+ references: CoreReferences,
69
+ options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
70
+ );
71
+
72
+ return compilation.GetDiagnostics();
73
+ }
74
+
75
+ internal static ImmutableArray<Diagnostic> ParseSnippet(string userSource)
76
+ {
77
+ SyntaxTree userTree = CSharpSyntaxTree.ParseText(userSource, ParseOptions);
78
+ return userTree.GetDiagnostics().ToImmutableArray();
79
+ }
80
+
81
+ private static ImmutableArray<MetadataReference> BuildCoreReferences()
82
+ {
83
+ List<MetadataReference> references = new();
84
+
85
+ void AddAssembly(Assembly assembly)
86
+ {
87
+ string location = assembly.Location;
88
+ if (!string.IsNullOrEmpty(location))
89
+ {
90
+ references.Add(MetadataReference.CreateFromFile(location));
91
+ }
92
+ }
93
+
94
+ AddAssembly(typeof(object).Assembly);
95
+ AddAssembly(typeof(Attribute).Assembly);
96
+ AddAssembly(typeof(Enumerable).Assembly);
97
+ AddAssembly(typeof(List<>).Assembly);
98
+
99
+ return references.ToImmutableArray();
100
+ }
101
+
102
+ private const string SharedStubs = """
103
+ namespace DxMessaging.Core.Attributes
104
+ {
105
+ using System;
106
+
107
+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)]
108
+ public sealed class DxAutoConstructorAttribute : Attribute { }
109
+
110
+ [AttributeUsage(AttributeTargets.Field)]
111
+ public sealed class DxOptionalParameterAttribute : Attribute
112
+ {
113
+ public DxOptionalParameterAttribute() { }
114
+
115
+ public DxOptionalParameterAttribute(object _) { }
116
+
117
+ public string Expression { get; set; }
118
+ }
119
+
120
+ [AttributeUsage(AttributeTargets.Struct)]
121
+ public sealed class DxTargetedMessageAttribute : Attribute { }
122
+
123
+ [AttributeUsage(AttributeTargets.Struct)]
124
+ public sealed class DxUntargetedMessageAttribute : Attribute { }
125
+
126
+ [AttributeUsage(AttributeTargets.Struct)]
127
+ public sealed class DxBroadcastMessageAttribute : Attribute { }
128
+ }
129
+
130
+ namespace DxMessaging.Core
131
+ {
132
+ using System;
133
+
134
+ public interface IMessage
135
+ {
136
+ Type MessageType => GetType();
137
+ }
138
+ }
139
+
140
+ namespace DxMessaging.Core.Messages
141
+ {
142
+ public interface IUntargetedMessage { }
143
+ public interface ITargetedMessage { }
144
+ public interface IBroadcastMessage { }
145
+ }
146
+
147
+ namespace UnityEngine
148
+ {
149
+ public struct Color
150
+ {
151
+ public static readonly Color green = default;
152
+ }
153
+ }
154
+ """;
155
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: 0225395ecee3f7645a4ed16844a7e58f
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,20 @@
1
+ <Project Sdk="Microsoft.NET.Sdk">
2
+ <PropertyGroup>
3
+ <TargetFramework>net9.0</TargetFramework>
4
+ <ImplicitUsings>enable</ImplicitUsings>
5
+ <Nullable>enable</Nullable>
6
+ </PropertyGroup>
7
+ <ItemGroup>
8
+ <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
9
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
10
+ <PackageReference Include="NUnit" Version="4.4.0" />
11
+ <PackageReference Include="NUnit3TestAdapter" Version="5.2.0" />
12
+ <PackageReference Include="coverlet.collector" Version="6.0.4">
13
+ <PrivateAssets>all</PrivateAssets>
14
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
15
+ </PackageReference>
16
+ </ItemGroup>
17
+ <ItemGroup>
18
+ <ProjectReference Include="..\WallstopStudios.DxMessaging.SourceGenerators\WallstopStudios.DxMessaging.SourceGenerators.csproj" />
19
+ </ItemGroup>
20
+ </Project>
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: a0cddeeb40636ef4ea094e2e88926031
3
+ DefaultImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: 89c62acfc9f82784e900a467ff4d3be1
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -0,0 +1,243 @@
1
+ #if UNITY_EDITOR && UNITY_2021_3_OR_NEWER
2
+ namespace DxMessaging.Tests.Editor
3
+ {
4
+ using System.Collections.Generic;
5
+ using Core;
6
+ using Core.MessageBus;
7
+ using Core.Messages;
8
+ using DxMessaging.Editor.Testing;
9
+ using DxMessaging.Unity;
10
+ using NUnit.Framework;
11
+ using UnityEditor;
12
+ using UnityEngine;
13
+ using Object = UnityEngine.Object;
14
+
15
+ [TestFixture]
16
+ public sealed class MessagingComponentEditorHarnessTests
17
+ {
18
+ private readonly List<Object> _createdObjects = new();
19
+
20
+ [TearDown]
21
+ public void TearDown()
22
+ {
23
+ foreach (Object instance in _createdObjects)
24
+ {
25
+ if (instance != null)
26
+ {
27
+ Object.DestroyImmediate(instance);
28
+ }
29
+ }
30
+ _createdObjects.Clear();
31
+
32
+ if (MessageHandler.MessageBus is MessageBus messageBus)
33
+ {
34
+ messageBus.DiagnosticsMode = false;
35
+ messageBus._emissionBuffer.Clear();
36
+ }
37
+ }
38
+
39
+ [Test]
40
+ public void CaptureReflectsListenerDiagnostics()
41
+ {
42
+ GameObject host = CreateTrackedObject("HarnessHost");
43
+ MessagingComponent messagingComponent = host.AddComponent<MessagingComponent>();
44
+ TestListener listener = host.AddComponent<TestListener>();
45
+
46
+ MessageRegistrationToken token = messagingComponent.Create(listener);
47
+ token.DiagnosticMode = true;
48
+ token.RegisterUntargeted<TestHarnessMessage>(listener.OnMessage);
49
+ token.Enable();
50
+
51
+ MessageBus messageBus = MessageHandler.MessageBus as MessageBus;
52
+ Assert.That(
53
+ messageBus,
54
+ Is.Not.Null,
55
+ "Default message bus should be the DxMessaging MessageBus implementation."
56
+ );
57
+ messageBus.DiagnosticsMode = true;
58
+ messageBus._emissionBuffer.Clear();
59
+
60
+ try
61
+ {
62
+ TestHarnessMessage message = default;
63
+ MessageHandler.MessageBus.UntargetedBroadcast(ref message);
64
+
65
+ MessagingComponentInspectorState state = MessagingComponentEditorHarness.Capture(
66
+ messagingComponent
67
+ );
68
+
69
+ Assert.That(state.GlobalDiagnosticsEnabled, Is.True);
70
+ Assert.That(
71
+ state.GlobalEmissionHistory.Count,
72
+ Is.GreaterThan(0),
73
+ "Global emission buffer should contain recorded messages."
74
+ );
75
+ Assert.That(state.Listeners.Count, Is.EqualTo(1));
76
+
77
+ ListenerDiagnosticsView listenerView = state.Listeners[0];
78
+ Assert.That(listenerView.Listener, Is.EqualTo(listener));
79
+ Assert.That(listenerView.DiagnosticsEnabled, Is.True);
80
+ Assert.That(listenerView.TokenEnabled, Is.True);
81
+ Assert.That(listenerView.Registrations.Count, Is.EqualTo(1));
82
+ Assert.That(listenerView.Registrations[0].CallCount, Is.EqualTo(1));
83
+ Assert.That(listenerView.EmissionHistory.Count, Is.GreaterThan(0));
84
+ }
85
+ finally
86
+ {
87
+ token.Disable();
88
+ messageBus.DiagnosticsMode = false;
89
+ }
90
+ }
91
+
92
+ [Test]
93
+ public void AutoConfigureWithoutSerializedProviderEmitsWarning()
94
+ {
95
+ GameObject host = CreateTrackedObject("ProviderWarningHost");
96
+ MessagingComponent messagingComponent = host.AddComponent<MessagingComponent>();
97
+
98
+ SerializedObject serializedObject = new(messagingComponent);
99
+ SerializedProperty autoConfigureProperty = serializedObject.FindProperty(
100
+ "autoConfigureSerializedProviderOnAwake"
101
+ );
102
+ Assert.That(autoConfigureProperty, Is.Not.Null);
103
+ autoConfigureProperty.boolValue = true;
104
+ serializedObject.ApplyModifiedPropertiesWithoutUndo();
105
+
106
+ MessagingComponentInspectorState state = MessagingComponentEditorHarness.Capture(
107
+ messagingComponent
108
+ );
109
+
110
+ Assert.That(
111
+ state.ProviderDiagnostics.SerializedProviderMissingWarning,
112
+ Is.True,
113
+ "Inspector should warn when auto-configure is enabled without a serialized provider."
114
+ );
115
+ }
116
+
117
+ [Test]
118
+ public void AssignedSerializedProviderClearsWarning()
119
+ {
120
+ MessageBus messageBus = new();
121
+ TestScriptableMessageBusProvider provider = CreateTrackedObject(
122
+ ScriptableObject.CreateInstance<TestScriptableMessageBusProvider>()
123
+ );
124
+ provider.Configure(messageBus);
125
+
126
+ GameObject host = CreateTrackedObject("ProviderAssignedHost");
127
+ MessagingComponent messagingComponent = host.AddComponent<MessagingComponent>();
128
+ messagingComponent.Configure(
129
+ new MessageBusProviderHandle(provider),
130
+ MessageBusRebindMode.RebindActive
131
+ );
132
+
133
+ SerializedObject serializedObject = new(messagingComponent);
134
+ SerializedProperty autoConfigureProperty = serializedObject.FindProperty(
135
+ "autoConfigureSerializedProviderOnAwake"
136
+ );
137
+ Assert.That(autoConfigureProperty, Is.Not.Null);
138
+ autoConfigureProperty.boolValue = true;
139
+ serializedObject.ApplyModifiedPropertiesWithoutUndo();
140
+
141
+ MessagingComponentInspectorState state = MessagingComponentEditorHarness.Capture(
142
+ messagingComponent
143
+ );
144
+
145
+ Assert.That(
146
+ state.ProviderDiagnostics.SerializedProviderMissingWarning,
147
+ Is.False,
148
+ "Inspector warning should clear when a serialized provider is assigned."
149
+ );
150
+ Assert.That(
151
+ state.ProviderDiagnostics.SerializedProviderNullBusWarning,
152
+ Is.False,
153
+ "Provider should resolve a message bus without triggering the null-bus warning."
154
+ );
155
+ }
156
+
157
+ [Test]
158
+ public void NullResolvingSerializedProviderEmitsWarning()
159
+ {
160
+ GameObject host = CreateTrackedObject("NullProviderHost");
161
+ MessagingComponent messagingComponent = host.AddComponent<MessagingComponent>();
162
+
163
+ NullBusProvider provider = CreateTrackedObject(
164
+ ScriptableObject.CreateInstance<NullBusProvider>()
165
+ );
166
+ messagingComponent.Configure(
167
+ new MessageBusProviderHandle(provider),
168
+ MessageBusRebindMode.RebindActive
169
+ );
170
+
171
+ SerializedObject serializedObject = new(messagingComponent);
172
+ SerializedProperty autoConfigureProperty = serializedObject.FindProperty(
173
+ "autoConfigureSerializedProviderOnAwake"
174
+ );
175
+ Assert.That(autoConfigureProperty, Is.Not.Null);
176
+ autoConfigureProperty.boolValue = true;
177
+ serializedObject.ApplyModifiedPropertiesWithoutUndo();
178
+
179
+ MessagingComponentInspectorState state = MessagingComponentEditorHarness.Capture(
180
+ messagingComponent
181
+ );
182
+
183
+ Assert.That(
184
+ state.ProviderDiagnostics.SerializedProviderMissingWarning,
185
+ Is.False,
186
+ "Warning should not claim the provider asset is missing when assigned."
187
+ );
188
+ Assert.That(
189
+ state.ProviderDiagnostics.SerializedProviderNullBusWarning,
190
+ Is.True,
191
+ "Inspector should warn when the serialized provider does not resolve a message bus."
192
+ );
193
+ }
194
+
195
+ private GameObject CreateTrackedObject(string name)
196
+ {
197
+ GameObject gameObject = new(name);
198
+ _createdObjects.Add(gameObject);
199
+ return gameObject;
200
+ }
201
+
202
+ private T CreateTrackedObject<T>(T unityObject)
203
+ where T : Object
204
+ {
205
+ if (unityObject != null)
206
+ {
207
+ _createdObjects.Add(unityObject);
208
+ }
209
+ return unityObject;
210
+ }
211
+
212
+ private sealed class TestListener : MonoBehaviour
213
+ {
214
+ public void OnMessage(ref TestHarnessMessage message) { }
215
+ }
216
+
217
+ private readonly struct TestHarnessMessage : IUntargetedMessage { }
218
+
219
+ private sealed class TestScriptableMessageBusProvider : ScriptableMessageBusProvider
220
+ {
221
+ private IMessageBus _bus;
222
+
223
+ public void Configure(IMessageBus bus)
224
+ {
225
+ _bus = bus;
226
+ }
227
+
228
+ public override IMessageBus Resolve()
229
+ {
230
+ return _bus;
231
+ }
232
+ }
233
+
234
+ private sealed class NullBusProvider : ScriptableMessageBusProvider
235
+ {
236
+ public override IMessageBus Resolve()
237
+ {
238
+ return null;
239
+ }
240
+ }
241
+ }
242
+ }
243
+ #endif
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 621c12482fb44fbd906e939ce72facb6
3
+ timeCreated: 1761880591