com.wallstop-studios.dxmessaging 2.1.1 → 2.1.2
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.
- package/.github/workflows/dotnet-tests.yml +72 -0
- package/.lychee.toml +4 -2
- package/AGENTS.md +1 -0
- package/Docs/Comparisons.md +4 -4
- package/Docs/Install.md +2 -1
- package/Docs/Performance.md +13 -11
- package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +13 -2
- package/Editor/Analyzers/Microsoft.CodeAnalysis.dll +0 -0
- package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +11 -0
- package/Editor/Analyzers/System.Collections.Immutable.dll +0 -0
- package/Editor/Analyzers/System.Collections.Immutable.dll.meta +11 -0
- package/Editor/Analyzers/System.Reflection.Metadata.dll +0 -0
- package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +13 -2
- package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll +0 -0
- package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +11 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +3 -2
- package/Editor/AssemblyInfo.cs +3 -0
- package/Editor/AssemblyInfo.cs.meta +3 -0
- package/Editor/CustomEditors/MessagingComponentEditor.cs +21 -0
- package/Editor/SetupCscRsp.cs +133 -53
- package/Editor/Testing/MessagingComponentEditorHarness.cs +218 -0
- package/Editor/Testing/MessagingComponentEditorHarness.cs.meta +3 -0
- package/Editor/Testing.meta +3 -0
- package/README.md +9 -3
- package/Runtime/AssemblyInfo.cs +1 -0
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs +26 -11
- package/Runtime/Core/Extensions/MessageBusExtensions.cs +2 -2
- package/Runtime/Core/Extensions/MessageExtensions.cs +2 -2
- package/Runtime/Core/InstanceId.cs +5 -3
- package/Runtime/Core/MessageBus/MessageBus.cs +4 -4
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +2 -2
- package/Runtime/Core/MessageBus/MessagingRegistration.cs +3 -3
- package/Runtime/Core/MessageHandler.cs +34 -2
- package/Runtime/Core/MessageRegistrationToken.cs +2 -2
- package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs +2 -0
- package/Runtime/Unity/InitialGlobalMessageBusProvider.cs +2 -0
- package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs +2 -0
- package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs +2 -0
- package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs +2 -0
- package/Runtime/Unity/MessageAwareComponent.cs +2 -0
- package/Runtime/Unity/MessageBusProviderHandle.cs +4 -0
- package/Runtime/Unity/MessagingComponent.cs +16 -0
- package/Runtime/Unity/MessagingComponentInstaller.cs +2 -0
- package/Runtime/Unity/ScriptableMessageBusProvider.cs +2 -0
- package/SourceGenerators/Directory.Build.props +9 -0
- package/SourceGenerators/Directory.Build.props.meta +7 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +19 -24
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +87 -27
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +24 -4
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DocsSnippetCompilationTests.cs +193 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DocsSnippetCompilationTests.cs.meta +11 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxAutoConstructorGeneratorDiagnosticsTests.cs +69 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxAutoConstructorGeneratorDiagnosticsTests.cs.meta +11 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxMessageIdGeneratorDiagnosticsTests.cs +66 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/DxMessageIdGeneratorDiagnosticsTests.cs.meta +11 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/GeneratorTestUtilities.cs +155 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/GeneratorTestUtilities.cs.meta +11 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/WallstopStudios.DxMessaging.SourceGenerators.Tests.csproj +20 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests/WallstopStudios.DxMessaging.SourceGenerators.Tests.csproj.meta +7 -0
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.Tests.meta +8 -0
- package/Tests/Editor/MessagingComponentEditorHarnessTests.cs +243 -0
- package/Tests/Editor/MessagingComponentEditorHarnessTests.cs.meta +3 -0
- package/Tests/Editor/MessagingComponentSerializationTests.cs +129 -0
- package/Tests/Editor/MessagingComponentSerializationTests.cs.meta +3 -0
- package/Tests/Editor/WallstopStudios.DxMessaging.Tests.Editor.asmdef +19 -0
- package/Tests/Editor/WallstopStudios.DxMessaging.Tests.Editor.asmdef.meta +3 -0
- package/Tests/Editor.meta +3 -0
- package/Tests/Runtime/Benchmarks/BenchmarkSession.cs +3 -0
- package/Tests/Runtime/Benchmarks/BenchmarkTestBase.cs +3 -0
- package/Tests/Runtime/Benchmarks/ComparisonPerformanceTests.cs +3 -0
- package/Tests/Runtime/Benchmarks/PerformanceTests.cs +137 -0
- package/Tests/Runtime/Core/AlternateBusTests.cs +3 -0
- package/Tests/Runtime/Core/BroadcastTests.cs +3 -0
- package/Tests/Runtime/Core/CyclicBufferTests.cs +3 -0
- package/Tests/Runtime/Core/DefaultBusFallbackTests.cs +5 -2
- package/Tests/Runtime/Core/DiagnosticsTests.cs +3 -0
- package/Tests/Runtime/Core/EdgeCaseTests.cs +3 -0
- package/Tests/Runtime/Core/EnablementTests.cs +3 -0
- package/Tests/Runtime/Core/Extensions/MessageExtensionsProviderTests.cs +2 -2
- package/Tests/Runtime/Core/GenericMessageTests.cs +3 -0
- package/Tests/Runtime/Core/GlobalAcceptAllTests.cs +3 -0
- package/Tests/Runtime/Core/InterceptorCancellationTests.cs +3 -0
- package/Tests/Runtime/Core/LifecycleTests.cs +3 -0
- package/Tests/Runtime/Core/MessageEmissionDataTests.cs +70 -0
- package/Tests/Runtime/Core/MessageEmissionDataTests.cs.meta +11 -0
- package/Tests/Runtime/Core/MessagingComponentLifecycleTests.cs +3 -0
- package/Tests/Runtime/Core/MessagingTestBase.cs +3 -0
- package/Tests/Runtime/Core/MutationDedupeTests.cs +3 -0
- package/Tests/Runtime/Core/MutationDestructionTests.cs +3 -0
- package/Tests/Runtime/Core/MutationDuringEmissionTests.cs +3 -0
- package/Tests/Runtime/Core/MutationGlobalAddTests.cs +3 -0
- package/Tests/Runtime/Core/MutationInterceptorTests.cs +3 -0
- package/Tests/Runtime/Core/MutationPostProcessorAcrossHandlersTests.cs +3 -0
- package/Tests/Runtime/Core/MutationPostProcessorMoreTests.cs +3 -0
- package/Tests/Runtime/Core/MutationPriorityTests.cs +3 -0
- package/Tests/Runtime/Core/NominalTests.cs +3 -0
- package/Tests/Runtime/Core/OrderingTests.cs +3 -0
- package/Tests/Runtime/Core/OverDeregistrationTests.cs +3 -0
- package/Tests/Runtime/Core/PostProcessorTests.cs +3 -0
- package/Tests/Runtime/Core/ReflexiveErrorTests.cs +3 -0
- package/Tests/Runtime/Core/ReflexiveMessageWarningTests.cs +4 -1
- package/Tests/Runtime/Core/ReflexiveTests.cs +3 -0
- package/Tests/Runtime/Core/RegistrationTests.cs +3 -0
- package/Tests/Runtime/Core/StringShorthandTests.cs +3 -0
- package/Tests/Runtime/Core/TargetedTests.cs +3 -0
- package/Tests/Runtime/Core/TypedShorthandTests.cs +3 -0
- package/Tests/Runtime/Core/UntargetedEquivalenceTests.cs +3 -0
- package/Tests/Runtime/Core/UntargetedPrefreezeTests.cs +14 -78
- package/Tests/Runtime/Core/UntargetedTests.cs +3 -0
- package/Tests/Runtime/Integrations/Reflex/ReflexIntegrationTests.cs +4 -1
- package/Tests/Runtime/Integrations/VContainer/VContainerIntegrationTests.cs +3 -0
- package/Tests/Runtime/Integrations/Zenject/ZenjectIntegrationTests.cs +3 -0
- package/Tests/Runtime/Scripts/Components/GenericMessageAwareComponent.cs +3 -0
- package/Tests/Runtime/Scripts/Components/ManualListenerComponent.cs +3 -0
- package/Tests/Runtime/Scripts/Components/ReflexiveReceiverComponent.cs +3 -0
- package/Tests/Runtime/TestUtilities/UnityFixtureBase.cs +3 -0
- package/Tests/Runtime/Unity/MessageBusProviderAssetTests.cs +3 -0
- package/Tests/Runtime/Unity/MessageBusProviderHandleTests.cs +87 -3
- package/Tests/Runtime/Unity/MessagingComponentInstallerSceneTests.cs +109 -0
- package/Tests/Runtime/Unity/MessagingComponentInstallerSceneTests.cs.meta +11 -0
- package/Tests/Runtime/Unity/MessagingComponentProviderIntegrationTests.cs +159 -17
- package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.csproj +20 -7
- package/package.json +1 -1
|
@@ -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,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,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,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,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
|